`
wu_quanyin
  • 浏览: 208162 次
  • 性别: Icon_minigender_1
  • 来自: 福建省
社区版块
存档分类
最新评论

ClassLoader的加载过程及分析一

    博客分类:
  • J2SE
阅读更多

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

 

一,ClassLoader的大体过程

 

如图:

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代码:

 

 

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

 

	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

 

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 的搜寻路径。因此,执行时期动态更改搜寻路径的设定是不可能的事情。

 

参考网址:http://blog.sina.com.cn/s/blog_4efddaed01008ypj.html

     http://syue.com/Software/JAVA/15709.html

 

 

  • 大小: 9.1 KB
  • 大小: 9 KB
分享到:
评论
5 楼 wupuyuan 2011-09-05  
写的很详细,不过我记得深入JVM虚拟机里的加载物理上分2层,时间上分3层
4 楼 gstarwd 2010-07-29  
我来学习来了~~还不错啊~~我还需要慢慢理解
3 楼 wu_quanyin 2010-07-05  
snow8261 写道
有没有什么好的例子啊


上面写的那些例子,运行一下,应该就可以了,,
2 楼 snow8261 2010-07-05  
有没有什么好的例子啊
1 楼 chris_zley 2010-07-04  
好深奥啊,前置知识有哪些。。可以讲讲吗

相关推荐

    【图解版】深入分析ClassLoader类加载工作机制

    【图解版】深入分析ClassLoader类加载工作机制,从原理到JVM的装载过程,详情分析了ClassLoader加载类以及自定义类加载器的过程,不可用于商业用途,如有版权问题,请联系删除!

    ClassLoader动态加载dex

    首先,我们要理解APK的加载过程。当Android系统启动一个应用时,会通过PathClassLoader加载APK中的`classes.dex`文件,这个文件包含了应用的大部分类。但是,如果我们的目标是动态加载额外的.dex文件,那么就需要...

    关于Classloader的总结!loadClass的分析和加载细节的分析

    5. **类加载过程** 类加载分为三个阶段:加载、验证、准备、解析和初始化。加载是`Classloader`的工作,验证确保类文件的正确性,准备分配静态变量并设置初始值,解析将符号引用转换为直接引用,初始化则执行类的...

    ClassLoader 详解.doc

    在类加载过程中,遵循“双亲委派模型”:当一个类加载器需要加载某个类时,它首先会委托它的父加载器尝试加载,只有当父加载器无法加载时,当前加载器才会尝试自己加载。这种机制避免了类的重复加载,并确保了核心...

    ClassLoader小例子

    - 示例可能还涉及到了对异常处理的演示,因为自定义加载过程中可能会遇到找不到类或非法类文件的问题。 了解和掌握ClassLoader的概念及其应用,对于理解和调试复杂的Java应用程序,尤其是涉及到动态加载和插件化...

    类加载机制ClassLoader

    由于链接无法直接访问,我们无法获取具体信息,但通常这类文章会涵盖如何自定义类加载器、分析类加载过程、类加载与JVM性能优化等相关主题。 在Java虚拟机文档(如`java虚拟机.doc`)中,通常会包含关于JVM架构、...

    ClassLoader

    - **自定义类加载器**则是通过重写`loadClass`方法来自定义类的加载过程。 ### 总结 本实例展示了如何通过自定义类加载器来加载类并实例化对象的过程。这种方法在某些特定场景下非常有用,比如在需要动态加载类的...

    ClassLoader的 一些测试

    1. 源码分析:研究ClassLoader的源码,了解其内部实现,特别是加载类的逻辑。 2. 类加载顺序:观察不同类加载器加载类的顺序,验证双亲委派模型。 3. 动态加载:创建自己的类加载器,尝试动态加载新的类,实现代码的...

    探索JVM底层奥秘ClassLoader源码分析与案例讲解

    在源码层面,ClassLoader的加载过程主要体现在`loadClass()`方法。这个方法会首先尝试从已加载的类中查找,如果没有找到,则会委托给父类加载器进行加载。这就是著名的"双亲委派模型"。这种模型保证了系统类的唯一性...

    classloader的简单实现

    1. 双亲委派模型:当一个类加载器收到加载类的请求时,它首先会将这个任务委托给其父类加载器,直到达到顶层的启动类加载器。如果父类加载器无法加载该类,子类加载器才会尝试自己加载。 2. 类的唯一性:同一个类...

    Android Classloader测试demo

    - 可能会有异常处理和日志记录,以帮助分析加载过程中的问题。 6. **实际应用** 对于开发者来说,理解这些类加载器的工作原理有助于优化应用的性能和功能。例如,在开发插件化应用时,可以利用DexClassLoader来...

    Android so加载过程详解

    在深入探讨Android中so(共享对象)文件加载过程之前,需要了解ELF(Executable and Linkable Format)文件格式。ELF是一种用于二进制文件、目标代码和可执行文件的标准文件格式,它描述了计算机中程序的结构。在...

    ClassLoader总结

    如IDEA、JProfiler等开发工具提供了分析ClassLoader的功能,帮助开发者调试和优化类加载过程。 10. 框架中的ClassLoader: 在Spring、OSGi等框架中,ClassLoader扮演着关键角色,如Spring的CGLIB代理机制就涉及到...

    classloader 加密解密应用程序 ,反编译class

    Bootstrap ClassLoader加载JRE的核心库,Extension ClassLoader加载Java扩展目录下的类,而AppClassLoader则加载应用的主类路径(ClassPath)上的类。 接下来,我们来讨论“加密解密应用程序”。在Java环境中,为了...

    classloader源码

    在Java编程语言中,`ClassLoader`是一个至关重要的组件,它负责加载类到JVM(Java虚拟机)中。深入理解`ClassLoader`的源码对于Java开发者来说是提升技能的重要环节,尤其是在进行模块化、插件化开发或者进行系统...

    java classloader classpath 张孝祥

    ### Java ClassLoader与ClassPath详解 #### 一、概述 在Java编程中,类加载机制是十分关键的一个环节。类加载器(`ClassLoader`)负责将...理解这些概念有助于开发者更好地管理和控制程序中的类和资源的加载过程。

    web_classloader_test.zip_web classloader

    9. **性能优化**:类加载过程会影响应用的启动速度和内存占用。优化类加载策略,比如延迟加载、缓存等,可以提升Web应用的性能。 通过分析`web_classloader_test`,我们可以学习到如何理解和调试Web应用的类加载...

Global site tag (gtag.js) - Google Analytics