Java之 ClassLoader 和 class 加载过程
程序员文章站
2022-06-09 22:35:13
...
Java 的 Class 加载 步骤
一、背景知识
1. java.lang.ClassLoader类介绍
<Abstract> java.lang.ClassLoader
java.lang.ClassLoader 类的基本职责就是根据一个指定的类的名称,找到其对应的二进制字节代码文件。
然后根据这个文件,生成一个 java.lang.Class 类的实例。
- part of methods in java.lang.ClassLoader
2. JVM中类加载器的树状层次结构
1) 引导类加载器(bootstrap class loader):
它用来加载 Java 的核心库(jre/lib/rt.jar)。
是用原生C++代码来实现的,并不继承自java.lang.ClassLoader。
2) 扩展类加载器(extensions class loader) :继承自 1)
它用来加载 Java 的扩展库(jre/ext/*.jar)。
Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载 Java 类。
3) 系统类加载器(system class loader):继承自 2)
它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。
一般来说,Java 应用的类都是由它来完成加载的。
可以通过 java.lang.ClassLoader.getSystemClassLoader()来获取它。
除了系统提供的类加载器以外,开发人员可以通过继承
java.lang.ClassLoader类的方式实现自己的类加载器,以满足一些特殊的需求。
3. 双亲委派机制
某个特定的类加载器在接到加载类的请求时,首先将加载任务委托交给父类加载器。
父类加载器又将加载任务向上委托,直到最父类加载器。
如果最父类加载器可以完成类加载任务,就成功返回。
如果不行就向下传递委托任务,由其子类加载器进行加载。
双亲委派机制的好处:
保证java核心库的安全性。
例如:
如果用户自己写了一个java.lang.String类就会因双亲委派机制不能被加载,
不会破坏原生的String类的加载。
二、类加载过程
JVM将类加载过程分为三个步骤:
1) 装载(Load):
查找并加载类的二进制数据。
2) 链接(Link):
语法验证:确保被加载类信息符合JVM规范、没有安全方面的问题。
准备:为类的静态变量分配内存,并将其初始化为默认值。
解析:把虚拟机常量池中的符号引用转换为直接引用。
Java 中,虚拟机会为每个加载的类维护一个常量池。
【不同于字符串常量池,这个常量池只是该类的字面值(
例如:类名、方法名)和符号引用的有序集合。
而字符串常量池,是整个JVM共享的】
这些符号(如int a = 5; 中的 a )就是符号引用,
而解析过程就是把它转换成指向该类在堆中生成的对象地址的相对地址。
3) 初始化(Initialize):
为类的静态变量赋予正确的初始值。
步骤:
1>. 如果这个类还没有被加载和链接,那先进行加载和链接。
2>. 假如这个类存在直接父类,并且该父类还没有被初始化(
注意:在一个类加载器中,类只能初始化一次),
那么先初始化其直接的父类(不适用于接口)
3>. 如果类中存在 static 语句块,那就依次执行这些初始化语句。
-
引用:
- 全面解析Java类加载器
http://www.cnblogs.com/sunniest/p/4574080.html
-
一、背景知识
1. java.lang.ClassLoader类介绍
<Abstract> java.lang.ClassLoader
java.lang.ClassLoader 类的基本职责就是根据一个指定的类的名称,找到其对应的二进制字节代码文件。
然后根据这个文件,生成一个 java.lang.Class 类的实例。
- part of methods in java.lang.ClassLoader
// 1. // get parent class loader. public java.lang.ClassLoader getParent() // 2. // load a class according its binary name, // return a class instance. public java.lang.Class<T> loadClass(String name) // 3. // Converts an array of bytes into an instance of class Class. protected final java.lang.Class<T> defineClass(String name, byte[] b, int off, int len) //
2. JVM中类加载器的树状层次结构
1) 引导类加载器(bootstrap class loader):
它用来加载 Java 的核心库(jre/lib/rt.jar)。
是用原生C++代码来实现的,并不继承自java.lang.ClassLoader。
2) 扩展类加载器(extensions class loader) :继承自 1)
它用来加载 Java 的扩展库(jre/ext/*.jar)。
Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载 Java 类。
3) 系统类加载器(system class loader):继承自 2)
它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。
一般来说,Java 应用的类都是由它来完成加载的。
可以通过 java.lang.ClassLoader.getSystemClassLoader()来获取它。
除了系统提供的类加载器以外,开发人员可以通过继承
java.lang.ClassLoader类的方式实现自己的类加载器,以满足一些特殊的需求。
public class TestMClassLoader { public static void main(String[] args) throws Exception{ //current class loader. System.out.println(TestMClassLoader.class.getClassLoader()); //application class loader System.out.println(ClassLoader.getSystemClassLoader()); //extensions class loader System.out.println(ClassLoader.getSystemClassLoader().getParent()); //bootstrap class loader System.out.println(ClassLoader.getSystemClassLoader().getParent().getParent()); } } /* output: sun.misc.Launcher$AppClassLoader@3e0ebb sun.misc.Launcher$AppClassLoader@3e0ebb sun.misc.Launcher$ExtClassLoader@39443f null */ /* 可以看出: ClassLoader 类是由 AppClassLoader 加载的,其父类是 ExtClassLoader 。 ExtClassLoader 的父类无法获取是因为它是用 C++ 实现的。 */
3. 双亲委派机制
某个特定的类加载器在接到加载类的请求时,首先将加载任务委托交给父类加载器。
父类加载器又将加载任务向上委托,直到最父类加载器。
如果最父类加载器可以完成类加载任务,就成功返回。
如果不行就向下传递委托任务,由其子类加载器进行加载。
双亲委派机制的好处:
保证java核心库的安全性。
例如:
如果用户自己写了一个java.lang.String类就会因双亲委派机制不能被加载,
不会破坏原生的String类的加载。
二、类加载过程
JVM将类加载过程分为三个步骤:
1) 装载(Load):
查找并加载类的二进制数据。
2) 链接(Link):
语法验证:确保被加载类信息符合JVM规范、没有安全方面的问题。
准备:为类的静态变量分配内存,并将其初始化为默认值。
解析:把虚拟机常量池中的符号引用转换为直接引用。
Java 中,虚拟机会为每个加载的类维护一个常量池。
【不同于字符串常量池,这个常量池只是该类的字面值(
例如:类名、方法名)和符号引用的有序集合。
而字符串常量池,是整个JVM共享的】
这些符号(如int a = 5; 中的 a )就是符号引用,
而解析过程就是把它转换成指向该类在堆中生成的对象地址的相对地址。
3) 初始化(Initialize):
为类的静态变量赋予正确的初始值。
步骤:
1>. 如果这个类还没有被加载和链接,那先进行加载和链接。
2>. 假如这个类存在直接父类,并且该父类还没有被初始化(
注意:在一个类加载器中,类只能初始化一次),
那么先初始化其直接的父类(不适用于接口)
3>. 如果类中存在 static 语句块,那就依次执行这些初始化语句。
-
引用:
- 全面解析Java类加载器
http://www.cnblogs.com/sunniest/p/4574080.html
-
上一篇: HTML DOM Form对象
下一篇: 关于数据写入缓存设计
推荐阅读
-
Java之反射第十八天( --反射----类的加载--获取对象属性( 成员变量和方法)-- 构造方法 )
-
Java 动态加载jar和class文件实例解析
-
Java 类加载之匿名类和主类相互依赖问题
-
Java 动态加载jar和class文件实例解析
-
【java基础】面试常见问题:类和对象,封装继承多态,final关键字,static关键字,类加载过程,双亲委派模型
-
通过实例解析Java class文件编译加载过程
-
java基础---类加载和对象创建过程
-
Java之.class和.getClass()的区别
-
Java自定义Class加载顺序 classloader
-
【Java中类的加载和执行过程】