JVM中加载类的整个过程
JVM中加载类的整个过程
陶邦仁 发表于6年前
JVM中加载类的整个过程
  • 发表于 6年前
  • 阅读 3170
  • 收藏 14
  • 点赞 2
  • 评论 0

移动开发云端新模式探索实践 >>>   

一、JVM中类的整个生命周期如下

JvmDllRun

加载=》验证=》准备=》解析=》初始化=》使用=》卸载
  
1、加载

类的加载阶段,主要是获取定义此类的二进制字节流,并将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构,最后在Java堆中生成一个代表这个类的java.lang.Class对象作为方法区这些数据的访问入口。相对于类加载过程的其他阶段,加载阶段是开发期可控性最强的阶段。我们可以通过定制不通的类加载器,也就是ClassLoader来控制二进制字节流的获取方式。

2、验证

验证,准备和解析其实都属于连接阶段,而验证就是连接阶段的第一步。这一阶段主要是为了确保Class文件的字节流中包含的信息复合当前虚拟机的要求,并且不会危害虚拟机自身的安全。主要验证过程包括:文件格式验证,元数据验证,字节码验证以及符号引用验证。
  
3、准备

准备阶段正式为类变量分配内存并设置初始值。这里的初始值并不是初始化的值,而是数据类型的默认零值。这里提到的类变量是被static修饰的变量,而不是实例变量。关于准备阶段为类变量设置零值的唯一例外就是当这个类变量同时也被final修饰,那么在编译时,就会直接为这个常量赋上目标值。

4、解析

解析时虚拟机将常量池中的符号引用替换为直接引用的过程。

5、初始化

在准备阶段,变量已经赋过一次系统要求的初始值,在初始化阶段,则是根据程序员通过程序的主观计划区初始化类变量和其他资源。Java虚拟机规范规定了有4种情况必须立即对类进行初始化(加载,验证,准备必须在此之前完成)
1)当使用new关键字实例化对象时,当读取或者设置一个类的静态字段(被final修饰的除外)时,以及当调用一个类的静态方法时,如果类未初始化,则需先初始化。
2)通过反射机制对类进行调用时,如果类未初始化,则需先初始化。
3)当初始化一个类时,如果其父类未初始化,先初始化父类。
4)用户指定的执行主类(含main方法的那个类)在虚拟机启动时会先被初始化。

除了上面这4种方式,所有引用类的方式都不会触发初始化,称为被动引用。如:通过子类引用父类的静态字段,不会导致子类初始化;通过数组定义来引用类,不会触发此类的初始化;引用类的静态常量不会触发定义常量的类的初始化,因为常量在编译阶段已经被放到常量池中了。

6、总结

在上述5个过程当中,验证,准备和解析完全由Java虚拟机主导和控制。只有加载阶段和初始化阶段程序员可以进行控制。在加载阶段可以通过实现自定义的ClassLoader来加载类的二进制流,在初始化阶段程序员则可完全按照需求来为类变量赋值。

二、执行java XXX.class的过程
 
找到JRE——》找到jvm.dll——》启动JVM并进行初始化——》产生Bootstrap Loader——》载入ExtClassLoader——》载入AppClassLoader——》执行java XXX.class

标签: jvm 加载 过程 分析
  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
粉丝 1544
博文 388
码字总数 1483822
×
陶邦仁
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: