`
longdick
  • 浏览: 584925 次
  • 性别: Icon_minigender_1
  • 来自: 0
社区版块
存档分类
最新评论

图解classloader加载class的流程及自定义ClassLoader

    博客分类:
  • JVM
阅读更多

/**

*  转载请注明作者longdick    http://longdick.iteye.com

*

*/


 

java应用环境中不同的class分别由不同的ClassLoader负责加载。
一个jvm中默认的classloader有Bootstrap ClassLoader、Extension ClassLoader、App ClassLoader,分别各司其职:


  • Bootstrap ClassLoader     负责加载java基础类,主要是 %JRE_HOME/lib/ 目录下的rt.jar、resources.jar、charsets.jar和class等
  • Extension ClassLoader     负责加载java扩展类,主要是 %JRE_HOME/lib/ext 目录下的jar和class
  • App ClassLoader           负责加载当前java应用的classpath中的所有类。

 

其中Bootstrap ClassLoader是JVM级别的,由C++撰写;Extension ClassLoader、App ClassLoader都是java类,都继承自URLClassLoader超类。
Bootstrap ClassLoader由JVM启动,然后初始化sun.misc.Launcher ,sun.misc.Launcher初始化Extension ClassLoader、App ClassLoader。

下图是ClassLoader的加载类流程图,以加载一个类的过程类示例说明整个ClassLoader的过程。

 



 Bootstrap ClassLoader、Extension ClassLoader、App ClassLoader三者的关系如下:

Bootstrap ClassLoader是Extension ClassLoader的parent,Extension ClassLoader是App ClassLoader的parent。

但是这并不是继承关系,只是语义上的定义,基本上,每一个ClassLoader实现,都有一个Parent ClassLoader。

 

可以通过ClassLoader的getParent方法得到当前ClassLoader的parent。Bootstrap ClassLoader比较特殊,因为它不是java class所以Extension ClassLoader的getParent方法返回的是NULL。

 

了解了ClassLoader的原理和流程以后,我们可以试试自定义ClassLoader。

 

关于自定义ClassLoader:

 

由于一些特殊的需求,我们可能需要定制ClassLoader的加载行为,这时候就需要自定义ClassLoader了.

自定义ClassLoader需要继承ClassLoader抽象类,重写findClass方法,这个方法定义了ClassLoader查找class的方式。

主要可以扩展的方法有:

findClass          定义查找Class的方式

defineClass       将类文件字节码加载为jvm中的class

findResource    定义查找资源的方式

 

如果嫌麻烦的话,我们可以直接使用或继承已有的ClassLoader实现,比如

 

  • java.net.URLClassLoader
  • java.security.SecureClassLoader
  • java.rmi.server.RMIClassLoader
  • sun.applet.AppletClassLoader

Extension ClassLoader 和 App ClassLoader都是java.net.URLClassLoader的子类。

这个是URLClassLoader的构造方法:

 

public URLClassLoader(URL[] urls, ClassLoader parent)

public URLClassLoader(URL[] urls)

 

urls参数是需要加载的ClassPath url数组,可以指定parent ClassLoader,不指定的话默认以当前调用类的ClassLoader为parent。

 

代码示例:

 

ClassLoader classLoader = new URLClassLoader(urls);
Thread.currentThread().setContextClassLoader(classLoader);
Class clazz=classLoader.loadClass("com.company.MyClass");//使用loadClass方法加载class,这个class是在urls参数指定的classpath下边。

Method taskMethod = clazz.getMethod("doTask", String.class, String.class);//然后我们就可以用反射做些事情了
taskMethod.invoke(clazz.newInstance(),"hello","world");

 

 

由于classloader 加载类用的是全盘负责委托机制。所谓全盘负责,即是当一个classloader加载一个Class的时候,这个Class所依赖的和引用的所有 Class也由这个classloader负责载入,除非是显式的使用另外一个classloader载入。

所以,当我们自定义的classloader加载成功了com.company.MyClass以后,MyClass里所有依赖的class都由这个classLoader来加载完成。

 

自定义ClassLoader在某些应用场景还是比较适用,特别是需要灵活地动态加载class的时候。

下面这篇文章列出了其中一种自定义ClassLoader的应用场景,有兴趣的同学可以参考下:

http://longdick.iteye.com/blog/332580

 

  • 大小: 65.9 KB
17
2
分享到:
评论
10 楼 timothy2005 2015-12-23  
楼主最下方的链接是不是放错了?
原本说该篇文章列出了其中一种自定义ClassLoader的应用场景, 但是点进去看,内容却是:
运行jar应用程序引用其他jar包的四种方法

@longdick, 能不能贴出正确的链接啊? 我们前来学习.
9 楼 sampou 2015-12-14  
8 楼 NeverSky 2014-02-26  
楼主好贴,受教了
7 楼 steven19880224 2013-11-19  
dracularking 写道
longdick 写道
patrickyao1988 写道
楼主讲的很好,受教了!但是我有个细节的问题,就是《深入java虚拟机》里说的好像是加载class文件由AppClassLoader先getParentClassLoader,然后得到ExtentionClassLoader后再调用getParent,直到得到Bootstrap ClassLoader,然后这个Bootstrap尝试加载该class文件,如果不行就交给他的下属(就是extendsion classLoder)去加载,extendsion不行再给App,就是这样一个过程,当然那本书比较老了,又或者是我理解有偏差,请问楼主你的图里是不是省略了这样一个过程?还是现在就是这样加载的不需要那么复杂?

《深入java虚拟机》说的没错。
每一个classLoader加载class的时候会先委托自己的parentClassLoader来加载,parent加载不了才由自己加载。所以如果它的parentClassLoader还有parent的话,还会继续向上委托,直到BootstrapClassLoader为止。这个图把这个过程精简成一步了。

好帖,不过我虽然知道会先委托给parent classloader去加载类,这种方式好像显得在某些情况下啰嗦,比如加载classpath下的用户自定义类,其实很明显应该由AppClassLoader来加载,但它还必须要先去问一下它的所有parent
那我自己写个恶意的Object类,这样的话是不是很危险啊,如果委托给parent就不会有这种情况了。
6 楼 dracularking 2013-07-03  
longdick 写道
patrickyao1988 写道
楼主讲的很好,受教了!但是我有个细节的问题,就是《深入java虚拟机》里说的好像是加载class文件由AppClassLoader先getParentClassLoader,然后得到ExtentionClassLoader后再调用getParent,直到得到Bootstrap ClassLoader,然后这个Bootstrap尝试加载该class文件,如果不行就交给他的下属(就是extendsion classLoder)去加载,extendsion不行再给App,就是这样一个过程,当然那本书比较老了,又或者是我理解有偏差,请问楼主你的图里是不是省略了这样一个过程?还是现在就是这样加载的不需要那么复杂?

《深入java虚拟机》说的没错。
每一个classLoader加载class的时候会先委托自己的parentClassLoader来加载,parent加载不了才由自己加载。所以如果它的parentClassLoader还有parent的话,还会继续向上委托,直到BootstrapClassLoader为止。这个图把这个过程精简成一步了。

好帖,不过我虽然知道会先委托给parent classloader去加载类,这种方式好像显得在某些情况下啰嗦,比如加载classpath下的用户自定义类,其实很明显应该由AppClassLoader来加载,但它还必须要先去问一下它的所有parent
5 楼 我改名了 2013-04-12  
图画的不错 。
4 楼 xiaojin21cen 2013-02-28  
之前,我一直对ClassLoader加载过程理解不了,
而楼主用图文并茂的方式使我很快就理解了。


3 楼 patrickyao1988 2009-10-08  
哦  谢谢! 看了楼主的帖子更容易理解些
2 楼 longdick 2009-10-08  
patrickyao1988 写道
楼主讲的很好,受教了!但是我有个细节的问题,就是《深入java虚拟机》里说的好像是加载class文件由AppClassLoader先getParentClassLoader,然后得到ExtentionClassLoader后再调用getParent,直到得到Bootstrap ClassLoader,然后这个Bootstrap尝试加载该class文件,如果不行就交给他的下属(就是extendsion classLoder)去加载,extendsion不行再给App,就是这样一个过程,当然那本书比较老了,又或者是我理解有偏差,请问楼主你的图里是不是省略了这样一个过程?还是现在就是这样加载的不需要那么复杂?

《深入java虚拟机》说的没错。
每一个classLoader加载class的时候会先委托自己的parentClassLoader来加载,parent加载不了才由自己加载。所以如果它的parentClassLoader还有parent的话,还会继续向上委托,直到BootstrapClassLoader为止。这个图把这个过程精简成一步了。
1 楼 patrickyao1988 2009-10-06  
楼主讲的很好,受教了!但是我有个细节的问题,就是《深入java虚拟机》里说的好像是加载class文件由AppClassLoader先getParentClassLoader,然后得到ExtentionClassLoader后再调用getParent,直到得到Bootstrap ClassLoader,然后这个Bootstrap尝试加载该class文件,如果不行就交给他的下属(就是extendsion classLoder)去加载,extendsion不行再给App,就是这样一个过程,当然那本书比较老了,又或者是我理解有偏差,请问楼主你的图里是不是省略了这样一个过程?还是现在就是这样加载的不需要那么复杂?

相关推荐

    使用classloader动态加载Class

    1. **自定义ClassLoader**:Java允许我们创建自定义的ClassLoader,这通常用于实现动态加载类的需求。自定义ClassLoader需要重写`findClass()`或`loadClass()`方法。`loadClass()`方法是类加载的入口,它会调用`find...

    Java实现热加载完整代码;Java动态加载class;Java覆盖已加载的class;Java自定义classloader

    让Java支持热加载是个不错的想法。如何做到的呢? 1. 定义好接口和实现类 2. 让代理类通过反射的方式调用实现类,对外暴露的是代理类。 3. 自定义URLClassLoader。检查实现类.class文件的...Java自定义classloader;

    ClassLoader类加载机制和原理详解

    双亲委派模型使得系统类(如java.*开头的类)由Bootstrap ClassLoader加载,而用户自定义类由应用程序类加载器(AppClassLoader)加载。这避免了类的冲突,保持了系统类库的稳定性。但有时我们可能需要打破这种模型...

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

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

    自定义classloader的使用

    自定义Classloader允许开发者根据特定需求定制类的加载逻辑,例如加密类文件、隔离不同版本的库或者动态加载代码。本文将深入探讨自定义Classloader的使用。 一、Classloader的工作原理 Java的类加载机制遵循双亲...

    ClassLoader类加载器

    自定义ClassLoader通常是为了满足特定的加载需求,例如从网络、数据库或非标准路径加载类。下面是一个简单的自定义ClassLoader的示例: ```java public class MyClassLoader extends ClassLoader { private String...

    java自定义类加载classloader文档,包括代码

    接下来我们通过一个简单的自定义类加载器示例来进一步了解类加载器的工作流程。 ```java package test.classloader; import java.io.*; import org.apache.log4j.Logger; public class MyClassLoader extends ...

    S18-ClassLoader类加载流程1

    通过自定义类加载器并重写`loadClass()`方法,可以打破双亲委派模型。但是通常不推荐这样做,因为这可能引入类版本冲突和安全性问题。 5. **自定义类加载器** 开发者可以创建自己的类加载器来实现特定的加载逻辑...

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

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

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

    在Java编程语言中,`Classloader`(类加载器)是一个至关重要的组件,它负责将类的`.class`文件从磁盘加载到JVM(Java虚拟机)内存中,使得程序能够执行。这篇博文主要围绕`Classloader`的`loadClass`方法进行深入...

    自定义类加载器实现自定义加载

    - 自定义类加载器需要继承Java的`java.lang.ClassLoader`类,并重写`loadClass(String name)`方法。这个方法是加载类的核心,它首先检查该类是否已经被加载,然后决定是从父类加载器还是从自己的实现中加载类的字节...

    定义ClassLoader调用外部jar包

    默认情况下,Java使用系统ClassLoader(Bootstrap ClassLoader)加载JDK核心库,然后是Extension ClassLoader加载扩展库,最后是App ClassLoader加载应用类路径(ClassPath)下的类。当这些默认ClassLoader无法满足...

    Java ClassLoader定制实例

    在实际应用中,我们可以通过反射API来使用自定义ClassLoader加载的类。例如,我们可以创建一个`Class`对象,然后调用`newInstance()`方法来创建该类的实例。 总结来说,Java ClassLoader的定制是一项强大的技术,它...

    ClassLoader运行机制 自己写的

    3. System ClassLoader(也称为AppClassLoader):加载`CLASSPATH`环境变量指定的类,以及应用主类路径(class path)上的类。 4. WebLogic特定的ClassLoaders: - Ear ClassLoader:加载EAR应用的全局库(如lib...

    ClassLoader小例子

    - 自定义ClassLoader通常需要重写`loadClass()`方法,该方法在找不到类时调用`findClass()`进行实际的加载操作。 - 在`ClassLoaderDemo`这个例子中,可能就展示了如何创建一个自定义的ClassLoader,从非标准位置...

    classloader

    3. 如果类还未加载,ClassLoader会在指定的路径(例如类路径,classpath)下寻找对应的.class文件。 4. 找到类文件后,ClassLoader读取文件内容并将其转换为字节码。 5. 接下来,字节码会被验证确保符合Java语言规范...

    ClassLoader(类加载机制)1

    // 自定义ClassLoader加载 this.getClass().getClassLoader().loadClass("com.anbai.sec.classloader.TestHelloWorld"); ``` 这两种方式在需要动态加载未知类或延迟初始化类的场景下非常有用,比如插件系统、热...

    JVM ClassLoader简析

    这些代码可能展示了如何创建自定义ClassLoader,以及如何使用ClassLoader加载非标准位置的类。通过分析这些示例,我们可以更好地理解ClassLoader的工作机制。 总的来说,理解和掌握JVM ClassLoader对于优化Java应用...

    ClassLoader动态加载dex

    为了实现动态加载,我们需要创建自定义的ClassLoader,并重写其关键方法,如`findClass()`。 首先,我们要理解APK的加载过程。当Android系统启动一个应用时,会通过PathClassLoader加载APK中的`classes.dex`文件,...

    android 动态加载class

    总结起来,Android 动态加载Class涉及到的关键技术包括:自定义ClassLoader、Dex文件操作、反射、权限管理以及Android的类加载机制。这一技术在提高程序灵活性和维护性的同时,也需要开发者对Android系统的深入了解...

Global site tag (gtag.js) - Google Analytics