Java类加载器

ClassLoader

一、分类:

1.BootStrap Class Loader:启动类加载器,负责加载rt.jar文件中所有的Java类,即Java的核心类都是由该ClassLoader加载。在Sun JDK中,这个类加载器是由C++实现的,并且在Java语言中无法获得它的引用。

2.Extension Class Loader:扩展类加载器,负责加载一些扩展功能的jar包。

3.System Class Loader:系统类加载器,负责加载启动参数中指定的Classpath中的jar包及目录,通常我们自己写的Java类也是由该ClassLoader加载。在Sun JDK中,系统类加载器的名字叫AppClassLoader。

4.User Defined Class Loader:用户自定义类加载器,由用户自定义类的加载规则,可以手动控制加载过程中的步骤。

二、工作原理:

类加载分为装载、链接、初始化三步。

1.装载

通过类的全限定名和ClassLoader加载类,主要是将指定的.class文件加载至JVM。当类被加载以后,在JVM内部就以“类的全限定名+ClassLoader实例ID”来标明类。

在内存中,ClassLoader实例和类的实例都位于堆中,它们的类信息都位于方法区。

装载过程采用了一种被称为“双亲委派模型(Parent Delegation Model)”的方式,当一个ClassLoader要加载类时,它会先请求它的双亲ClassLoader(其实这里只有两个ClassLoader,所以称为父ClassLoader可能更容易理解)加载类,而它的双亲ClassLoader会继续把加载请求提交再上一级的ClassLoader,直到启动类加载器。只有其双亲ClassLoader无法加载指定的类时,它才会自己加载类。

双亲委派模型是JVM的第一道安全防线,它保证了类的安全加载,这里同时依赖了类加载器隔离的原理:不同类加载器加载的类之间是无法直接交互的,即使是同一个类,被不同的ClassLoader加载,它们也无法感知到彼此的存在。这样即使有恶意的类冒充自己在核心包(例如java.lang)下,由于它无法被启动类加载器加载,也造成不了危害。

由此也可见,如果用户自定义了类加载器,那就必须自己保障类加载过程中的安全。

2.链接

链接的任务是把二进制的类型信息合并到JVM运行时状态中去。

链接分为以下三步:

a.验证:校验.class文件的正确性,确保该文件是符合规范定义的,并且适合当前JVM使用。

b.准备:为类分配内存,同时初始化类中的静态变量赋值为默认值。

c.解析(可选):主要是把类的常量池中的符号引用解析为直接引用,这一步可以在用到相应的引用时再解析。

3.初始化

初始化类中的静态变量,并执行类中的static代码、构造函数。

JVM规范严格定义了何时需要对类进行初始化:

a、通过new关键字、反射、clone、反序列化机制实例化对象时。

b、调用类的静态方法时。

c、使用类的静态字段或对其赋值时。

d、通过反射调用类的方法时。

e、初始化该类的子类时(初始化子类前其父类必须已经被初始化)。

f、JVM启动时被标记为启动类的类(简单理解为具有main方法的类)。

原文地址:https://www.cnblogs.com/libaoting/p/4110548.html