`

ClassLoader加载class的 流程

阅读更多

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。

 

代码示例:

 

Java代码 <embed type="application/x-shockwave-flash" width="14" height="15" src="http://longdick.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=ClassLoader%20classLoader%20%3D%20new%20URLClassLoader(urls)%3B%0AThread.currentThread().setContextClassLoader(classLoader)%3B%0AClass%20clazz%3DclassLoader.loadClass(%22com.company.MyClass%22)%3B%2F%2F%E4%BD%BF%E7%94%A8loadClass%E6%96%B9%E6%B3%95%E5%8A%A0%E8%BD%BDclass%2C%E8%BF%99%E4%B8%AAclass%E6%98%AF%E5%9C%A8urls%E5%8F%82%E6%95%B0%E6%8C%87%E5%AE%9A%E7%9A%84classpath%E4%B8%8B%E8%BE%B9%E3%80%82%0A%0AMethod%20taskMethod%20%3D%20clazz.getMethod(%22doTask%22%2C%20String.class%2C%20String.class)%3B%2F%2F%E7%84%B6%E5%90%8E%E6%88%91%E4%BB%AC%E5%B0%B1%E5%8F%AF%E4%BB%A5%E7%94%A8%E5%8F%8D%E5%B0%84%E5%81%9A%E4%BA%9B%E4%BA%8B%E6%83%85%E4%BA%86%0AtaskMethod.invoke(clazz.newInstance()%2C%22hello%22%2C%22world%22)%3B" quality="high" allowscriptaccess="always" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>
  1. ClassLoader classLoader =  new  URLClassLoader(urls);  
  2. Thread.currentThread().setContextClassLoader(classLoader);  
  3. Class clazz=classLoader.loadClass("com.company.MyClass" ); //使用loadClass方法加载class,这个class是在urls参数指定的classpath下边。   
  4.   
  5. Method taskMethod = clazz.getMethod("doTask" , String. class , String. class ); //然后我们就可以用反射做些事情了   
  6. taskMethod.invoke(clazz.newInstance(),"hello" , "world" );  
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在某些应用场景还是比较适用,特别是需要灵活地动态加载class的时候。

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

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

本文作者:longdick   

分享到:
评论

相关推荐

    S18-ClassLoader类加载流程1

    本文将详细讲解类加载的流程、类加载器的层次结构以及双亲委派模型。 1. **类加载的生命周期** 类的生命周期包括7个阶段:加载、验证、准备、解析、初始化、使用和卸载。 - **加载**:从指定的位置(如类路径、...

    jvm 加载class文件

    ### JVM加载Class文件详解 #### 一、Java与JVM中的Class文件加载机制概述 Java作为一种动态性极强的解释型编程语言,在程序运行时,Java虚拟机(JVM)负责将编译生成的`.class`文件加载到内存中进行执行。在Java...

    Java ClassLoader定制实例

    接着,Extension ClassLoader加载扩展类库,然后是App ClassLoader加载应用程序的类路径下的类。每个ClassLoader都有其父ClassLoader,它们形成了一个层次结构,子ClassLoader可以委托父ClassLoader去加载类,避免了...

    JVM ClassLoader简析

    这种委托加载机制保证了类的唯一性,防止了同一个类被不同ClassLoader加载两次的问题。 ClassLoader还有自定义的概念,允许开发者创建自己的ClassLoader来实现特定的加载逻辑。例如,从网络、数据库或特定文件系统...

    Java ClassLoader学习总结

    JVM 首先启动 bootstrap classloader,该 ClassLoader 加载 Java 核心 API,然后调用 ExtClassLoader 加载扩展 API,最后 AppClassLoader 加载 CLASSPATH 目录下定义的 Class,这就是一个程序最基本的加载流程。...

    ClassLoader

    通过对`ClassLoader`的基本概念、工作原理、双亲委托机制以及不同类型的类加载器的了解,我们可以更好地理解Java类加载的过程及其背后的设计哲学。这对于深入理解Java虚拟机的内部机制以及开发高质量的应用程序都至...

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

    - **`findClass()`方法**:重写`ClassLoader`中的`findClass()`方法,该方法用于实际加载类的二进制数据。首先调用`loadClassData()`方法从文件系统读取类文件数据,然后使用`defineClass()`方法将二进制数据转换为`...

    ClassLoader小例子

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

    classloader

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

    理解Java ClassLoader机制

    最后,App ClassLoader加载的是应用类路径(ClassPath)中的类。 ClassLoader的工作流程主要包含以下步骤: 1. **查找类**:当JVM需要加载一个类时,ClassLoader会根据类名(全限定名,如`java.lang.String`)在...

    ClassLoader 案例

    自定义ClassLoader则允许我们插入这个流程,按照自己的规则去查找和加载类。 在自定义ClassLoader时,主要需要覆写两个关键方法:`findClass()` 和 `loadClass()`。`loadClass()` 方法通常用于委托父类加载器加载类...

    java classloader

    ClassLoader的工作流程包括查找、加载和验证。当一个类被请求加载时,ClassLoader首先检查该类是否已经被加载。如果未加载,它会根据类的全名(包括包名)来寻找对应的.class文件。这个过程通常涉及到从文件系统或...

    ClassLoader原理

    ClassLoader的工作流程可以分为三个主要步骤: 1. **查找**:当需要加载一个类时,ClassLoader首先会检查该类是否已经被加载过。如果已经加载,则直接返回;如果没有,就会继续下一步。 2. **加载**:ClassLoader...

    classloader体系结构(含hotswap)

    3. System ClassLoader(系统类加载器):也称为应用程序类加载器,由sun.misc.Launcher$AppClassLoader实现,负责加载通过-classpath或-Djava.class.path指定的路径中的类和jar包。 这三种类加载器遵循双亲委派...

    了解Java ClassLoader

    - Bootstrap ClassLoader加载JDK的核心库,如rt.jar。 - Extension ClassLoader加载Java扩展目录下的jar文件。 - AppClassLoder(也叫System ClassLoader)加载应用类路径(classpath)中的类。 2. **类加载机制...

    深入java虚拟机(七)深入源码看java类加载器ClassLoader 1

    ClassLoader的工作流程遵循父亲委托模型(Parent Delegation Model)。当一个类加载器接收到加载类的请求时,它首先将请求委托给其父类加载器,只有当父类加载器无法找到或加载该类时,子类加载器才会尝试自己去加载...

    java中classLoader的使用

    Java中的类加载器(ClassLoader)是Java虚拟机(JVM)的一个重要组成部分,它负责将类的.class文件从文件系统或者网络中加载到内存中,并转换为对应的Class对象。类加载器的工作流程主要包括加载、验证、准备、解析...

    java类加载器-tomcat中的类加载器

    Java 类加载器是Java虚拟机(JVM)的核心组成部分,它负责将编译后的字节码文件(.class文件)加载到JVM中并转换为运行时的数据结构。Tomcat,作为广泛使用的Java Servlet容器,它自定义了一套类加载机制,以满足Web...

    详解Android类加载ClassLoader

    Android类加载器(ClassLoader)是Android系统中负责查找和加载类的重要组件。在深入理解Android的ClassLoader之前,我们先回顾一下Java的类加载机制。Java的类加载采用的是双亲委派模型,即当一个类加载器需要加载...

Global site tag (gtag.js) - Google Analytics