求解java反射问题

求da lao 解惑,java反射获取Class对象,一般有3个方法,forname(),.class,getclass();forname底层是用getclassloader加载器去先加载成class对象,再去获取,是这样吗?那.class是在哪个阶段获取class对象的呢?最好有实列证明,先给da lao磕头了

.class对象是在类加载的时候创建的。类加载的步骤有:加载(这里生成class对象),验证,准备,解析,初始化(执行构造函数)

.class 是类的字面常量;跟 String s = "abc" 中,abc是String类型的常量一样, Class< A > a = A.class 就是Class的常量

1加载阶段

JVM 在该阶段的主要目的是将字节码从不同的数据源(可能是class 文件 ,也可能是 jar包,甚至网络)转化成二进制字节流加载到内存中,并生成一个代表该类的java.lang.Class 对象

2.1)连接阶段 -验证

1 目的是为了确保Class 文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全

2包括:文件格式验证(是否以魔数 oxcafebabe开头),元数据验证、字节码验证、符号引用验证

3可以考虑使用 -Xverify:none 参数来关闭大部分的类验证措施,缩短虚拟墙类加载的时间

2.2)连接阶段 - 准备

JVM会在该阶段对静态变量,分配内存 并默认初始化(对应数据类型的默认初始值 ,如:0、0L、null、false等)。这些变量所使用的内存都健在方法区中进行分配

2.3)连接阶段 - 解析

虚拟机将常量池的符号引用替换为直接引用的过程

lnitalization (初始化)

1 到初始化阶段,才真正开始执行类中定义分java程序代码,此阶段是执行clinit()方法的过程

2 clinit()方法是由编译器按语句在源文件出现的顺序,依次自动收集类中的所有静态变量的赋值动作和静态代码块的语句,并进行合并

3 虚拟机会保证一个类的clinit()方法在多线程环境中被正确地加锁、同步如果多个线程同时去初始化一个类,那么只会有一个线程去执行这个类的clinit()方法,其他线程都需要阻塞等待,直到活动线程执行clinit()方法完毕

forName加载类,本质上与import导入类没什么区别,主要是方便配置,最典型的就是加载数据库的驱动程序。