Java关键技术强化:类加载器 (day05)

概述

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

    相信困难总会过去,相信坚持的意义。

原文地址:https://www.cnblogs.com/cmf12/p/13550108.html