JVM类加载机制

看了大量文档和相关周志明老师的《深入理解Java虚拟机》其中的第七章虚拟机类加载机制,或者纯洁的微笑知乎的jvm理解知识也不错,下面是我的一些笔记

1、首先了解下Java为什么要进行编译

       计算机只认识二进制的数据,例如0和1的数据,所以编译就是把Java高级语言变成计算机可以识别的二进制语言,编译后的文件就是.class文件。

2、编译后由于我们要使用所以就会涉及到类加载,类加载的本质:是将编译后的.class类加载到jvm虚拟机中并且为其分配内存,类加载如下图所示 (我建议你在图形画布中 画一次非常好记,也有助于你理解每一个过程)

JVM类加载机制_第1张图片

1)加载阶段(本质文件到内存)

        加载分为三个阶段,首先通过路径的位置找到刚才编译好的,然后是将二进制转为标准的Java语言,最后就是给加载到内存中并分配空间。

        (1)将这个类通过class.forname找到这个类的全限定名称,其实就是要找到这个类所在的位置。

        (2)将二进制转为Java语言,打开二进制只是计算机识别的,实际要使用的时候需要将二进制转为Java规范的语言。

        (3)再堆内存中创建一个.class对象,堆的本质是在内存空间中所有对象存放的一个地址,类似于我们有一些需求是指定放到指定对应版本的文件夹下一个意思。

2)连接阶段

        a、验证阶段

                该阶段主要是为了验证Java内部的语法的正确性,以及是否符合虚拟机规范。        

                1、文件格式的验证

                        验证点有如下几个点

                                是否已魔数0xCAFEBABE开头

                                主、次版本号是否在处理范围内

                                常量池的常量是否与不被支持的常量类型...                 

                2、元数据验证

                               这个类是否有父类(除object之外的类)

                               这个类的父类是否集成不允许被继承的类

                               如果是抽象类是否实现了所有的方法...

                3、字节码验证

                        保证跳转指令不会跳转到方法体以外的字节码指令上

                          ......

                4、符号引用验证

                         符号引用中通过字符串描述的全限定名是否能找到对应的类

                         符号引用中的类、字段的访问性(private、protected、public、defalut)是否可被当前访问

                          .....

         b、准备阶段 ->类变量内存          

                 正式为类变量分配内存并设置类变量初始值的阶段。             

                 例如:public  static int value = 12345; 则在准备阶段就是为value初始化即为0 而不是12345赋值操作,因为在该阶段没有使用任何的Java方法,而赋值操作真正的是在初始化阶段开始的。

        c、解析阶段

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

                1)  类和接口的解析

                2)字段的解析

                3)类方法解析

                4)接口方法的解析

          d、初始化->静态块、静态变量

                  除了在加载过程中用户可以通过自定义类加载器去参与以外,其他阶段都是虚拟机托管去主导和控制的,到了初始化阶段才真正的开始执行类中的Java程序,例如自定的static块。

         e、使用(jvm的生命周期)

                使用主要是为了做实例化。

        f、卸载(jvm的生命周期)

                Gc回收、注意只有用户自定的类会被回收

3、一个Java类中在具体的jvm内存中都存了写什么(内存分配)

        1)堆内存:用于存储对象实例和数组。在堆内存中分配对象时,Java会动态地为其分配内存空间。

        2)栈内存:每个线程都有自己的栈,用于存储局部变量、方法调用和部分结果。栈内存包含方法调用的执行信息,每个方法调用都会在栈中创建一个栈帧。

        如图所示:

        JVM类加载机制_第2张图片

        线程共享区域主要有:堆(heap)、方法区(Method Area) 

        线程独享区域主要有:栈(stack)、本地方法栈(Native Method Stack)、程序计数栈

        

你可能感兴趣的:(Java进阶,jvm)