1. 类的加载机制深度解析
1.1 类的加载运行过程
如上图所示,Java中的类的加载靠的是类加载器实现的,其中通过loadClass进行类加载的时候会经历:加载》》验证》》准备》》解析》》初始化
几个步骤。
- 加载:查找磁盘中的类的字节码文件并通过io操作读入,只有类被真正使用的时候才会被加载
- 验证:验证字节码是否符合规范
- 准备:为静态变量分配内存空间,并且赋上默认的初始值。int类型赋值0、boolean类型赋值false、对象类型赋值null
- 解析:将符号引用(静态方法)转换为直接引用
- 初始化:为静态变量赋上真正的值
注意:主类在运行时如果使用到其他类,这些类会被逐步加载,jar包和war包中的类并不是一次性都加载出来的,而是真正使用到这个类的时候才会进行加载
package com.muzili.jvm;
public class TestDynamicLoad {
public static String initDate="test";
static {
System.out.println("运行TestDynamicLoad类的静态方法.....");
}
public TestDynamicLoad(){
System.out.println("运行TestDynamicLoad类的构造方法.....");
}
public static class InnerClassA{
static {
System.out.println("运行InnerClassA类的静态方法.....");
}
public InnerClassA(){
System.out.println("运行InnerClassA类的构造方法.....");
}
}
public static void main(String[] args) {
TestDynamicLoad testDynamicLoad=new TestDynamicLoad();
InnerClassA innerClassA=new InnerClassA();
}
}
结果输出:
运行TestDynamicLoad类的静态方法.....
运行TestDynamicLoad类的构造方法.....
运行InnerClassA类的静态方法.....
运行InnerClassA类的构造方法.....
Process finished with exit code 0
1.2 类加载器和双亲委派机制
1.2.1 类加载器
Java中的类加载器主要有三种:BootstrapClassLoader(引导类加载器)
、ExtClassLoader(扩展类加载器)
、AppClassLoader(应用程序类加载器)
。
- BootstrapClassLoader:主要用于加载Java程序运行时必不可少的核心类,如
jre/lib/rt.jar
、jre/lib/charsets.jar
中的类。 - ExtClassLoader:用于加载
jre/lib/ext
下的所有jar包中的类 - AppClassLoader:用于加载自己编写的类
package com.muzili.jvm;
import com.sun.crypto.provider.DESKeyFactory;
import sun.misc.Launcher;
import java.net.URL;
public class TestJDKClassLoader {
public static void main(String[] args) {
/**
* 输出以下类的ClassLoader
*/
System.out.println(String.class.getClassLoader());
System.out.println(DESKeyFactory.class.getClassLoader());
System.out.println(TestJDKClassLoader.class.getClassLoader());
System.out.println();
/**
* 获取ClassLoader
*/
//因为BootStrapClassLoader是通过C++实现,并实例化的故Java程序无法获取
ClassLoader appClassLoader=TestJDKClassLoader.class.getClassLoader();
ClassLoader extClassLoader=appClassLoader.getParent();
ClassLoader bootstrapClassLoader=extClassLoader.getParent();
System.out.println("the BootStrapClassLoader:"+bootstrapClassLoader);
System.out.println("the ExtClassLoader:"+extClassLoader);
System.out.println("the AppClassLoader:"+appClassLoader);
System.out.println();
URL[] bootStrapUrls = Launcher.getBootstrapClassPath().getURLs();
System.out.println("BootStrapLoader加载:");
for (URL url : bootStrapUrls) {
System.out.println(url.getPath()