自己写写对Java ClassLoader的理解,
首先ClassLoader分为:
Bootstrap ClassLoader/启动类加载器
主要负责jdk_home/lib目录下的核心 api 或 -Xbootclasspath 选项指定的jar包装入工作。
Extension ClassLoader/扩展类加载器
主要负责jdk_home/lib/ext目录下的jar包或 -Djava.ext.dirs 指定目录下的jar包装入工作。
System ClassLoader/系统类加载器
主要负责java -classpath/-Djava.class.path所指的目录下的类与jar包装入工作。
User Custom ClassLoader/用户自定义类加载器(java.lang.ClassLoader的子类)
在程序运行期间, 通过java.lang.ClassLoader的子类动态加载class文件, 体现java动态实时类装入特性。
关系如下:
具体类的实现关系如下:
自定义类加载器加载一个类的步骤步骤,使用的双亲委托加载模式:
为什么要使用这种双亲委托模式呢?
因为这样可以避免重复加载,当父亲已经加载了该类的时候,就没有必要子ClassLoader再加载一次。
考虑到安全因素,我们试想一下,如果不使用这种委托模式,那我们就可以随时使用自定义的String来动态替代java核心api中定义类型,这样会存在非常大的安全隐患,而双亲委托的方式,就可以避免这种情况,因为String已经在启动时被加载,所以用户自定义类是无法加载一个自定义的ClassLoader。
下面写一段代码用于观察其加载过程:
public class ClassLoaderTree {
public static void main(String[] args) {
ClassLoader loader = ClassLoaderTree.class.getClassLoader();
while (loader != null) {
System.out.println(loader.toString());
loader = loader.getParent();
}
}
}
结果观察一下,看看是不是跟想的一样。
上网去查classloader的资料,都叫我们自己如果要自定义classloader用于加载的类话,就只需重写findclass就行了,为什么了?自己看看了ClassLoader源码后,写了一个简易版的,很好理解。
import java.util.Hashtable;
import java.io.FileInputStream;
public class SimpleClassLoader extends ClassLoader {
private Hashtable classes = new Hashtable();
public SimpleClassLoader() {
}
/**
*
* 函数用于查找返回自定义class文件的二进制文件
*/
private byte findclass(String className)[] {
System.out.println(" >>>>>> 查找 返回类 "+className);
byte result[];
try {
FileInputStream fi = new FileInputStream("store\\"+className+".impl");
result = new byte[fi.available()];
fi.read(result);
return result;
} catch (Exception e) {
/*
* If we caught an exception, either the class wasnt found or it
* was unreadable by our process.
*/
return null;
}
}
/**
* loadClass 用于加载类(根据类名字符串)
*/
public Class loadClass(String className) throws ClassNotFoundException {
return (loadClass(className, true));
}
/**
* 加载类的具体过程
*/
public synchronized Class loadClass(String className, boolean resolveIt)
throws ClassNotFoundException {
Class result;
byte classData[];
System.out.println(" >>>>>>加载 class : "+className);
/* Check our local cache of classes */
result = (Class)classes.get(className);
if (result != null) {
System.out.println(" >>>>>> 返回已经加载的class.");
return result;
}
/* Check with the primordial class loader */
try {
result = super.findSystemClass(className);
System.out.println(" >>>>>> 从CLASSPATH中返回已经加载的类");
return result;
} catch (ClassNotFoundException e) {
System.out.println(" >>>>>> CLASSPATH中没有这个类.");
}
/* 自定读取class */
classData = findclass(className);
if (classData == null) {
throw new ClassNotFoundException();
}
/* 定义类 (分析 class 文件) */
result = defineClass(classData, 0, classData.length);
if (result == null) {
throw new ClassFormatError();
}
if (resolveIt) {
resolveClass(result);//解析class文件
}
classes.put(className, result);
System.out.println(" >>>>>> 返回 这个新加载 class.");
return result;
}
}
- 大小: 14.1 KB
- 大小: 30.8 KB
- 大小: 24.7 KB
分享到:
相关推荐
Java ClassLoader定制实例
java classloader classpath 张孝祥
Java ClassLoader Tutorial
理解Java ClassLoader机制
NULL 博文链接:https://sbiigu.iteye.com/blog/260456
java classloader 讲义-淘宝网
Understanding the Java ClassLoader
java classLoader 的全面讲解 从基本概念到具体的应用 里面共有三份资料。
Understanding the Java ClassLoader.pdf
Sun 官方关于 ClassLoader原理的文章,值得一看
破解java加密的ClassLoader.java,在classloader植入破解代码
内容简介: ClassLoader体系结构 类装载器在JVM中并不是唯一的,JVM自带了三个装载器,用户也可以根据自己的需求自定义新的装载器,这些装载器的体系结构可以看作是树状结构,如图1所示:
了解 Java ClassLoader
ClassLoader类加载器讲解,理解JAVA类加载机制
Java ClassLoader 是一个重要的、但又常常被人忽略的 Java 运行时系统组件。它是负责在运行时查找和装入类文件的类。创建自己的 ClassLoader 可以以实用且有趣的方式定制 JVM,这样可以让您彻底重新定义如何将类文件...
深入了解Java_ClassLoader,Bytecde.pdf
主要内容包括 Java类加载机制及加载流程,以及如何定义自己的类加载器,如何实现类的热替换。