java类加载器要点整理
所属分类 java
浏览量 1781
启动类加载器 BootstrapClassLoader
扩展类加载器 ExtClassLoader
应用类加载器 AppClassLoader
自定义加载器
JAVA_HOME/lib
lib/ext
classpath
加载路径
System.out.println("boot:"+System.getProperty("sun.boot.class.path"));
System.out.println("ext:"+System.getProperty("java.ext.dirs"));
System.out.println("app:"+System.getProperty("java.class.path"));
//加载器之间的层级关系
public class ClassLoaderTest {
public static void main(String[] args) {
ClassLoader loader = ClassLoaderTest.class.getClassLoader();
while (loader != null) {
System.out.println(loader.toString());
loader = loader.getParent();
}
}
}
// 没有显示引导类加载器,获取引导类加载器时,返回null。
sun.misc.Launcher$AppClassLoader@xxx
sun.misc.Launcher$ExtClassLoader@xxx
双亲委派模型
自定义类加载器且不破坏双亲委派模型,继承ClassLoader类并重写findClass方法。
自定义类加载器且破坏双亲委派模型,继承ClassLoader类并重写findClass方法 和 loadClass方法。
ClassLoader.getSystemClassLoader() 获取应用加载器
自定义类加载器继承ClassLoader,一般是继承URLClassLoader
public class MyClassLoader extends ClassLoader {
protected Class> findClass(String name) throws ClassNotFoundException {
byte[] bytes = readClassBytes(name);
if (bytes == null) {
throw new ClassNotFoundException();
}else{
return defineClass(name, bytes, 0, bytes.length);
}
}
URL url1 = new URL("file:///Users/dugang/my/classes/");
URL url2 = new URL("file:///Users/dugang/my/lib/xxx.jar");
URLClassLoader ucl = new URLClassLoader(new URL[]{url1,url2});
Class cls = ucl.loadClass("dyyx.my.Cat");
Class cls2 = Class.forName("dyyx.my.Cat",true,ucl);
上下文类加载器 父类加载器使用子类加载器 加载类
SPI jdbc
//建立数据库连接各个不同参数的方法最终都会走到这里
private static Connection getConnection(
String url, java.util.Properties info, Class> caller) throws SQLException {
//获取调用者的类加载器
ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
synchronized(DriverManager.class) {
//如果为null,则使用上下文类加载器
//这里是重点,什么时候类加载器才会为null? 当然就是由根类加载器加载的类了
if (callerCL == null) {
callerCL = Thread.currentThread().getContextClassLoader();
}
}
//...
for(DriverInfo aDriver : registeredDrivers) {
//使用上下文类加载器去加载驱动
if(isDriverAllowed(aDriver.driver, callerCL)) {
try {
//如果加载成功,则进行连接
Connection con = aDriver.driver.connect(url, info);
//...
} catch (SQLException ex) {
if (reason == null) {
reason = ex;
}
}
}
//...
}
}
类隔离 热部署 热替换
tomcat 类加载机制
jsp热部署
类加载常见错误
ClassNotFoundException
ClassNotFoundError
NoClassDefFoundError
ClassCastException
java.lang.LinkageError: loader (instance of dyyx/my/MyClassLoader): attempted duplicate class definition for name: "dyyx/my/Cat"
重复加载相同的类会报错 ,因此热部署时,需要把classload一起替换掉
-XX:+TraceClassLoading
-XX:+TraceClassUnloading
类名错误
jar包没有引入
jar 包冲突
测试代码
ClassLoadTest.java
package dyyx.my;
public class ClassLoadTest extends ClassLoader {
public static void main(String[] args) throws Exception {
ClassLoader loader = ClassLoadTest.class.getClassLoader();
while (loader != null) {
System.out.println(loader.toString());
loader = loader.getParent();
}
System.out.println("boot:"+System.getProperty("sun.boot.class.path"));
System.out.println("ext:"+System.getProperty("java.ext.dirs"));
System.out.println("app:"+System.getProperty("java.class.path"));
System.out.println(ClassLoader.getSystemClassLoader());
System.out.println(System.getProperty("java.system.class.loader"));
// -XX:+TraceClassLoading
// [Loaded dyyx.my.ClassLoadTest from file:/Users/dugang/fun/hellocode/bin/]
try{
Class.forName("x.y.z.A");
}catch(Throwable e){
// java.lang.ClassNotFoundException: x.y.z.A
System.out.println(e);
}
String className = "dyyx.my.Hello";
Class cls = ClassLoader.getSystemClassLoader().loadClass(className);
// 类不会初始化
// class1=class dyyx.my.Hello
System.out.println("class1="+cls);
try{
// 类初始化异常
cls = Class.forName(className);
System.out.println("class2="+cls);
}catch(Throwable e){
// java.lang.ExceptionInInitializerError
System.out.println(e);
}
try{
Hello.hello();
}catch(Throwable e){
// java.lang.NoClassDefFoundError: Could not initialize class dyyx.my.Hello
System.out.println(e);
}
}
}
Hello.java
package dyyx.my;
import java.util.Date;
public class Hello {
static{
boolean flag = true;
if(flag){
throw new RuntimeException("hello static init error");
}
}
public static void hello(){
System.out.println("hello,"+new Date());
}
}
上一篇
下一篇
JMX配置及java客户端远程连接JMX端口
AQS要点整理
自定义类加载器例子
kibana安装配置及使用
elasticsearch7.0压测问题记录
elasticsearch工具