自定义加载器实现
public class MyClassLoader extends ClassLoader {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
try{
String className = null;
if(name.startsWith("java.lang")){
className = "/" + name.replace('.', '/') + ".class";
}else{
className = name.substring(name.lastIndexOf('.') + 1) + ".class";
}
InputStream is = getClass().getResourceAsStream(className);
if (is == null) {
return super.loadClass(name);
}
byte[] b = new byte[is.available()];
is.read(b);
return defineClass(name, b, 0, b.length);
}catch (Exception e) {
e.printStackTrace();
throw new ClassNotFoundException();
}
}
}
Main方法
public class ClassLoaderTest {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
ClassLoader myLoader = new MyClassLoader();
Object obj = myLoader.loadClass("java.lang.MyMath").newInstance();
System.out.println(obj);
}
}
Math方法
package java.lang;
public final class Math {
public static void main(String[] args) {
System.out.println("hello world");
}
}
结果
java.lang.SecurityException: Prohibited package name: java.lang
at java.lang.ClassLoader.preDefineClass(ClassLoader.java:662)
at java.lang.ClassLoader.defineClass(ClassLoader.java:761)
at java.lang.ClassLoader.defineClass(ClassLoader.java:642)
at com.vivo.demo.classload.MyClassLoader.loadClass(MyClassLoader.java:37)
at com.vivo.demo.classload.ClassLoaderTest.main(ClassLoaderTest.java:14)
Exception in thread "main" java.lang.ClassNotFoundException
at com.vivo.demo.classload.MyClassLoader.loadClass(MyClassLoader.java:41)
at com.vivo.demo.classload.ClassLoaderTest.main(ClassLoaderTest.java:14)
classLoader里面有一个preDefineClass会判断加载的路径是以java.lang开头的会报错
private ProtectionDomain preDefineClass(String name,
ProtectionDomain pd)
{
if (!checkName(name))
throw new NoClassDefFoundError("IllegalName: " + name);
// Note: Checking logic in java.lang.invoke.MemberName.checkForTypeAlias
// relies on the fact that spoofing is impossible if a class has a name
// of the form "java.*"
if ((name != null) && name.startsWith("java.")) {
throw new SecurityException
("Prohibited package name: " +
name.substring(0, name.lastIndexOf('.')));
}
if (pd == null) {
pd = defaultDomain;
}
if (name != null) checkCerts(name, pd.getCodeSource());
return pd;
}
我们梳理一下过程,如果用自定义的类加载器加载我们自定义的类
1.会调用自定义类加载器的loadClass方法
2.而我们自定义的classLoader必须继承ClassLoader,loadClass方法会调用父类的defineClass方法
3.而父类的这个defineClass是一个final方法,无法被重写
4.所以自定义的classLoader是无论如何也不可能加载到以java.开头的类的
网友评论