要自定义加载器,要继承ClassLoader,很多情况是直接继承子类UrlClassLoader
BootstrapClassLoader 加载class文件的路径定义在key:sun.boot.class.path
System.getProperty("sun.boot.class.path");
同样:
扩展类加载器ExtClassLoader 加载class文件的路径定义在key:java.ext.dirs中
应用(系统)类加载器AppClassLoader 加载class文件的路径定义在key:java.class.path中
在类加载器ClassLoader中类加载的过程:
protected ClassLoader() {
// 方法getSystemClassLoader得到AppClassLoader
this(checkCreateClassLoader(), getSystemClassLoader());
}
通过loadClass方法得到 需要加载的类的Class对象。
public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false);
}
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
//是否已经被加载如果已经加载则返回对应的Class
Class c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
//通过父加载器加载。
//大多数加载class执行过程:最后追续到ExtClassLoader。又因ExtClassLoader的parent=null。则进行findBootstrapClassOrNull[通过bootstrap class loader加载器] 进行加载。BootstrapClassLoader加载失败后。再通过ExtClassLoader.findClass(name)方法进行加载。如果还没有加载成功再通过AppClassLoader.findClass(name)加载(一般情况[没有自定义加载器]在这一步骤都会加载成功。返回class);依次执行。最终调用自定义的加载器的findClass(name)方法进行加载。(代码如下:)
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
c = findClass(name);
}
}
return c;
}
}
自定义加载器:
//必须extends ClassLoader
public class MyClassLoader extends ClassLoader{
//无参的构造方法,用于class.newInstance()构造对象使用
public MyClassLoader(){
}
@Override
//实现findClass方法。
protected Class<?> findClass(String name) throws ClassNotFoundException {
//class文件的路径 (自定义的文件路径)
String classPathFile = classDir + "/" + name + ".class";
try {
// 需要生成字节流
FileInputStream fis = new FileInputStream(classPathFile);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
encodeAndDecode(fis,bos);
byte[] classByte = bos.toByteArray();
//将字节流变成一个class 。必须调用这个方法。
// defineClass是ClassLoader的方法
return defineClass(classByte,0,classByte.length);
} catch (Exception e) {
e.printStackTrace();
}
return super.findClass(name);
}
}
defineClass最终调用三个本地方法:
private native Class defineClass0(String name, byte[] b, int off, int len,
ProtectionDomain pd);
private native Class defineClass1(String name, byte[] b, int off, int len,
ProtectionDomain pd, String source);
private native Class defineClass2(String name, java.nio.ByteBuffer b,
int off, int len, ProtectionDomain pd,
String source);
classloader2
最新推荐文章于 2024-10-02 20:28:37 发布