可以通过“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-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. Access viewchild from another component

    https://stackoverflow.com/questions/50935728/access-viewchild-from-another-component =============== ...

  2. ansible模块-user

    一.概述user 模块可以帮助我们管理远程主机上的用户,比如创建用户.修改用户.删除用户.为用户创建密钥对等操作.二.心得password参数:此参数用于指定用户的密码.但是这个密码不能是明文的密码, ...

  3. python-platform模块:平台相关属性

    import platform x=platform.machine() #返回平台架构 #AMD64 x=platform.node() #网络名称(主机名) #DESKTOP-KIK668C x= ...

  4. 写出一条SQL语句:取出表A中第31到40行记录(SQLserver,以自增长的ID作为主键,注意: 一条Sql语句:取出表A中第31到第40记录

    解1: select top 10 * from A where id not in (select top 30 id from A) 解2: select top 10 * from A wher ...

  5. CI环境搭建下-Jenkis与git结合

     设置权限:  也可以通过公私钥的方式,添加权限,公私钥填写在gitblit用户中心:  Jenkins中填写私钥: 添加: 添加后如果仍然报错,是因为windows下要使用http的地址. 在此,可 ...

  6. has(expr|ele)保留包含特定后代的元素,去掉那些不含有指定后代的元素。

    has(expr|ele) 概述 保留包含特定后代的元素,去掉那些不含有指定后代的元素.大理石平台等级 .has()方法将会从给定的jQuery对象中重新创建一组匹配的对象.提供的选择器会一一测试原先 ...

  7. JavaScript实现 简易 堆

    有两个原始操作用于保证插入或删除节点以后堆是一个有效的最大堆或者最小堆: shiftUp(): 如果一个节点比它的父节点大(最大堆)或者小(最小堆),那么需要将它同父节点交换位置.这样是这个节点在数组 ...

  8. [Luogu] 国王游戏

    https://www.luogu.org/problemnew/show/P1080 按照 a * b 排序 高精度 #include <bits/stdc++.h> using nam ...

  9. 用ST解决RMQ问题

    用ST算法解决RMQ(区间最值问题) 在解决CF上的6E Exposition时,用到了RMQ+二分的方法.学习了用ST来快速解决RMQ问题,因此做一个小记 建表 用DP的方式来建ST. dp[i][ ...

  10. canvas实现水印

    最近遇到一个需求,给所有页面加水印(登录人),不影响其他点击等功能的使用,目的是防止信息外漏,当时就在想:这年头,PS就不说人人都能使用,谁手机还没个涂鸦功能,防不了,但是就是这么个需求,那就实现吧! ...