JAVA类装载方式,有两种:
隐式装载, 程序在运行过程当中当碰到经过new 等方式生成对象时,隐式调用类装载器加载对应的类到jvm中。
显式装载, 经过class.forname()等方法,显式加载须要的类html
类加载的动态性体现:java
一个应用程序老是由n多个类组成,Java程序启动时,并非一次把全部的类所有加载后再运行,它老是先把保证程序运行的基础类一次性加载到jvm中,其它类等到jvm用到的时候再加载,这样的好处是节省了内存的开销,由于java最先就是为嵌入式系统而设计的,内存宝贵,这是一种能够理解的机制,而用到时再加载这也是java动态性的一种体现。 JDK 默认提供了以下几种ClassLoader
Bootstrp loaderjvm
Bootstrp加载器是用C++语言写的,它是在Java虚拟机启动后初始化的,它主要负责加载%JAVA_HOME%/jre/lib,-Xbootclasspath参数指定的路径以及%JAVA_HOME%/jre/classes中的类。
ExtClassLoaderspa
Bootstrp loader加载ExtClassLoader,而且将ExtClassLoader的父加载器设置为Bootstrp loader.ExtClassLoader是用Java写的,具体来讲就是 sun.misc.Launcher$ExtClassLoader,ExtClassLoader主要加载%JAVA_HOME%/jre/lib/ext,此路径下的全部classes目录以及java.ext.dirs系统变量指定的路径中类库。
AppClassLoader设计
Bootstrp loader加载完ExtClassLoader后,就会加载AppClassLoader,而且将AppClassLoader的父加载器指定为 ExtClassLoader。AppClassLoader也是用Java写成的,它的实现类是 sun.misc.Launcher$AppClassLoader,另外咱们知道ClassLoader中有个getSystemClassLoader方法,此方法返回的正是AppclassLoader.AppClassLoader主要负责加载classpath所指定的位置的类或者是jar文档,它也是Java程序默认的类加载器。 综上所述,它们之间的关系能够经过下图形象的描述: 为何要有三个类加载器,一方面是分工,各自负责各自的区块,另外一方面为了实现委托模型。
类加载器之间是如何协调工做的code
前面说了,java中有三个类加载器,问题就来了,碰到一个类须要加载时,它们之间是如何协调工做的,即java是如何区分一个类该由哪一个类加载器来完成呢。 在这里java采用了委托模型机制,这个机制简单来说,就是“类装载器有载入类的需求时,会先请示其Parent使用其搜索路径帮忙载入,若是Parent 找不到,那么才由本身依照本身的搜索路径搜索类” 下面举一个例子来讲明,为了更好的理解,先弄清楚几行代码:
[Java] 纯文本查看 复制代码
?htm
Public class Test{对象
Public static void main(String[] arg){ ClassLoader c = Test.class.getClassLoader(); //获取Test类的类加载器 System.out.println(c); ClassLoader c1 = c.getParent(); //获取c这个类加载器的父类加载器 System.out.println(c1); ClassLoader c2 = c1.getParent();//获取c1这个类加载器的父类加载器 System.out.println(c2);
}blog
}内存
运行结果:
[Java] 纯文本查看 复制代码
?
……AppClassLoader……
……ExtClassLoader……
Null
能够看出Test是由AppClassLoader加载器加载的,AppClassLoader的Parent 加载器是 ExtClassLoader,可是ExtClassLoader的Parent为 null 是怎么回事呵,朋友们留意的话,前面有提到Bootstrap Loader是用C++语言写的,依java的观点来看,逻辑上并不存在Bootstrap Loader的类实体,因此在java程序代码里试图打印出其内容时,咱们就会看到输出为null。
注:本文转自博客园,版权归博客园全部。
原文连接:https://www.cnblogs.com/doit8791/p/5820037.html