-Xbootclasspath:bootclasspath 
让jvm从指定路径(可以是分号分隔的目录、jar、或者zip)中加载bootclass,用来替换jdk的rt.jar;若非必要,一般不会用到; 
-Xbootclasspath/a:path 
将指定路径的所有文件追加到默认bootstrap路径中; 
-Xbootclasspath/p:path 
让jvm优先于bootstrap默认路径加载指定路径的所有文件; 

一,ClassLoader的大体过程

如图:

详解:

 虚拟机一启动,会先做一些初始化的动作。一旦初始化动作完成之后,就会产生第一个类别加载器,即所谓的Bootstrap Loader,Bootstrap Loader 是由C++ 所撰写而成,这个Bootstrap Loader所做的初始工作中,除了也做一些基本的初始化动作之外,最重要的就是加载定义在sun.misc 命名空间底下的Launcher.java 之中的ExtClassLoader( 因为是inner class ,所以编译之后会变成Launcher$ExtClassLoader.class) ,并设定其Parent 为null,代表其父加载器为Bootstrap Loader 。然后Bootstrap Loader ,再要求加载定义于sun.misc 命名空间底下的Launcher.java 之中的AppClassLoader( 因为是inner class,所以编译之后会变成Launcher$AppClassLoader.class) ,并设定其Parent 为之前产生的ExtClassLoader 实例。

由以上可以看出,classLoader是由下向上查找,上层的不能向下查找。

二,ClassLoader中类的关系

如图:

详解:

 AppClassLoader 和ExtClassLoader 都是URLClassLoader 的子类别。由于它们都是URLClassLoader 的子类别,所以它们也应该有URL 作为搜寻类别档的参考,由原始码中我们可以得知,AppClassLoader 所参考的URL 是从系统参java.class.path 取出的字符串所决定,而java.class.path 则是由我们在执行java.exe 时,利用 –cp 或-classpath 或CLASSPATH 环境变量所决定。

ClassLoader的loadClass代码:

  1. protected synchronized Class<?> loadClass(String name, boolean resolve)
  2. throws ClassNotFoundException
  3. {
  4. // First, check if the class has already been loaded
  5. //类是否被加载过
  6. Class c = findLoadedClass(name);
  7. if (c == null) {
  8. try {
  9. if (parent != null) {
  10. //到parentclassloader中去查找(像这个parent还有parent递归方式进行查找)
  11. c = parent.loadClass(name, false);
  12. } else {
  13. //启动类加载器进行加载
  14. c = findBootstrapClass0(name);
  15. }
  16. } catch (ClassNotFoundException e) {
  17. // If still not found, then invoke findClass in order
  18. // to find the class.
  19. //当一直都没有找到时,启动当前类的findClass进行查找
  20. //这个通常也是我们扩展的地方
  21. c = findClass(name);
  22. }
  23. }
  24. if (resolve) {
  25. resolveClass(c);
  26. }
  27. return c;
  28. }
protected synchronized Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
// First, check if the class has already been loaded
//类是否被加载过
Class c = findLoadedClass(name);
if (c == null) {
try {
if (parent != null) {
//到parentclassloader中去查找(像这个parent还有parent递归方式进行查找)
c = parent.loadClass(name, false);
} else {
//启动类加载器进行加载
c = findBootstrapClass0(name);
}
} catch (ClassNotFoundException e) {
// If still not found, then invoke findClass in order
// to find the class.
//当一直都没有找到时,启动当前类的findClass进行查找
//这个通常也是我们扩展的地方
c = findClass(name);
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
 
详解:
java文件的编译和Class的载入执行,都是使用Launcher初始化的appclassloader作为类载入器的,我们无法动态的改变App classloader,更无法让JVM使用我们自己的classloader来替换system classloader,根据全盘负责原则,就限制了编译和运行时,我们无法直接显式的使用一个system classloader寻找不到的Class,即我们只能使用Java核心类库,扩展类库和CLASSPATH中的类库中的Class。
而且我们也无法载入以java.lang....开头的包,进行了限制

三,分析及证明:

可以用最底层的ClassLoader得到某一个类(Test)时,Test.class.getClassLoader()就可知当前类在哪一个层次的ClassLoader下被加载

1,BootStrapClassLoader

  1. Class clazz=Class.forName("java.lang.Object");
  2. System.out.println(clazz.getClassLoader());
  3.   //输出为null,因为bootstrap在java中不是类,而是由c++编写的
  4.     URL[] urls=sun.misc.Launcher.getBootstrapClassPath().getURLs();
  5. for (int i = 0; i < urls.length; i++) {
  6. System.out.println(urls[i].getFile());
  7. }//用这个进行查找bootstrap所加载的是哪些jar包
	Class clazz=Class.forName("java.lang.Object");
System.out.println(clazz.getClassLoader());    //输出为null,因为bootstrap在java中不是类,而是由c++编写的     URL[] urls=sun.misc.Launcher.getBootstrapClassPath().getURLs();
for (int i = 0; i < urls.length; i++) {
System.out.println(urls[i].getFile());
}//用这个进行查找bootstrap所加载的是哪些jar包

 

2,ExtClassLoader

  1. clazz = Class.forName("sun.net.spi.nameservice.dns.DNSNameService");
  2. clazzLoader = clazz.getClassLoader();
  3. System.out.println(" sun.net.spi.nameservice.dns.DNSNameService's loader is  "
  4. + clazzLoader);
  5. //在些可以说明ExtClassLoader所加载的类
clazz = Class.forName("sun.net.spi.nameservice.dns.DNSNameService");
clazzLoader = clazz.getClassLoader();
System.out.println(" sun.net.spi.nameservice.dns.DNSNameService's loader is "
+ clazzLoader);
//在些可以说明ExtClassLoader所加载的类

 3,AppClassLoader

当前工程中class与lib都是用此Loader加载

可以通过ClassLoader.getSystemClassLoader()可以获取到AppClassLoader的

4,DefineClassLoader

可以继承URLClassLoader或ClassLoader

当继承ClassLoader重写findClass()方法,parent会相应是AppClassLoader-->ExtClassLoader-->BootStrapClassLoader

URLClassLoader可以直接设置url即可

问题:

由于自己自定义了一个DefineClassLoader替代了加载ant的ClassLoader,另外添加自己jar包,

但是在执行ant编译时,要执行tools.jar里的javac类,在执行javac这个类时,是处在AppClassLoader

下,找不到我添加的DefineClassLoader的jar包

------------------------------------------------

其他一些相应的操作(参考)

  在预设情况下,AppClassLoader的搜寻路径为”.”( 目前所在目录),如果使用-classpath 选项(与-cp 等效),就可以改变AppClassLoader 的搜寻路径,如果没有指定-classpath 选项,就会搜寻环境变量CLASSPATH 。如果同时有CLASSPATH 的环境设定与-classpath 选项,则以-classpath 选项的内容为主,CLASSPATH 的环境设定与-classpath 选项两者的内容不会有加成的效果。至于ExtClassLoader 也有相同的情形,不过其搜寻路径是参考系统参数java.ext.dirsBootstrap Loader ,我们可以经由查询由系统参数sun.boot.class.path 得知Bootstrap Loader 用来搜寻类别的路径java -Dsun.boot.class.path=请回头看到java.class.path 与sun.boot.class.path,也就是说,AppClassLoader 与Bootstrap Loader 会搜寻它们所指定的位置(或JAR 文件),如果找不到就找不到了,AppClassLoader 与Bootstrap Loader 不会递归式地搜寻这些位置下的其他路径或其他没有被指定的JAR 文件。反观ExtClassLoader,所参考的系统参数是java.ext.dirs,意思是说,他会搜寻底下的所有JAR 文件以及classes 目录,作为其搜寻路径(所以您会发现上面我们在测试的时候,如果加入-Dsun.boot.class.path=c:windows 选项时,程序的起始速度会慢了些,这是因为c:windows 目录下的文件很多,必须花额外的时间来列举JAR 文件)。

  在命令行下参数时,使用–classpath / -cp / 环境变量CLASSPATH 来更改AppClassLoader 的搜寻路径,或者用 –Djava.ext.dirs 来改变ExtClassLoader的搜寻目录,两者都是有意义的。可是用–Dsun.boot.class.path 来改变Bootstrap Loader 的搜寻路径是无效。这是因为AppClassLoader与ExtClassLoader 都是各自参考这两个系统参数的内容而建立,当您在命令行下变更这两个系统参数之后,AppClassLoader 与ExtClassLoader在建立实例的时候会参考这两个系统参数,因而改变了它们搜寻类别文件的路径; 而系统参数sun.boot.class.path 则是默认与Bootstrap Loader 的搜寻路径相同,就算您更改该系统参与,与BootstrapLoader 完全无关,AppClassLoader 与ExtClassLoader 在整个虚拟机之中只会存有一份,一旦建立了,其内部所参考的搜寻路径将不再改变,也就是说,即使我们在程序里利用System.setProperty() 来改变系统参数的内容,仍然无法更动AppClassLoader 与ExtClassLoader 的搜寻路径。因此,执行时期动态更改搜寻路径的设定是不可能的事情。

ClassLoad的加载过程及分析的更多相关文章

  1. insmod模块加载过程代码分析1【转】

    转自:http://blog.chinaunix.net/uid-27717694-id-3966290.html 一.概述模块是作为ELF对象文件存放在文件系统中的,并通过执行insmod程序链接到 ...

  2. module加载过程初步分析[更新中]【转】

    转自:http://blog.chinaunix.net/uid-1817735-id-2837068.html 分析这个过程可以有助于我们认识在加载模块时出现的问题大抵在哪里了. 直接从sys_in ...

  3. 重温.NET下Assembly的加载过程

    最近在工作中牵涉到了.NET下的一个古老的问题:Assembly的加载过程.虽然网上有很多文章介绍这部分内容,很多文章也是很久以前就已经出现了,但阅读之后发现,并没能解决我的问题,有些点写的不是特别详 ...

  4. 重温.NET下Assembly的加载过程 ASP.NET Core Web API下事件驱动型架构的实现(三):基于RabbitMQ的事件总线

    重温.NET下Assembly的加载过程   最近在工作中牵涉到了.NET下的一个古老的问题:Assembly的加载过程.虽然网上有很多文章介绍这部分内容,很多文章也是很久以前就已经出现了,但阅读之后 ...

  5. NET下Assembly的加载过程

    NET下Assembly的加载过程 最近在工作中牵涉到了.NET下的一个古老的问题:Assembly的加载过程.虽然网上有很多文章介绍这部分内容,很多文章也是很久以前就已经出现了,但阅读之后发现,并没 ...

  6. Glide图片加载过程(简)

    iceIC 关注 2018.10.25 20:53* 字数 906 阅读 529评论 0喜欢 1 调研版本为4.7.1为了更加简单的理解,会将函数代码简化,详细代码请自行照源码对比 Glide用法 G ...

  7. springmvc源码分析——入门看springmvc的加载过程

    本文将分析springmvc是如何在容器启动的时候将各个模块加载完成容器的创建的. 我知道在web.xml文件中我们是这样配置springmvc的: 可以看到,springmvc的核心控制器就是Dis ...

  8. Dubbo源码分析之ExtensionLoader加载过程解析

    ExtensionLoader加载机制阅读: Dubbo的类加载机制是模仿jdk的spi加载机制:  Jdk的SPI扩展加载机制:约定是当服务的提供者每增加一个接口的实现类时,需要在jar包的META ...

  9. springmvc源码分析----入门看springmvc的加载过程

    接上一篇我们写的入门---http://www.cnblogs.com/duanxiaojun/p/6591448.html 今天从这个门里进去我们看springmvc是如何在容器启动的时候将各个模块 ...

随机推荐

  1. ThinkPHP整合支付宝担保交易

    ThinkPHP整合支付宝担保交易本代码参考大神 http://www.thinkphp.cn/code/240.html 的思路 1.登陆支付宝后台,下载担保交易的集成包. 2.下载完成后的文件说明 ...

  2. Jquery Md5加密解密

    首先需要调用md5解析的js文件.(右击-目标另存为方式下载) http://files.cnblogs.com/files/colinliu/md5.js 加密方法参考: <script ty ...

  3. 欧几里得证明$\sqrt{2}$是无理数

    选自<费马大定理:一个困惑了世间智者358年的谜>,有少许改动. 原译者:薛密 \(\sqrt{2}\)是无理数,即不能写成一个分数.欧几里得以反证法证明此结论.第一步是假定相反的事实是真 ...

  4. 使用type="redirect"重定向,传递List等变量到jsp页面的问题

    Struts2在提交表单的时候,使用「type="redirect"」重定向到相应的jsp页面. Action中的List表单是无法传到相应的jsp页面. 我猜测是因为List作为 ...

  5. jstl c标签

    判断List是否为空的一种方法是使用jstl的c标签. <c:if test="${not empty cpInfo.cpCredentials}"> </c:i ...

  6. 用SQLite查看编辑android导出的微信聊天记录

    上一篇我们已经能够完成文字版微信聊天记录导出android了,也即复制或剪切MicroMsg.db文件到电脑,以.db格式结尾的文件是数据库文件(database document),需要安装相关数据 ...

  7. Objective-C上地球坐标系到火星坐标系转换算法

    Objective-C上地球坐标系到火星坐标系转换算法 http://blog.csdn.net/zhaoxy_thu/article/details/17033347

  8. zabbix 3.0.4 监控windows 服务

    下载客户端 http://www.zabbix.com/download.php http://www.zabbix.com/downloads/3.0.4/zabbix_agents_3.0.4.w ...

  9. Java 7 Concurrency Cookbook 翻译 第一章 线程管理之三

    五.睡眠和唤醒一个线程 有时,你会想要在一段特定的时间后再去中断线程的运行.举个例子,程序中的一个线程每一分钟检查一次传感器的状态,剩余的时间,线程应该处于空闲的状态.在这段空闲时间里,线程不会使用计 ...

  10. Tomcat7优化配置

    导读 Tomcat在使用的过程中会遇到很多报错,有些是程序的报错,但还有一部分是tomcat本身的报错,我们可以通过优化tomcat的初始配置来提高tomcat的性能.Tomcat的优化主要体现在两方 ...