Java类加载/ClassLoader

(1) JVM中ClassLoader的类型

JVM预定义了三种类型类加载器,当一个 JVM 启动的时候,Java 缺省开始使用如下三种类型类装入器:Bootstrap类加载器:引导类加载器是用本地代码实现的类装入器,它负责将 <Java_Runtime_Home>/lib 下面的类库加载到内存中。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作。Extension类加载器:扩展类加载器是由 Sun 的 ExtClassLoader(sun.misc.Launcher$ExtClassLoader) 实现的。它负责将 < Java_Runtime_Home >/lib/ext 或者由系统变量 java.ext.dir 指定位置中的类库加载到内存中。开发者可以直接使用标准扩展类加载器。System类加载器:系统类加载器是由 Sun 的 AppClassLoader(sun.misc.Launcher$AppClassLoader)实现的。它负责将系统类路径(CLASSPATH)中指定的类库加载到内存中。开发者可以直接使用系统类加载器。可以通过 ClassLoader.getSystemClassLoader() 来获取它。

ExtClassLoader和AppClassLoader都是继承自URLClassLoader。

(2) 类加载的规则

类加载规则有两个:1双亲委托2 类A引用到类B,则由类A的加载器去加载类B,保证引用到的类由同一个加载器加载JVM在加载类时默认采用的是双亲委托机制。通俗的讲,就是某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。

ClassLoader在运行期会以父/子的层次结构存在,每个classLoader 实例都有其父ClassLoader的引用,而父ClassLoader并没有持有子ClassLoader的引用,从而形成一条单向链,当一个类装载请求提交到某个ClassLoader时,默认的类装载过程如下:1. 检查这个类有没有被装载过,如果已经装载过,,返回 2. 调用父ClassLoader去装载类,如果装载成功返回. 3. 调用自身的装载类方法,如果装载成功则返回 4. 如查都没有成功,抛出ClassNotFoundException. 简单说,当ClassLoader链上的某一ClassLoader收到类装载请求时,会按顺序向上询问其所有父节点,直到boot classLoader.任何一个节点成功受理了此请求,则返回,如果所有父节点都不能受理,这个时候才由请求的ClassLoader自身来装载这个类,如果仍不能装载,则抛出异常.可以使用JVM参数-verbose:class来打印类的加载log.

(3) 类加载的方法

(4) 代码实例

在eclipse工程的当前目录下建立一个文件./cp/test/MyClass.java

package test;public class MyClass {}

进入cp目录下,编译此文件,生成MyClass.class

javac test/MyClass.java

运行下面的代码

package learning.classloader;import java.io.BufferedReader;import java.io.File;import java.io.InputStream;import java.io.InputStreamReader;import java.lang.reflect.Method;import java.net.URL;import java.net.URLClassLoader;public class ClassLoaderTest {public static void main(String[] args) throws Exception {try {Class.forName("test.MyClass");} catch (ClassNotFoundException e) {System.out.println("Failed to load MyClass");}File myClassDir = new File("./cp");URLClassLoader sysCl = (URLClassLoader) ClassLoader.getSystemClassLoader();Method addUrlMethod = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{URL.class});addUrlMethod.setAccessible(true);addUrlMethod.invoke(sysCl, myClassDir.toURI().toURL());Class c = Class.forName("test.MyClass");System.out.println("Loaded MyClass successfully");URLClassLoader clNew = new URLClassLoader(sysCl.getURLs(), sysCl.getParent());Class c1 = clNew.loadClass("test.MyClass");System.out.println(c.equals(c1));System.out.println(c.getClassLoader());System.out.println(c1.getClassLoader());System.out.println();InputStream is1 = c.getResourceAsStream("MyClass.java");BufferedReader reader = new BufferedReader(new InputStreamReader(is1));String s;while ((s = reader.readLine()) != null) {System.out.println(s);}reader.close();System.out.println();InputStream is2 = c.getResourceAsStream("/test/MyClass.java");reader = new BufferedReader(new InputStreamReader(is2));while ((s = reader.readLine()) != null) {System.out.println(s);}reader.close();System.out.println();InputStream is3 = sysCl.getResourceAsStream("test/MyClass.java");reader = new BufferedReader(new InputStreamReader(is3));while ((s = reader.readLine()) != null) {System.out.println(s);}reader.close();}}那段雨骤风狂。人生之旅本就是风雨兼程,是要说曾经拥有,

Java类加载/ClassLoader

相关文章:

你感兴趣的文章:

标签云: