美文网首页
自己实现Classloader加载自定义java.lang.Ma

自己实现Classloader加载自定义java.lang.Ma

作者: wuli白 | 来源:发表于2020-04-01 14:34 被阅读0次

自定义加载器实现

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.开头的类的

相关文章

网友评论

      本文标题:自己实现Classloader加载自定义java.lang.Ma

      本文链接:https://www.haomeiwen.com/subject/yrcouhtx.html