Java ClassLoader

自己写写对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动态实时类装入特性。

关系如下:
[img]http://dl.iteye.com/upload/attachment/452558/4b198894-339d-3cd7-88ff-eafa1fa58615.jpg[/img]
具体类的实现关系如下:
[img]http://dl.iteye.com/upload/attachment/452560/b2d7f29b-0df4-37dc-b460-31c9d9f5d1df.jpg[/img]

自定义类加载器加载一个类的步骤步骤,使用的双亲委托加载模式:
[img]http://dl.iteye.com/upload/attachment/452562/4efa4f8a-094f-392d-83c2-281fe0c60f3d.jpg[/img]

为什么要使用这种双亲委托模式呢?

因为这样可以避免重复加载,当父亲已经加载了该类的时候,就没有必要子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;
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值