- 类的生命周期
- 类加载器种类
Bootstrap ClassLoader:根类加载器,加载jdk/lib下的类。
Extention ClassLoader:扩展类加载器,加载jdk/lib/extention下的类,jdk9后改为Platform ClassLoader。
Application CalssLoader:应用程序类加载器,加载普通的应用程序。
package example;
import javax.xml.crypto.Data;
public class Test1 {
public static void main(String[] args) {
System.out.println("--- current app");
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
while (classLoader != null) {
System.out.println(classLoader.toString());
classLoader = classLoader.getParent();
}
System.out.println("--- class String");
classLoader = String.class.getClassLoader();
while (classLoader != null) {
System.out.println(classLoader.toString());
classLoader = classLoader.getParent();
}
System.out.println("--- class javax.xml.crypto.Data");
classLoader = Data.class.getClassLoader();
while (classLoader != null) {
System.out.println(classLoader.toString());
classLoader = classLoader.getParent();
}
}
}
运行结果:
--- current app
jdk.internal.loader.ClassLoaders$AppClassLoader@512ddf17
jdk.internal.loader.ClassLoaders$PlatformClassLoader@54a097cc
--- class String
--- class javax.xml.crypto.Data
jdk.internal.loader.ClassLoaders$PlatformClassLoader@54a097cc
- 类加载机制
双亲委派机制:
线程应用上下文加载器:
Thread.currentThread().getContextClassLoader() // 获取当前线程的类加载器
Thread.currentThread().setContextClassLoader(classLoader) // 设置当前线程类加载器
如果没有设置默认继承父线程的类上下文加载器
package example;
public class Test3 {
public static void main (String[] args) throws InterruptedException {
System.out.println(Thread.currentThread().getContextClassLoader().toString());
Thread t1 = new Thread(() -> {
run();
});
t1.start();
Thread t2 = new Thread(() -> {
run();
});
t2.setContextClassLoader(new Test2.TestClassLoader());
t2.start();
}
public static void run() {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
System.out.println(loader.toString());
try {
loader.loadClass("example.Test1");
System.out.println("load success");
} catch (ClassNotFoundException e) {
System.out.println("load fail");
}
}
}
运行结果:
jdk.internal.loader.ClassLoaders$AppClassLoader@512ddf17
jdk.internal.loader.ClassLoaders$AppClassLoader@512ddf17
load fail
example.Test2$TestClassLoader@3d24753a
/Users/qiuyingzhai/kuaishou-java/quality/class-loader/target/test-classes/example/Test1.class
load success
-
类加载方式
ClassLoader loader = ClassLoader.getSystemClassLoader();
Class cls = loader.loadClass(“com.example.Test”); // 会findClass并且加载Class cls = Class.forName(“com.example.Test”); // 不会findClass
-
自定义类加载器
为什么要自定义类加载器
如何自定义加载器
package example;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test2 {
public static class TestClassLoader extends ClassLoader {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
String path = "/quality/class-loader/src/main/java/" + name.replaceAll("\\.", "\\/");
System.out.println(path);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try {
InputStream inputStream = new FileInputStream(path);
byte[] bytes = new byte[2048];
int len = 0;
while ((len = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
byte[] bytes = outputStream.toByteArray();
return defineClass(name, bytes, 0, bytes.length);
}
}
public static void main (String[] args)
throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException,
InstantiationException {
ClassLoader classLoader = new TestClassLoader();
Class T = classLoader.loadClass("example.Test1");
Object t = T.getConstructor(null).newInstance(null);
Method m = T.getMethod("main", new String[0].getClass());
m.invoke(null, (Object) new String[0]);
}
}
运行结果:
--- current app
jdk.internal.loader.ClassLoaders$AppClassLoader@512ddf17
jdk.internal.loader.ClassLoaders$PlatformClassLoader@54a097cc
--- class String
--- class javax.xml.crypto.Data
jdk.internal.loader.ClassLoaders$PlatformClassLoader@54a097cc