可以通过“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. nginx反向代理和负载均衡的简单部署

    1.   安装 1)         从Nginx官网下载页面(http://nginx.org/en/download.html)下载Nginx最新版本(目前是1.5.13版本)安装包: 2)    ...

  2. Switch按钮

    使用CSS+HTML5修改原生checkbox为Switch Button .switch { width: 45px; height: 15px; position: relative; borde ...

  3. python_推导式

    列表推导式 目的:方便的生成一个列表 格式: v1 = [i for i in 可迭代对象 ] v2 = [i for i in 可迭代对象 if条件]#条件为True菜进行append v1 = [ ...

  4. 为什么说Redis是单线程的以及Redis为什么这么块

    一.前言 近乎所有与Java相关的面试都会问到缓存的问题,基础一点的会问到什么是“二八定律”.什么是“热数据和冷数据”,复杂一点的会问到缓存雪崩.缓存穿透.缓存预热.缓存更新.缓存降级等问题,这些看似 ...

  5. tensorflow 更新出现HTTPSConnectionPool(host='files.pythonhosted.org', port=443): Read timed out.

    pip install --upgrade tensorflow --default-timeout=1000

  6. Java队列与栈转换中String.Valueof()使用

    1. 由 基本数据型态转换成 String String 类别中已经提供了将基本数据型态转换成 String 的 static 方法 也就是 String.valueOf() 这个参数多载的方法 有下 ...

  7. Modbus通讯协议

    <ignore_js_op> O1CN01P1wxTI1dCdw5nAeMO_!!85243700.jpg (287.43 KB, 下载次数: 0) 下载附件  保存到相册 2019-6- ...

  8. webstorm 2016.3 注册方法

    用license server 的方式吧,activation code 的方式没有找到方法. license server 里写http://idea.iteblog.com/key.php 用li ...

  9. centos7部署mysql5.7一主多从

    /usr/share/mysql/charsets/ 服务器 ip 操作系统 mysql Mysql_master 192.168.188.11 centos7 5.7 Mysql_slave1 19 ...

  10. shell拷贝文件到另一台机器

    #!/bin/bash data=$(date "+%Y-%m-%d %H:%M:%S") ip='192.168.10.14' password='fan' gitBak='/v ...