JVM如何加载类?
官方文档根据官方文档:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html
一、类加载步骤
可以看出类加载到JVM包含三步:类加载(Loading)、链接(Linking)、初始化(Initalizing)
类加载步骤
-
加载(Loading)
- 找到 Class文件所在的位置
- Class文件的信息写入JVM方法区(method area)中
类文件信息包含:类的版本、字段、方法、接口描述等 - 通过Class文件所生成的对象,放入JVM堆(heap)中
-
链接(Linking)
-
验证(Verification)
验证Class文件的正确,符合JVM的要求 -
准备(Preparation)
为类变量分配内存空间并设置变量类型的默认值。public static int a=10;
准备阶段下 a的值为int类型的默认值0。
注:final 修饰的变量,直接设置为初始化的值。public static final int b=10;
准备阶段下 b的值为初始化的值10。
-
解析(Resolution)
将常量池中的符号引用转换为直接引用
-
-
初始化(Initialization)
为链接的准备阶段中的静态变量初始化值,此时a设置初始值10。
至此,类如何加到JVM中其实已经结束,但是我们能不能发散我们的思维,来达到最大的记忆效果呢?
比如
1、类加载时是通过什么机制去加载的?
2、类加载我们了解到类是放置到了JVM的运行时数据区中,如:方法区、堆。
那么运行时数据区是怎样划分的呢?
3、什么情况下JVM不会执行类的初始化流程呢?
二、类加载机制(双亲委派)
双亲委派- CustomClassLoader,判断是否已经加载,已经加载则返回,没有加载则委托给父类AppClassLoader
- AppClassLoader,判断是否已经加载,已经加载则返回,没有加载则委托给父类ExtClassLoader
- ExtClassLoader,判断是否已经加载,已经加载则返回,没有加载则委托给父类BootstrapClassLoader
- BootstrapClassLoader判断是否已经加载,已经加载则返回,没有加载则查到加载路径下是否有Class文件,有则进行加载,没有则通知ExtClassLoader进行加载
……
如果最后没有找到类,会抛出ClassNotFound异常
双亲委派机制的核心就是保障类的唯一性和安全性
三、JVM运行时数据区
运行时数据区运行时数据区中的知识点太多了,如:新生代、老年代、垃圾回收、回收算法……就不在本篇中详解了
四、什么情况下JVM不会执行类的初始化
- 子类引用父类的静态字段时,不会触发子类的初始化,只会触发父类的初始化
- 定义对象数组,不会触发该类的初始化
- 在使用类名获取Class对象时不会触发类的初始化
- 在使用Class.forName加载指定的类时,可通过initialize参数设置是否需要对类进行初始化
面对每一道题目,要学会把自己的思维发散出去。每一篇文章只当自己对知识的总结!
网友评论