• 【JVM学习笔记】系统类加载器


    可以通过“java.system.class.loader"属性指定系统类加载器

    默认情况下,该属性值为空:

    public class Test {
    
        public static void main(String[] args) {
            System.out.println(System.getProperty("java.system.class.loader"));
            System.out.println(Test.class.getClassLoader());
            System.out.println(ClassLoader.getSystemClassLoader());
            System.out.println(ClassLoader.getSystemClassLoader().getParent());
        }
    }

    输出结果为

    null
    sun.misc.Launcher$AppClassLoader@18b4aac2
    sun.misc.Launcher$AppClassLoader@18b4aac2
    sun.misc.Launcher$ExtClassLoader@1540e19d

    定义一个我们自己的classloader,并尝试设置其为系统类加载器

    public class MyClassLoader extends ClassLoader {
    
        private String name; //加载器的名字
        private String path; //加载路径
        private final String fileType = ".class"; //class文件的扩展名
    
        @Override
        protected Class<?> findClass(String className) {
            byte[] data = this.loadClassData(className);
            //将字节数组转换成Class对象
            return this.defineClass(className, data, 0, data.length);
        }
    
        private byte[] loadClassData(String className) {
            InputStream inputStream = null;
            byte[] data = null;
            ByteArrayOutputStream byteArrayOutputStream = null;
            try {
                className = className.replace('.', '/');
                inputStream = new FileInputStream(new File(path + "/" + className + fileType));
                byteArrayOutputStream = new ByteArrayOutputStream();
                int ch = 0;
                while (-1 != (ch = inputStream.read())) {
                    byteArrayOutputStream.write(ch);
                }
                data = byteArrayOutputStream.toByteArray();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    inputStream.close();
                    byteArrayOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return data;
        }
    
        public MyClassLoader(String name, String path) {
    //        super(); //让系统类加载器成为该类加载器的父类;补充一下基础知识,如果子类没有调用父类的有参构造方法,则默认会调用无参构造方法super(),所以这一行可以注释掉
            this.name = name;
            this.path = path;
        }
    
        public MyClassLoader(String name, String path, ClassLoader parent) {
            super(parent); //显示指定该类加载器的的父加载器
            this.name = name;
            this.path = path;
        }
    }

    在控制台运行如下:

    java -Djava.system.class.loader=com.learn.jvm.loader.MyClassLoader Test

     运行结果

     意思是缺少一个参数为ClassLoader类型的构造方法,这是在getSystemClassLoader的doc文档中有说明的

    该方法的doc文档翻译如下

    返回用于委托的系统类加载器。这是新ClassLoader实例的默认委托父级,通常是用于启动应用程序的类加载器。
    此方法会在Java运行时启动阶段的早期被调用,此时它会创建系统类加载器并将其设置为调用线程的上下文类加载器。
    默认的系统类加载器是此类的依赖于实现的实例。
    如果在首次调用此方法时定义了系统属性“java.system.class.loader”,那么该属性的值将被视为将作为系统类加载器返回的类的名称。使用默认的系统类加载器加载该类,并且必须定义一个公共构造函数,该构造函数接受一个类型为ClassLoader的参数,该参数用作委托父级。然后使用此构造函数创建一个实例,并使用默认的系统类加载器作为参数。生成的类加载器被定义为系统类加载器。
    如果存在安全管理器,并且调用者的类加载器不为null且调用者的类加载器与系统类加载器的祖先不同,则此方法使用RuntimePermission(“getClassLoader”)调用安全管理器的checkPermission方法)验证对系统类加载器的访问权限。如果不是,则抛出SecurityException。

    于是我们增加构造方法如下:

    // 新增构造方法
    public MyClassLoader(ClassLoader parent) {
        super(parent);
    }

    重新运行,结果:

    D:workspace-learncommon-learnlearn-jvm argetclasses>java -Djava.system.class.loader=com.learn.jvm.loader.MyClassLoader com.learn.jvm.loader.Test
    com.learn.jvm.loader.MyClassLoader
    sun.misc.Launcher$AppClassLoader@5a2264c
    com.learn.jvm.loader.MyClassLoader@54624a40
    sun.misc.Launcher$AppClassLoader@5a2264c

    可以看出我们自定义的MyClassLoader已经称为系统类加载器,并且其父加载器为sun.misc.Launcher$AppClassLoader类的实例

  • 相关阅读:
    如果向某网址Post信息,并得到CookieContainer以便以后直接通过验证
    使用WebClient自动填写并提交ASP.NET页面表单的源代码
    mysql中文乱码,phpmyadmin乱码,php乱码 产生原因及其解决方法
    自己修改的一个WebRequest+代理+POST登录
    HttpWebRequest POST 数据时请求头多了一行Expect: 100continue,少了数据行
    [zt]Windows 2000下PHP5+IIS的安装方法(ISAPI方式)
    GridView控件修改、删除示例(修改含有DropDownList控件)
    GridView的常用操作(增删改查)
    ASP.net 验证码(C#)
    IE对input元素onchange事件的支持BUG
  • 原文地址:https://www.cnblogs.com/heben/p/11453305.html
Copyright © 2020-2023  润新知