类加载

类加载的时机                                    

(1)遇到new, getstatic, putstatic或invokestatic这4条字节码指令时,如果类没有进行初始化,则需要先触发初始化。

这4条指令的最常见场景是:使用new关键字实例化对象、读取一个类的静态字段(非final)、设置一个类的静态字段(非final)

、调用一个类的静态方法。  上述非final的原因是final static修饰的字段在类加载的准备阶段会完成初始化。

(2)使用reflect包的反射方法对类进行反射调用的时候,若类没有初始化,则会先触发类的初始化。

(3)当初始化一个类的时候,若父类没有进行过初始化,则会先触发父类初始化。

(4)当虚拟机启动的时候,用户需要指定一个入口类(主类),虚拟机会先触发这个主类的初始化。

(5)如果一个java.lang.invoke.MethodHandler实例最后的解析结果是REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,并且该方法句柄对应的类没有进行过初始化,则需要先触发方法句柄对应的类的初始化。

类加载的加载阶段

(1)加载是类加载的第一个阶段。此阶段主要完成三件事情。

①通过一个类的全限定名,获取此类的二进制字节流。

②将这个二进制字节流,所代表的静态存储结构,转化为方法区的运行时数据结构。

③在内存中生成一个代表这个类的java.lang.Class对象,作为方法区的这个类的各种数据访问入口。

(2)上述通过类的全限定名获取此类的二进制字节流,并没有指定从哪获取,怎么获取;

①从zip包里获取,例如jar、war等。

②从网络中获取,例如Applet。

③运算时动态生成,例如动态代理,在java.lang.reflect.Proxy中,就是用了ProxyGenerator.generateProxyClass来为特定的接口生成形式为“*Proxy”的代理类的二进制字节流。

(3)数组类不通过类加载器创建,而是jvm直接创建。

类加载的验证阶段;

(1)文件格式验证;

(2)元数据验证;

(3)字节码验证;

(4)符号引用验证;

类加载的准备阶段;

(1)类加载的准备阶段,是正式为类变量分配内存,并设置初始值的阶段。这些类变量所使用的内存都在方法区中分配。

备注:类加载的准备阶段进行内存分配的变量,只有类变量(被static修饰的变量),而实例变量是在对象初始化的时候,随着对象一起分配在堆里面。

A:static final int value = 123;编译时,javac将会为value生成ConstantValue属性,在类加载的准备阶段,jvm根据ConstantValue属性,将Value在方法区分配内存空间,并赋值为123;

B:static int value = 234;在类加载的准备阶段,将value在方法区分配内存空间,并赋零值(0);

 

 

 

 

 

                                                                                                                                          -----------摘自《深入理解Java虚拟机》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值