【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-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学习笔记】系统类加载器的更多相关文章
- 【JVM学习笔记】类加载器
概述 类加载器用来把类加载到Java虚拟机中.从JDK1.2版本开始,类的加载过程采用父委托机制,这种机制能更好地保证Java平台的安全.在此委托机制中,除了Java虚拟机自带的根类加载器以外,其余的 ...
- Java虚拟机JVM学习06 自定义类加载器 父委托机制和命名空间的再讨论
Java虚拟机JVM学习06 自定义类加载器 父委托机制和命名空间的再讨论 创建用户自定义的类加载器 要创建用户自定义的类加载器,只需要扩展java.lang.ClassLoader类,然后覆盖它的f ...
- java之jvm学习笔记四(安全管理器)
java之jvm学习笔记四(安全管理器) 前面已经简述了java的安全模型的两个组成部分(类装载器,class文件校验器),接下来学习的是java安全模型的另外一个重要组成部分安全管理器. 安全管理器 ...
- JVM学习笔记之类加载机制【八】
一.类加载时机 1.1 触发类初始化的六个场景: 加载? 1.遇到new.getstatic.putstatic或invokestatic这四条字节码指令时 如果类型没有进行过初始化,则需要先触发其初 ...
- 【JVM学习笔记】类加载过程
在Java代码中,类型的加载.连接与初始化过程都是在程序运行期间完成的:提供了更大的灵活性,增加了更多的可能性 JVM启动过程包括:加载.连接.初始化 加载:就是将class文件加载到内存.详细的说是 ...
- jvm学习笔记:类加载过程
类加载器子系统 类加载器的作用是加载class文件到内存 加载阶段->链接阶段->初始化阶段 ClassLoader只负责class文件的加载,至于是否能够运行由执行引擎判断 加载的类信息 ...
- jvm学习二:类加载器
前一节详细的聊了一下类的加载过程,本节聊一聊类的加载工具,类加载器 --- ClassLoader 本想自己写的,查资料的时候查到一篇大神的文章,写的十分详细 大家直接过去看吧http://blo ...
- JVM学习笔记——GC垃圾收集器
GC 垃圾收集器 Java 堆内存采用分代回收算法,因此 JVM 针对新生代和老年代提供了多种垃圾收集器. 1. Serial 收集器 Serial 收集器是单线程收集器,采用复制算法. 是最基本的垃 ...
- 【JVM学习笔记】扩展类加载器
扩展类加载器独有的特点,代码如下 public class Sample { } public class Test { static { System.out.println("Test ...
随机推荐
- SqlMetaData异常 dbType xx 对于此构造函数无效。
今天在dapper中想扩展使用表值类型参数——tableValue.但是dapper不支持此类参数,于是扩展了一下.其中出现了一个问题. Microsoft.SqlServer.Server.SqlM ...
- 推荐几款好用的Chrome插件
'工欲善其事,必先利其器'.优秀的开发者不仅体现在其在技术方面的精通,还体现在其对各种开发工具的充分了解与使用,这会让其开发效率事半功倍.作为一个前端开发者,平时主要是跟浏览器打交道,Chrome浏览 ...
- CSS效果篇--纯CSS+HTML实现checkbox的思路与实例
checkbox应该是一个比较常用的html功能了,不过浏览器自带的checkbox往往样式不怎么好看,而且不同浏览器效果也不一样.出于美化和统一视觉效果的需求,checkbox的自定义就被提出来了. ...
- Spring事务管理----------整合学习版
作者:学无先后 达者为先 Spring提供了一流的事务管理.在Spring中可以支持声明式事务和编程式事务. 一 spring简介 1 Spring的事务 事务管理在应用程序中起着至关重 ...
- 串口+RS485驱动
其实RS485不算什么协议,只是物理层做了差分传输,AB两线的电压差来表示0,1,0,1,可靠性和距离更加好,因此,一个串口外设只能作为半双工使用,而RS232是可以全双工的. max485模块可以直 ...
- [2019牛客多校第二场][E. MAZE]
题目链接:https://ac.nowcoder.com/acm/contest/882/E 题目大意:有一个\(n\times m\)的01矩阵,一开始可以从第一行的一个点出发,每次可以向左.向右. ...
- Laravel中Contracts的理解和使用
Laravel 的 Contracts 是一组定义了框架核心服务的接口.说白了就是一组接口.使用它就是为了降低耦合性. 即便如此,是不是也有同学会搞不清楚Contracts在lavarel体系中的到底 ...
- PHP mysqli_num_rows() 函数
<?php // 假定数据库用户名:root,密码:123456,数据库:RUNOOB $con=mysqli_connect("localhost","root& ...
- spring@Async注解实现异步方法调用
概述 如何实现异步方法调用,很多人首先会想到使用线程或者线程池技术,springboot中有一个很简单的方法可以实现异步方法调用,那就是在方法上使用@Async注解 例子 首先在Springboot启 ...
- 2019CCPC秦皇岛自我反省&部分题解
练了一年半了,第一次打CCPC,险些把队友坑了打铁,最后也是3题危险捡了块铜. 非常水的点双连通,我居然不相信自己去相信板子,唉,结果整来整去,本来半个小时能出的题,整到了3个小时,大失误呀,不然就可 ...