jvm学习 类的加载过程

一.类的加载时机
编译好的类-二进制文件(class文件)在以下情况会被加载进入内存。
1)遇到new getstatic ,putstatic 或invokestatic这四条字节码指令的是时候。
*使用new关键字实例化对象的时候。
*读取或设置一个类型的静态字段)(被final修饰.已在编译器吧结果放入常量池的静态字段除外)的时候。
2)使用java.lang.reflect包的方法对类型进行反射调用的时候,如果类型没有进行过初始化,则需要先出法其初始化。
3)当初始化类的时候,如果发现父类还没有进行过初始化,则需要先出发其父类的初始化。
4)虚拟机启动时,用户指定执行的主类(包含main()方法的那个类),虚拟机启动会县初始化这个类。
5)jdk7新加入的动态语言支持,jvava.lang.invoke,MethodHandle实例最后的解析结果为REF_getStatic,REF_putStatic,REF_invokeStatic,REF_newInvokeSpecial四中类型句柄( ),且这个方法的句柄对应的类没有进行初始化,则需要初始化。
6)jdk1.8接口定义了defautl方法,且这个类的实现类发色很给力初始化,则该接口类在之前被初始化。

句柄摘抄地址:https://blog.csdn.net/liuming_nx/article/details/50425000
    补充 句柄:
       每种编程语言都有自己的数据处理方式。有些时候,程序员必须时刻留意准备处理的是什么类型。您曾利用一些特殊语法直接操作过对象,或处理过一些间接表示的对象吗(C或C++里的指针)?
所有这些在Java里都得到了简化,任何东西都可看作对象。因此,我们可采用一种统一的语法,任何地方均可照搬不误。但要注意,尽管将一切都“看作”对象,但操纵的标识符实际是指向一个对象的“句柄”(Handle)。在其他Java参考书里,还可看到有的人将其称作一个“引用”,甚至一个“指针”。可将这一情形想象成用遥控板(句柄)操纵电视机(对象)。只要握住这个遥控板,就相当于掌握了与电视机连接的通道。但一旦需要“换频道”或者“关小声音”,我们实际操纵的是遥控板(句柄),再由遥控板自己操纵电视机(对象)。如果要在房间里四处走走,并想保持对电视机的控制,那么手上拿着的是遥控板,而非电视机。
   此外,即使没有电视机,遥控板亦可独立存在。也就是说,只是由于拥有一个句柄,并不表示必须有一个对象同它连接。所以如果想容纳一个词或句子,可创建一个String句柄:
    String s;
    但这里创建的只是句柄,并不是对象。若此时向s发送一条消息,就会获得一个错误(运行期)。这是由于s实际并未与任何东西连接(即“没有电视机”)。因此,一种更安全的做法是:创建一个句柄时,记住无论如何都进行初始化:
    String s = "asdf";
    然而,这里采用的是一种特殊类型:字串可用加引号的文字初始化。通常,必须为对象使用一种更通用的初始化类型。

二.类的加载,连接,初始化过程
总共分为5大步
1.加载
2.连接(验证,准备,解析)
3.初始化
4.使用
5.卸载
加载: 通过类加载器(这个可以看做是一个工具),以类的全限定名(如: com.mycompany.test.MyTest MyTest是一个类,) 来获取MyTest的二进制文件(MyTest经过编译后生成的MyTest.class二进制文件)字节流。然后把这个流放入(读入)到jvm内存中,将其放在运行时数据区的方法区内,然后在jvm内存中创建一个该类的java.lang.Class对象(hotSpot放在方法区,没放到堆上)。
加载的二进制.class文件来源
1)本地系统中直接加载,
2)网络下载.class文件
3)zip,jar等归档文件中加载.class文件
4)从专有数据库中提取.class文件
5)强java源文件动态编译为.class文件。
补充: 所谓的java反编译,指将.class文件转换为对应的.java源代码文件(模板引擎中的如jsp会被转换为java在编译为。class二进制文件).
我们在开发中 看一些jar包的实现代码时,就利用了开发工具的反编译特性。
连接
连接分为三个部分
1) 验证
1>验证二进制文件的格式是否符合Class文件格式的规范。
2>验证元数据信息是否符合。包括是否有父类,如final修饰的类是否被继承等。
3>字节码验证 。 验证程序的设计及控制流程等(如:if,else,方法调用等流程)
4>符号引用验证。 如符号引用是否可以通过全限定名找到对应类。private,protected,public 等是否可以被当前类访问。
2)准备
为类中定义为static的变量分配内存和初始化默认值。

public static int a = 5;
此阶段会为静态变量a初始化一个默认值 0,注意不是5 。在第三阶段初始化时,才会给予a变量显示化的值 5
3)解析
将 符号引用替换为直接引用。
初始化
给予变量值如 把a=0 改为a= 5
使用

内存中某个类型的类已经加载进来比如MyTest类了,在内存中以MyTest的Class对象存在,比如在堆上创建对象,就使用这个MyTest的Class对象,创建出一个实例。其使用分为两类:
1>主动使用
2>被动使用
详细分类介绍地址:
xxxxxx.com
卸载
类的Class对象不再被引用,就会卸载。但是启动类加载器加载的类型在整个运行期间是不可能被卸载

你可能感兴趣的:(Jvm学习,java)