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

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

  1. public class Test {
  2.  
  3. public static void main(String[] args) {
  4. System.out.println(System.getProperty("java.system.class.loader"));
  5. System.out.println(Test.class.getClassLoader());
  6. System.out.println(ClassLoader.getSystemClassLoader());
  7. System.out.println(ClassLoader.getSystemClassLoader().getParent());
  8. }
  9. }

输出结果为

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

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

  1. public class MyClassLoader extends ClassLoader {
  2.  
  3. private String name; //加载器的名字
  4. private String path; //加载路径
  5. private final String fileType = ".class"; //class文件的扩展名
  6.  
  7. @Override
  8. protected Class<?> findClass(String className) {
  9. byte[] data = this.loadClassData(className);
  10. //将字节数组转换成Class对象
  11. return this.defineClass(className, data, 0, data.length);
  12. }
  13.  
  14. private byte[] loadClassData(String className) {
  15. InputStream inputStream = null;
  16. byte[] data = null;
  17. ByteArrayOutputStream byteArrayOutputStream = null;
  18. try {
  19. className = className.replace('.', '/');
  20. inputStream = new FileInputStream(new File(path + "/" + className + fileType));
  21. byteArrayOutputStream = new ByteArrayOutputStream();
  22. int ch = 0;
  23. while (-1 != (ch = inputStream.read())) {
  24. byteArrayOutputStream.write(ch);
  25. }
  26. data = byteArrayOutputStream.toByteArray();
  27. } catch (Exception e) {
  28. e.printStackTrace();
  29. } finally {
  30. try {
  31. inputStream.close();
  32. byteArrayOutputStream.close();
  33. } catch (IOException e) {
  34. e.printStackTrace();
  35. }
  36. }
  37. return data;
  38. }
  39.  
  40. public MyClassLoader(String name, String path) {
  41. // super(); //让系统类加载器成为该类加载器的父类;补充一下基础知识,如果子类没有调用父类的有参构造方法,则默认会调用无参构造方法super(),所以这一行可以注释掉
  42. this.name = name;
  43. this.path = path;
  44. }
  45.  
  46. public MyClassLoader(String name, String path, ClassLoader parent) {
  47. super(parent); //显示指定该类加载器的的父加载器
  48. this.name = name;
  49. this.path = path;
  50. }
  51. }

在控制台运行如下:

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

运行结果

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

该方法的doc文档翻译如下

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

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

  1. // 新增构造方法
  2. public MyClassLoader(ClassLoader parent) {
  3. super(parent);
  4. }

重新运行,结果:

D:\workspace-learn\common-learn\learn-jvm\target\classes>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类的实例

【JVM学习笔记】系统类加载器的更多相关文章

  1. 【JVM学习笔记】类加载器

    概述 类加载器用来把类加载到Java虚拟机中.从JDK1.2版本开始,类的加载过程采用父委托机制,这种机制能更好地保证Java平台的安全.在此委托机制中,除了Java虚拟机自带的根类加载器以外,其余的 ...

  2. Java虚拟机JVM学习06 自定义类加载器 父委托机制和命名空间的再讨论

    Java虚拟机JVM学习06 自定义类加载器 父委托机制和命名空间的再讨论 创建用户自定义的类加载器 要创建用户自定义的类加载器,只需要扩展java.lang.ClassLoader类,然后覆盖它的f ...

  3. java之jvm学习笔记四(安全管理器)

    java之jvm学习笔记四(安全管理器) 前面已经简述了java的安全模型的两个组成部分(类装载器,class文件校验器),接下来学习的是java安全模型的另外一个重要组成部分安全管理器. 安全管理器 ...

  4. JVM学习笔记之类加载机制【八】

    一.类加载时机 1.1 触发类初始化的六个场景: 加载? 1.遇到new.getstatic.putstatic或invokestatic这四条字节码指令时 如果类型没有进行过初始化,则需要先触发其初 ...

  5. 【JVM学习笔记】类加载过程

    在Java代码中,类型的加载.连接与初始化过程都是在程序运行期间完成的:提供了更大的灵活性,增加了更多的可能性 JVM启动过程包括:加载.连接.初始化 加载:就是将class文件加载到内存.详细的说是 ...

  6. jvm学习笔记:类加载过程

    类加载器子系统 类加载器的作用是加载class文件到内存 加载阶段->链接阶段->初始化阶段 ClassLoader只负责class文件的加载,至于是否能够运行由执行引擎判断 加载的类信息 ...

  7. jvm学习二:类加载器

    前一节详细的聊了一下类的加载过程,本节聊一聊类的加载工具,类加载器  ---  ClassLoader 本想自己写的,查资料的时候查到一篇大神的文章,写的十分详细 大家直接过去看吧http://blo ...

  8. JVM学习笔记——GC垃圾收集器

    GC 垃圾收集器 Java 堆内存采用分代回收算法,因此 JVM 针对新生代和老年代提供了多种垃圾收集器. 1. Serial 收集器 Serial 收集器是单线程收集器,采用复制算法. 是最基本的垃 ...

  9. 【JVM学习笔记】扩展类加载器

    扩展类加载器独有的特点,代码如下 public class Sample { } public class Test { static { System.out.println("Test ...

随机推荐

  1. Codeforces Round #588 (Div. 1) C. Konrad and Company Evaluation

    直接建反边暴力 复杂度分析见https://blog.csdn.net/Izumi_Hanako/article/details/101267502 #include<bits/stdc++.h ...

  2. BZOJ 1135 P3488 LYZ-Ice Skates 线段树+Hall

    https://www.luogu.org/problem/P3488 根据Hall定理 左边任意一个区间L-R a[i]的和sum[l~r] 都要<= (R-L+1+d)*K 把(R-L+1) ...

  3. luogu3651 展翅翱翔之时 (はばたきのとき)[基环树+贪心]

    考前随便做点水题愉♂悦身心 有助于退役 这题意思其实就是说要把外向基环树森林改成一个环的最小代价. 依照套路,先对每棵基环树的树做dp,这里因为要是环,要把所有的树都拆成链,然后连接.所以考虑以最小代 ...

  4. CSS3 -- 弹性盒

    新版弹性盒 兼容到IE10及以上 flex小游戏 display: flex; 设置为弹性盒(父元素添加) flex-direction 用来来确定主轴的方向,从而确定基本的项目排列方向. 参数 说明 ...

  5. 利用vue v-bind属性绑定bootstrap样式以及输出数据

    自从知道了bootstrap,就被他简介,大气美观的样式吸引,即使在vue框架中,仍旧想使用,下面给出了vue适配版和原版的代码,以飨读者 数据输出部分 export default { data() ...

  6. mysql自增主键清零方法

    MySQL数据库自增主键归零的几种方法 如果曾经的数据都不需要的话,可以直接清空所有数据,并将自增字段恢复从1开始计数: truncate table table_name; 1 当用户没有trunc ...

  7. 题解 [BZOJ4368][IOI2015]boxes纪念品盒

    题面 解析 可以发现,发纪念品有三种方式: 从左边走再原路返回. 从右边走再原路返回. 走一圈. 注意到,第三种走法最多只会走一次, 因为如果走了多次,那发放的物品数量就会>=\(2k\), 那 ...

  8. Kafka集群---分布式消息系统

    概念: kafka是一种消息中间件 作用: 解耦.冗余.提高扩展性.缓冲 保证顺序.灵活.削峰填谷 异步通信 kafla角色 producer: 生产者,负责发布消息 consumer: 消费者,负责 ...

  9. Laravel 多态关联中不能使用 has, whereHas

    ghost commented on Apr 13, 2017 • edited by ghost  i'm currently using this code in my own project m ...

  10. Java中equals方法null造成空指针异常的原因及解决方案

    正文 bug描述 当查找已修改的与未修改的做比较的时候,之前为null的值调用equals方法与其他值做比较的时候,会导致抛出空指针异常 知识补充 关于null,你不得不知道的几件事: 1.null是 ...