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>
-
ClassLoader classLoader =
new
URLClassLoader(urls);
-
Thread.currentThread().setContextClassLoader(classLoader);
-
Class clazz=classLoader.loadClass("com.company.MyClass"
);
-
-
Method taskMethod = clazz.getMethod("doTask"
, String.
class
, String.
class
);
-
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
分享到:
相关推荐
本文将详细讲解类加载的流程、类加载器的层次结构以及双亲委派模型。 1. **类加载的生命周期** 类的生命周期包括7个阶段:加载、验证、准备、解析、初始化、使用和卸载。 - **加载**:从指定的位置(如类路径、...
### JVM加载Class文件详解 #### 一、Java与JVM中的Class文件加载机制概述 Java作为一种动态性极强的解释型编程语言,在程序运行时,Java虚拟机(JVM)负责将编译生成的`.class`文件加载到内存中进行执行。在Java...
接着,Extension ClassLoader加载扩展类库,然后是App ClassLoader加载应用程序的类路径下的类。每个ClassLoader都有其父ClassLoader,它们形成了一个层次结构,子ClassLoader可以委托父ClassLoader去加载类,避免了...
这种委托加载机制保证了类的唯一性,防止了同一个类被不同ClassLoader加载两次的问题。 ClassLoader还有自定义的概念,允许开发者创建自己的ClassLoader来实现特定的加载逻辑。例如,从网络、数据库或特定文件系统...
JVM 首先启动 bootstrap classloader,该 ClassLoader 加载 Java 核心 API,然后调用 ExtClassLoader 加载扩展 API,最后 AppClassLoader 加载 CLASSPATH 目录下定义的 Class,这就是一个程序最基本的加载流程。...
通过对`ClassLoader`的基本概念、工作原理、双亲委托机制以及不同类型的类加载器的了解,我们可以更好地理解Java类加载的过程及其背后的设计哲学。这对于深入理解Java虚拟机的内部机制以及开发高质量的应用程序都至...
- **`findClass()`方法**:重写`ClassLoader`中的`findClass()`方法,该方法用于实际加载类的二进制数据。首先调用`loadClassData()`方法从文件系统读取类文件数据,然后使用`defineClass()`方法将二进制数据转换为`...
- 自定义ClassLoader通常需要重写`loadClass()`方法,该方法在找不到类时调用`findClass()`进行实际的加载操作。 - 在`ClassLoaderDemo`这个例子中,可能就展示了如何创建一个自定义的ClassLoader,从非标准位置...
3. 如果类还未加载,ClassLoader会在指定的路径(例如类路径,classpath)下寻找对应的.class文件。 4. 找到类文件后,ClassLoader读取文件内容并将其转换为字节码。 5. 接下来,字节码会被验证确保符合Java语言规范...
最后,App ClassLoader加载的是应用类路径(ClassPath)中的类。 ClassLoader的工作流程主要包含以下步骤: 1. **查找类**:当JVM需要加载一个类时,ClassLoader会根据类名(全限定名,如`java.lang.String`)在...
自定义ClassLoader则允许我们插入这个流程,按照自己的规则去查找和加载类。 在自定义ClassLoader时,主要需要覆写两个关键方法:`findClass()` 和 `loadClass()`。`loadClass()` 方法通常用于委托父类加载器加载类...
ClassLoader的工作流程包括查找、加载和验证。当一个类被请求加载时,ClassLoader首先检查该类是否已经被加载。如果未加载,它会根据类的全名(包括包名)来寻找对应的.class文件。这个过程通常涉及到从文件系统或...
ClassLoader的工作流程可以分为三个主要步骤: 1. **查找**:当需要加载一个类时,ClassLoader首先会检查该类是否已经被加载过。如果已经加载,则直接返回;如果没有,就会继续下一步。 2. **加载**:ClassLoader...
3. System ClassLoader(系统类加载器):也称为应用程序类加载器,由sun.misc.Launcher$AppClassLoader实现,负责加载通过-classpath或-Djava.class.path指定的路径中的类和jar包。 这三种类加载器遵循双亲委派...
- Bootstrap ClassLoader加载JDK的核心库,如rt.jar。 - Extension ClassLoader加载Java扩展目录下的jar文件。 - AppClassLoder(也叫System ClassLoader)加载应用类路径(classpath)中的类。 2. **类加载机制...
ClassLoader的工作流程遵循父亲委托模型(Parent Delegation Model)。当一个类加载器接收到加载类的请求时,它首先将请求委托给其父类加载器,只有当父类加载器无法找到或加载该类时,子类加载器才会尝试自己去加载...
Java中的类加载器(ClassLoader)是Java虚拟机(JVM)的一个重要组成部分,它负责将类的.class文件从文件系统或者网络中加载到内存中,并转换为对应的Class对象。类加载器的工作流程主要包括加载、验证、准备、解析...
Java 类加载器是Java虚拟机(JVM)的核心组成部分,它负责将编译后的字节码文件(.class文件)加载到JVM中并转换为运行时的数据结构。Tomcat,作为广泛使用的Java Servlet容器,它自定义了一套类加载机制,以满足Web...
Android类加载器(ClassLoader)是Android系统中负责查找和加载类的重要组件。在深入理解Android的ClassLoader之前,我们先回顾一下Java的类加载机制。Java的类加载采用的是双亲委派模型,即当一个类加载器需要加载...