安溪住房和城乡规划建设局网站,响应式网站代码规范,成都美誉网站设计,12306网站多少钱做的Java中的字节码#xff1a;Java源代码经过虚拟机编译器编译后产生的文件#xff08;即扩展为.class的文件#xff09;#xff0c;它不面向任何特定的处理器#xff0c;只面向虚拟机。
1.反射的定义
反射机制
JAVA反射机制是在运行状态中#xff0c;对于任意一个类Java源代码经过虚拟机编译器编译后产生的文件即扩展为.class的文件它不面向任何特定的处理器只面向虚拟机。
1.反射的定义
反射机制
JAVA反射机制是在运行状态中对于任意一个类都能够知道这个类的所有属性和方法对于任意一个对象都能够调用它的任意一个方法和属性这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。 要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
什么是反射
反射就是把java类中的各种成分映射成一个个的Java对象
2.Class类
Class 类的实例表示正在运行的 Java 应用程序中的类和接口。也就是jvm中有N多的实例每个类都有该Class对象。包括基本数据类型 Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的defineClass 方法自动构造的。也就是这不需要我们自己去处理创建JVM已经帮我们创建好了
(具体可查看源码或查看Java api详解)
所有类型的Class对象 Class c1 Object.class; //类Class c2 Comparable.class; //接口Class c3 String.class; //一维数组Class c4 int[][].class; //二维数组Class c5 Override.class; //注解Class c6 ElementType.class; //枚举Class c7 Integer.class; //基本数据类型Class c8 void.class; //voidClass c9 Class.class; //Class//只要元素类型与维度一致就是同一个Classint[] a new int[10];int[] b new int[100];int[][] c new int[10][10];System.out.println(a.getClass().hashCode());System.out.println(b.getClass().hashCode());System.out.println(c.getClass().hashCode());
3.获取反射对象Class五种方式
通过Object类的方法getClass()继承给所有子类任何数据类型都有静态的class属性通过Class类的静态方法:forName(String className)基本内置类型的包装类都有一个Type属性通过子类Class找到父类Class
4.类的加载内存分析
加载
加载是指Java虚拟机查找字节流查找.class文件并且根据字节流创建java.lang.Class对象的过程。这个过程将类的.class文件中的二进制数据读入内存放在运行时区域的方法区内。然后在堆中创建java.lang.Class对象用来封装类在方法区的数据结构。
类加载阶段
1Java虚拟机将.class文件读入内存并为之创建一个Class对象。
2任何类被使用时系统都会为其创建一个且仅有一个Class对象。
3这个Class对象描述了这个类创建出来的对象的所有信息比如有哪些构造方法都有哪些成员方法都有哪些成员变量等。
链接
链接包括验证、准备以及解析三个阶段。
1验证阶段。主要的目的是确保被加载的类.class文件的字节流满足Java虚拟机规范不会造成安全错误。
2准备阶段。负责为类的静态成员分配内存并设置默认初始值。
3解析阶段。将类的二进制数据中的符号引用替换为直接引用。
初始化
初始化则是为标记为常量值的字段赋值的过程。换句话说只对static修饰的变量或语句块进行初始化。
如果初始化一个类的时候其父类尚未初始化则优先初始化其父类。
如果同时包含多个静态变量和静态代码块则按照自上而下的顺序依次执行。
具体说法如下
执行类构造器clinit()方法的过程。类构造器clinit()方法是由编译期自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的。(类构造器是构造类信息的不是构造该类对象的构造器)。
当初始化一个类的时候如果发现其父类还没有进行初始化则需要先触发其父类的初始化虚拟机会保证一个类的clinit()方法在多线程环境中被正确加锁和同步。
虚拟机会保证一个类的clinit()方法在多线程环境中被正确加锁和同步。 public class test03 {public static void main(String[] args) {A a new A();System.out.println(a.m);}/*1.加载到内存会产生一个类对应的Class对象2.链接结束后 m 0;3.初始化clinit() {System.out.println(A类静态代码块初始化);m 300;m 100;}m 100;*/
}
class A {static {System.out.println(A类静态代码块初始化);m 300;}static int m 100;public A() {System.out.println(A类无参构造初始化);}
}
5.分析类初始化
类的主动引用(一定会发生初始化) 当虚拟机启动先初始化main方法所在的类 new一个类的对象 调用类的静态成员(除了final常量)和静态方法 使用java,lang.reflect包的方法对类进行反射调用 当初始化一个类如果其父类未被初始化则先会初始化其父类
类的被动引用(不会发生类的初始化)
当访问一个静态域时只有真正声明这个域的类才会被初始化。如当通过子类引用父类的静态变量不会导致子类的初始化通过数组定义引用不会出发此类的初始化引用常量不会触发此类的初始化(常量在链接阶段就存入调用类的常量池中)
public class test04 {static {System.out.println(Main类被加载);}public static void main(String[] args) throws ClassNotFoundException {//1.主动引用Son son new Son();//反射也会产生主动引用Class.forName(cn.com.reflection.Son);//不会产生类的引用的方法//子类引用父类的值System.out.println(Son.n);//数组只是开辟一个内存空间也不会初始化Son[] a new Son[5];//引用常量也不会初始化System.out.println(Son.M);}
}
class Father {static int n 2;static {System.out.println(父类被加载);}
}
class Son extends Father {static {System.out.println(子类被加载);m 300;}static int m 100;static final int M 1;
}
6.类加载器
类加载器作用是用来把类(class)装载进内存的。JVM规范定义了如下类型的类加载器。
系统类加载器
负责java-classpath或-d java.class.path所指的目录下的类与jar包装入工作库是最常用的加载器。
扩展类加载器
负责jre/lib/ext或-d java.ext.dirs所指的目录下的类与jar包装入工作库
引导类加载器(根加载器)
用c编写的是jvm自带的类加载器负责Java平台核心库用来装载核心类库。该加载器无法直接获取。
各加载器关系
自定义加载器—System Classloader—Extension Classloader—Bootstap Classloader(从左至右对应从底到顶) 自底向上检查类是否已装载 自顶向底尝试加载类
双亲委派机制
自顶向底尝试加载类时会检查是否存在了该类的包如果已存在就不会向下加载子类的包。 双亲委派机制保证了安全性。避免创建一些如Java核心类库中同样的命名。