JVM的类加载器与双亲委派模型

类加载器

  • 启动类加载器(Bootstrap ClassLoader):

    加载java的核心类,无法被java程序直接引用。

  • 扩展类加载器(ectensions class loader):

    加载java扩展目录下的一些指定的类库。

  • 系统类加载器(System class loader):

    加载开发时指定目录下的代码,一般来说java应用的类的加载都是通过它来完成的。

  • 自定义加载器:

    继承ClassLoader,重写findClass。例如:

    public class MyClassload extends ClassLoader{
    
        @Override
        protected Class<?> findClass(String name) {
    
            try{
                String className = name+".class";
                File file = new File("E:\\aaaaa",className);
                FileInputStream fileInputStream = new FileInputStream(file);
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                byte[] b = new byte[1024];
    			//读文件
                int len = fileInputStream.read(b);
                byteArrayOutputStream.write(b,0,len);
                byte[] datas = byteArrayOutputStream.toByteArray();
                return defineClass(name,datas,0,datas.length);
    
            }catch (Exception e){
                e.printStackTrace();
    			return null;
            }
    
        }
    }
    
    public static void main(String[] args) throws Exception {
        MyClassload myClassload = new MyClassload();
        Class test = myClassload.loadClass("Test");
        System.out.println(test.getName());
    }
    

双亲委派

当加载器加载文件时,先看上级加载器能否加载,如果能加载就进行加载,不能加载再由本级来加载。
如果有同包同类名的两个类出现,不会都进行加载,并会抛出java.lang.SecurityException

例如:

public class MyClassload extends ClassLoader{

    @Override
    protected Class<?> findClass(String name) {

        try{
            String className = name+".class";
            File file = new File("E:\\aaaaa",className);
            FileInputStream fileInputStream = new FileInputStream(file);
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            byte[] b = new byte[1024];
            //读文件
            int len = fileInputStream.read(b);
            byteArrayOutputStream.write(b,0,len);
            byte[] datas = byteArrayOutputStream.toByteArray();
            //测试就写死了
            return defineClass("java.lang."+name,datas,0,datas.length);

        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
        
    }
}
public static void main(String[] args) throws Exception {
    MyClassload myClassload = new MyClassload();
    Class string = myClassload.loadClass("String");
    System.out.println(string.getName());
}

结果:

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 classload.MyClassload.findClass(MyClassload.java:23)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at MainClass.main(MainClass.java:30)
Exception in thread "main" java.lang.NullPointerException
	at MainClass.main(MainClass.java:31)

Process finished with exit code 1
posted @ 2022-03-07 18:04  叕叕666  阅读(21)  评论(0)    收藏  举报