概述
1、类加载器
顾名思义,它就是用来加载Class文件到JVM,以供程序使用的。
JAVA的类加载,都是通过类加载器完成的。
2、类加载器的创建
当java运行class文件时,java运行程序会尝试找到JRE安装的所在目录,然后寻找jvm.dll(默认安装在binclient目录中)
接着启动JVM 并进行初始化的工作,产生Bootstrap Loader,Bootstrap Loader会加载Extended Loader和AppClass Loader。
Bootstrap Loader是Extended Loader的parent Loader Extended Loader是AppClass Loader的parent Loader
3、类加载器介绍
- Java内置的ClassLoader
1、 Bootstrap Loader (引导类加载器) 其实现依赖于底层操作系统,由C编写而成,没有继承于ClassLoader类。根类加载器从系统属性sun.boot.class.path所指定的目录中加载类库。默认为jre目录下的 lib目录下的.class文件 该加载器没有父加载器。负责加载虚拟机的核心类库,如java.lang.*。Object类就是由根类加载器加载的。
2.、Extended Loader (标准扩展类加载器) 它的父加载器为根类加载器。由Java编写而成,是ClassLoader的子类。 它从java.ext.dirs中加载类库,或者从JDK安装目录jrelibext子目录下加载类库。 如果把用户创建的jar文件放在该目录下,也会自动由扩展类加载器加载 。
3. AppClass Loader(应用程序类路径类加载器) 父加载器为扩展类加载器。由Java编写而成,是ClassLoader的子类 它从环境变量classpath或者系统属性java.class.path所指定的目录中加载类,是用户自定义的类加载器的默认父加载器。
4、类加载器工作原理
每个类加载器会先将加载类的任务交给其parent,如果parent找不到,再由自己负责加载。
所以在加载类时,会以Bootstrap Loader —— Extended Loader —— AppClass Loader 的顺序来寻找类,如果找不到,就会丢出NoClassDefFoundError。
5、Class和ClassLoader
- 类加载器在Java中是以java.lang.ClassLoader类型存在 每一个类被加载后,都会有一个Class的实例来代表,而每个Class的实例都会记得自己是由哪个ClassLoader加载的。
- 可以通过Class的getClassLoader()取得加载该类的ClassLoader。
- 可以通过ClassLoader的getParent()取得自己的parent 注意:返回null并不代表没有parent,因为Bootstrap Loader 是用C语言编写的,所以没有一个实际的类来表示它。
- 可以通过ClassLoader的loadClass()加载类。这时不会立即运行静态块,会等到创建类的实例时才会运行。
代码示例
1 package work3;
2
3 public class Work3 {
4 /*
5 * @param args
6 * @throws ClassNotFoundException
7 * */
8 public static void main(String[] args) {
9 Class clz;
10 ClassLoader cl,cl1;
11
12 System.out.println("1------------------");
13 // 得到系统类加载器
14 cl = ClassLoader.getSystemClassLoader();
15 System.out.println(cl);
16
17 // 输出其父加载器
18 while(cl != null){
19 cl1 = cl;
20 cl = cl1.getParent();
21 System.out.println(cl1+"的父加载器是:"+cl);
22 }
23
24 System.out.println("2------------------");
25 try {
26 clz = Class.forName("java.lang.Object");
27 cl = clz.getClassLoader();
28 System.out.println("加载Object类的类加载器是:"+cl);
29 } catch (ClassNotFoundException e) {
30 e.printStackTrace();
31 }
32
33 System.out.println("3------------------");
34 clz = Work3.class;
35 cl = clz.getClassLoader();
36 System.out.println("加载当前类的类加载器是:"+cl);
37 }
38 }
运行效果
1 1------------------
2 sun.misc.Launcher$AppClassLoader@14dad5dc
3 sun.misc.Launcher$AppClassLoader@14dad5dc的父加载器是:sun.misc.Launcher$ExtClassLoader@28d93b30
4 sun.misc.Launcher$ExtClassLoader@28d93b30的父加载器是:null
5 2------------------
6 加载Object类的类加载器是:null
7 3------------------
8 加载当前类的类加载器是:sun.misc.Launcher$AppClassLoader@14dad5dc
6、类的加载过程
类的加载分为三个部分:装载、连接、初始化三个过程。装载是将类做为二进制流读到内存中;
连接是将二进制流转换成类对象(class对象) ,并加载初始化类所需要的资源;
初始化是初始化类变量或执行static静态块,并为类对象(Class的实例)分配内存空间。
7、类加载器树状组织结构示意图
8、类的死亡
类也能被垃圾回收。类被回收的条件有二条: 如果程序没有对Class对象保持明确的引用。 并且堆中没有一个此类的对象。
总结
心得总结
不怕你迈的步子太小,只怕你停滞不前;不怕你做的事太少,只怕你无所事事。任何的收获都不是偶然和巧合,而是日复一日的付出和努力换来。今天一点一滴的进步,终会塑造一个与众不同的你。
人总是会有懒惰的时刻,昨天停更了一天,今天要继续更新博客,再接再厉!
有兴趣了解java或者想多跟作者交流的可以加qq--》1265987500
相信困难总会过去,相信坚持的意义。