JVM类加载器的认识
对类的加载器进行认识:
public class ClassLoaderTest {
public static void main(String[] args) {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
System.out.println(loader);
System.out.println(loader.getParent());
System.out.println(loader.getParent().getParent());
}
}
sun.misc.Launcher$AppClassLoader@64fef26a sun.misc.Launcher$ExtClassLoader@1ddd40f3 null会发现,找到了ApplicationClassLoader和ExtClassLoader,但是没有找到ExtClassLoader的父加载器BootstrapClassLoader,原因是BootstrapClassLoader使用C语言实现的,并不是用java语言做的,所以是不能返回一个确定的父加载器的方法,所以才返回了NULL。
而在Java中,类加载器的结构为:
注意:这里的父类加载器并不是通过集成的方式来实现的,而是通过类组合的方式实现的。
类加载器大致分为三类:
第一、启动类加载器。(BootStrapt ClassLoader)
启动类加载器,负责加载存放在JDK/jre/lib目录下的类库,比如:rt.jar。启动类加载器是无法被Java程序直接引用的。
第二、扩展类加载器。(Ext ClassLoader)
扩展类加载器,负责加载JDK/jre/lib/ext目录下的所有类库。开发者是可以直接使用扩展类加载器。
第三、应用程序类加载器。(Application ClassLoader)
应用程序类加载器,负责加载用户类路径(classpath)所指定的类,开发者可以直接使用该类加载器,如果引用程序没有自定义过自己的类加载器,一般情况这就是程序默认的类加载器。
同时,可以实现自定义类加载器:
通常情况下,我们都是直接使用系统自带的类加载器。但是,有的时候,我们也需要自定义类加载器。那图和实现呢?
自定义类加载器一般都是继承自ClassLoader类,从上面对loadClass方法来分析看,只需要重写findClass方法即可。
自定义类加载器的应用场景:比如对字节码进行了加密之后,可以通过自定义类加载器来实现解密。
package com.hui;
import java.io.*;
public class MyClassLoader extends ClassLoader {
private String root;
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] classData = loadClassData(name);
if (classData == null) {
throw new ClassNotFoundException();
} else {
return defineClass(name, classData, 0, classData.length);
}
}
private byte[] loadClassData(String className) {
String fileName = root + File.separatorChar + className.replace('.', File.separatorChar) + ".class";
try {
InputStream ins = new FileInputStream(fileName);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int length = 0;
while ((length = ins.read(buffer)) != -1) {
baos.write(buffer, 0, length);
}
return baos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public String getRoot() {
return root;
}
public void setRoot(String root) {
this.root = root;
}
public static void main(String[] args) {
MyClassLoader classLoader = new MyClassLoader();
classLoader.setRoot("E:\\temp");
Class<?> testClass = null;
try {
testClass = classLoader.loadClass("com.neo.classloader.Test2");
Object object = testClass.newInstance();
System.out.println(object.getClass().getClassLoader());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
查看5道真题和解析