首先介绍什么是类加载:
类加载就是java虚拟机将工程所需的Class文件中的二进制数据到内存中,通过检验,解析,初始化等操作,将静态的字节流转化成方法区中动态的数据结构。
类的加载主要分为三个过程:加载、连接(验证、准备、解析)、初始化。
1、加载:主要是将Class文件中的二进制数据读到内存中去,然后将其转化为方法区中的运行时数据(包括常量、静态变量、静态代码块),同时在堆中创建一个java.lang.Class对象,用于外部访问这个Class类的入口。
2、连接:连接主要又分为三个阶段,首先验证加载的类中的内容是否符合正确的结构、JVM的规范,其次准备阶段为类的静态变量在方法区中分配内存,并赋初始值0或者null(这一点有一个问题注意就是static int a = 100 和 static final int a =100是不一样的第一个a准备阶段的赋值是0,第二个a准备阶段赋值是100),最后就是解析,将二进制数据中的符号引用转化为直接引用。
3、初始化:初始化阶段主要是对连接过程中的准备阶段赋初始值的静态变量赋程序设定的初值。初始化阶段不是必须的,但是有几种必须初始化类的情况:
当new一个类时、
使用getstatic或者putstatic读取或者设置一个静态变量时、
调用静态方法、
对类进行反射调用时、
初始化子类时首先初始化父类、
当子类调用父类的静态字段时只需初始化父类。
这几种情况下必须对类进行初始化操作。
这里区分一下“符号引用”和“直接引用”:
public class Test{
public static void main() {
String s=”adc”;
System.out.println(“s=”+s);
}
}
利用这段代码来解释就其中的代表“符号引用”的是s,s是我们用来定义的一个String类型变量abc的符号,这个符号在java程序中就代表着abc这个String类型变量。
这段代码经过jvm加载后就在计算机中就不需要s来代指abc这个String变量,而是把s直接替换成abc的内存地址。这里的内存地址就称之为直接引用。