想必大家都知道JVM,Java没了它,就跟人没了空气一样难受。那大家知道JVM怎么跟平时的Java类文件关联起来的呢,
学过Java的人都知道,Java是一种与平台无关的语言,“一次编译,到处运行”,注意,运行是指运行编译之后的class字节码文件,而
JVM可以理解为是一个虚拟的计算机,它载入class字节码文件,将它解释成具体平台例如linux,windows所能理解的语言
那class文件是怎么被JVM加载进去的呢?晚饭自己随便copy编写的class文件能被加载解释吗?
大家看看《深入理解java虚拟机》是怎么解释类被JVM加载的过程的
类从被加载到虚拟机内存开始,到卸载出内存为止,它的整个生命周期包括:加载、验证、准备、解析、初始化、使用、卸载7个阶段
用一张图来简单说明,就清楚大致流程了
晚饭今天只讲解JVM如何加载class文件的,所以只讲解前五个阶段,也可以合并成前三个阶段,那就是
加载、连接(验证、准备、解释)、初始化
加载,晚饭也理解为“装载”,装载就是找到对应的class字节码文件,读入到JVM
OK,怎么读入的呢?大家对Class.forName(“className”) 这个方法不陌生吧,顾名思义,该方法是通过类的全限定名来获取的,获取之后会在内存中生成一个该类的对象。这时候加载完成,让我们来细看这个转变的过程
1.通过该类的全限定名来该类的二进制流
2.方法区生成该二进制流代表的各种数据结构
3.内存生成该类的对象,作为方法区该类各种数据结构的外部接口
好了,可能有人会疑惑了,是谁将class字节码文件装入到JVM中的?答案是类加载器,而类加载器有系统提供的,也可以自定义类加载器,小伙伴可以思考一下类加载器是怎么加载class文件的,晚饭在以后的文章将会详细的讲解这一部分
内存中已经生成了该class对象了,能直接用了吗?额,当然不行,理由就是
1.没验证此字节码文件是不是合法的
2.还没有为对象里的各种变量分配内存
3.需要根据类中的符号引用转换成直接引用
简单的理解为,内存分配对象了,而要用这个对象,就得先连接,连接又分为三部分:验证、准备、解析,分别对应以上三个理由
这是一个非常重要的阶段,为了确保解字节码中的信息符合JVM的要去,并且不会危害JVM自身的安全
我们知道,Java是一个相对于c,c++比较安全的语言,就是因为JVM会检查输入的class文件,而class文件是以十六进制表示的,人工都可以编写,如果JVM不验证class文件的正确性的话,载入有害攻击性的字节流将会导致崩溃,因此,晚饭自己随便copy编写的class文件是不可以被解析的,验证阶段就被kill了
验证阶段从整体上看,又分为
文件格式验证、元数据验证、字节码验证、符号引用验证
要是感兴趣的话,可以自己继续深究哦~
准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些变量所使用的内存都在方法区中进行分配
这里大家要分清楚类变量(被static修饰的变量)和实例变量的区别,假如你定义了一个类变量
public static int static_value =123;
和一个实例变量
private int instance_value =123;
那么在准备阶段过后static_value的值是0,而instance_value的值要在对象实例化时随对象一起分配,这里不作深究。
大家别误以为解析阶段只是简单的讲一个对象的符号引用指向另一个对象而已,解析针对了7类符号引用
类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符
看晕了吧,没关系,只要稍微知道这是一个将符号引用找到对应的对象就可以啦,而这个对象可以是以上其中七种中的任意一种
啊,终于来到初始化了,类加载过程的最后一步。一个简简单单写的类要经过这么多麻烦的步骤,晚饭还极大的精简了其中的过程。
前面我们提到过的static_value在准备阶段被赋值为0,而在初始化阶段类会执行构造器的
()方法,这个时候,static_value才会被赋值为123
从没见过
好啦,JVM加载class文件就到这里了啊,有什么疑问可以发我邮箱!~
晚饭邮箱:[email protected]
欢迎关注,微信公众号,获取最新文章