JAVA 双亲委派及如何打破
双亲委派原则解释
java为了类加载安全定义了一个原则,那就是双亲委派原则
解释:所有类的加载都被委派给父类加载,只有父类不能加载的时候才由子类加载
由此才能保证java类的安全,因为用户不能随便自定义修改java类库中的类
双亲委派模型图
如何打破这种加载模型
- 继承ClassLoader类
- 重写loadClass方法
package com.bamdow.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
public class TestClassLoader {
static{
System.out.println("static block init");
}
public TestClassLoader() {
System.out.println("constructer init");
}
public static void main(String[] args) {
//自定义类加载器
ClassLoader classLoader = new ClassLoaderDelegate(TestClassLoader.class.getResource("/").getPath());
try {
Class b = TestClassLoader.class.getClassLoader().loadClass(TestClassLoader.class.getName());
b.newInstance();
Class a = classLoader.loadClass(TestClassLoader.class.getName());
a.newInstance();
System.out.println("a="+a+",hash="+a.hashCode());
System.out.println("b="+b+",hash="+b.hashCode());
System.out.println(a==b);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
static class ClassLoaderDelegate extends ClassLoader{
private String path;
protected ClassLoaderDelegate(String path) {
super();
this.path = path;
}
public Class<?> loadClass(String name)
throws ClassNotFoundException {
//System.out.println("loadclass..."+name);
if(!TestClassLoader.class.getName().equals(name)){
return super.loadClass(name);
}
byte[] classBytes = null;
try( InputStream in = new FileInputStream(path+name.replaceAll("\\.", "/")+".class")){
classBytes = new byte[(int)in.available()];
in.read(classBytes);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Class<?> clazz = defineClass(name, classBytes, 0, classBytes.length);
return clazz;
}
}
}
总结
- 双亲委派漏洞是jdk早起版本出现的,后面sun公司为了自己的API承诺为屏蔽方法重写。如果要自定义类加载请重写findclass方法
- 因为所亲委派的出现,因此所有的类只会有一个类加载加载,也因此static静态模块只会执行一次,但是当我们重写loadClass方法之后,类肯能被多个类加载器执行,也因此类的静态模块就可以执行多次。