作用:

类装载子系统装载过程及两种类加载器_类加载器


三个阶段:

1、加载阶段

类装载子系统装载过程及两种类加载器_类加载器_02


这个阶段主要是读取字节码文件。2、链接阶段

类装载子系统装载过程及两种类加载器_类加载器_03


类装载子系统装载过程及两种类加载器_加载_04


验证:查看 class 的二进制文件,能查看到是以 CA FE BA EE开头,说明这是一个符合要求的字节码文件。可以防止恶意文件危害虚拟机的安全。

准备:在这个阶段会为类变量分配默认的值。如:int 类型为0,char 类型为\u0000,float 类型为0.0f,boolean 为false,引用类型为null。这里不包含 final 修饰的 static ,这些数据会直接初始化。

解析:如上图。

3、初始化

类装载子系统装载过程及两种类加载器_java_05


类装载子系统装载过程及两种类加载器_加载_06

  • 初始化阶段,按照顺序来赋值。
    为什么把 number 定义在下面,但是可以在上面赋值呢?因为我们前面在链接阶段说过,变量首先会初始化该类型的默认值即 0。所以可以直接赋值,但是不能前向引用
  • 父类在子类之前加载。
    上面的例子结果为2。
  • 虚拟机必须保证一个类的()方法在多线程下被同步加锁。

两种类加载器

1、引导类加载器 BootstrapClassLoader,由 C++ 语言编写,在程序中获取该类加载器得到的是一个null值。

该加载器加载虚拟机核心类库,如以 java、javax、sun 开头的包下的类。

2、自定义加载器,由java编写,常见的是扩展类加载器 ExtensionClassLoader、系统类加载器或叫应用类加载器 AppClassLoader(SystemClassLoader)

其中 ExtensionClassLoader 由 BootstrapClassLoader 加载, AppClassLoader 由 ExtensionClassLoader 加载,常称引导类加载器是扩展类加载器的父类,而扩展类加载器是系统类加载器的父类。

其中扩展类加载器加载目录 jre/lib/ext 下的类库,系统类加载器负责加载 classpath 或者 java.class.path 指定路径下的类库。

双亲委派机制:

某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。

例:
我们在项目下创建一个 java.lang 的包,然后在包下创建一个 String 类。

package java.lang;

public class String {

static {
System.out.println("我是自定义String类");
}
}

另外在这个包外创建主方法入口

package com.hausen;
public class StackStruTest {

public static void main(String[] args) {

String s = new String();
System.out.println("hello");
}
}

如果创建的这个 String 类是由我们创建的话,那么会打印 " 我是自定义 String 类 ",运行程序,得到下面结果:

类装载子系统装载过程及两种类加载器_java_07


原因:由于双亲委派机制的存在,系统类加载器接收到创建 String 类的请求,将请求交给扩展类,扩展类交给引导类。引导类发现 java.lang 这个路径在自己的管理范围内,就把 java 自带 String 类加载,就不把请求向下传递了。反之,则需要向下传递,一直到系统类加载器把需要的类加载。

优点:
1.防止类的重复加载
2.保护程序安全,防止核心 Api 被修改。