Java 理解类加载过程 -- 自定义加载器
类加载器可以看下我的收藏:
https://www.cnblogs.com/dongguacai/p/5879931.html
现在准备一个字节码文件:

自定义加载器:
package com.xzlf.test; import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream; /**
* 自定义类加载器
*
* @author xzlf
*
*/
public class MyClassLoader extends ClassLoader {
// 类加载器查找的根目录
private String rootDir; public MyClassLoader(String rootDir) {
super();
this.rootDir = rootDir;
} @Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
// 查看 c 是否已经被加载
Class<?> c = findLoadedClass(name);
if(c != null) {
// 已经加载直接返回
return c;
}else {
// 没有被加载,先委派给父类加载器, 最终会委派到引导类加载器
ClassLoader parent = this.getParent();
try {
c = parent.loadClass(name);
} catch (ClassNotFoundException e) {
//e.printStackTrace();
}
// 如果父类加载器已加载则直接返回,如果没有加载则使用自定加载器加载类的字节码文件
if(c != null) {
return c;
}else {
// 获取字节码文件
byte[] classDatas = getClassData(name);
if(classDatas == null) {
throw new ClassNotFoundException();
}else {
//Converts an array of bytes into an instance of class
c = defineClass(name, classDatas, 0, classDatas.length);
}
}
}
return c;
} // 获取字节码文件
private byte[] getClassData(String name) {
//com.test.A --> f:/mycode/ com/test/A.class
String path = rootDir + "/" + name.replace('.', '/') + ".class"; // IO 操作 返回字节码
InputStream is = null;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
is = new FileInputStream(path);
byte[] flush = new byte[1024];
int len;
while((len = is.read(flush)) != -1) {
bos.write(flush, 0, len);
}
return bos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
}finally {
if(bos != null) {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
}
测试代码:
package com.xzlf.test;
public class TestClassLoader {
public static void main(String[] args) throws Exception {
MyClassLoader loader1 = new MyClassLoader("f:/mycode");
MyClassLoader loader2 = new MyClassLoader("f:/mycode");
Class<?> c1 = loader1.loadClass("com.test.Welcome");
Class<?> c2 = loader1.loadClass("com.test.Welcome");
Class<?> c3 = loader2.loadClass("com.test.Welcome");
Class<?> c4 = loader2.loadClass("java.lang.String");
Class<?> c5 = loader2.loadClass("com.xzlf.test.MyClassLoader");
// 自定义加载器
System.out.println("c1-->" + c1.hashCode() + "-->" + c1.getClassLoader());
System.out.println("c2-->" + c2.hashCode() + "-->" + c2.getClassLoader());
// 同一个类,被不同的加载器加载,JVM认为也是不相同的类
System.out.println("c3-->" + c3.hashCode() + "-->" + c3.getClassLoader());
// 引导加载器
System.out.println("c4-->" + c4.hashCode() + "-->" + c4.getClassLoader());
// 应用加载器
System.out.println("c5-->" + c5.hashCode() + "-->" + c5.getClassLoader());
}
}
运行测试:

Java 理解类加载过程 -- 自定义加载器的更多相关文章
- Java类加载机制及自定义加载器
转载:https://www.cnblogs.com/gdpuzxs/p/7044963.html Java类加载机制及自定义加载器 一:ClassLoader类加载器,主要的作用是将class文件加 ...
- xLua自定义加载器
xLua入门基础 环境配置 github下载xLua文件: xLua是腾讯开发,据说比较先进: 下载下来后将Plugins和XLua文件夹考进项目: Plugins多平台权限:XLua和C#交互: t ...
- java中三个类别加载器的关系以及各自加载的类的范围
Java在需要使用类别的时候,才会将类别加载,Java的类别载入是由类别载入器(Class loader)来达到的,预设上,在程序启动之后,主要会有三个类别加载器:Bootstrap Loader.E ...
- 深入理解JVM-类加载器深入解析(3)
深入理解JVM-类加载器深入解析(3) 获得ClassLoader的途径 获得当前类的ClassLoader clazz.getClassLoader() 获得当前线程上下文的ClassLoader ...
- JVM类加载(4)—加载器
定义: 虚拟机设计团队把类加载阶段中“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类.实现这个动作的代码模块称之为“类加载器 ...
- 深入理解JVM-类加载器深入解析(2)
深入理解JVM-类加载器深入解析(2) 加载:就是把二进制形式的java类型读入java虚拟机中 连接: 验证: 准备:为类变量分配内存,设置默认值.但是在到达初始化之前,类变量都没有初始化为真正的初 ...
- 我理解的Android加载器
Android的加载器(loader)是从Android 3.0开始出来的东西.要理解这里需要先理解为什么会出现加载器(也有地方把它说成是装载器)呢? 如果没有加载器... 首先Activity是我们 ...
- 深入java虚拟机学习 -- 类的加载机制(三)
类的初始化时机 在上篇文章中讲到了类的六种主动使用方式,反射是其中的一种(Class.forName("com.jack.test")),这里需要注意一点:当调用ClasLoade ...
- <JVM中篇:字节码与类的加载篇>04-再谈类的加载器
笔记来源:尚硅谷JVM全套教程,百万播放,全网巅峰(宋红康详解java虚拟机) 同步更新:https://gitee.com/vectorx/NOTE_JVM https://codechina.cs ...
随机推荐
- coding++:Spring_IOC(控制反转)详解
IoC是什么: 1):Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想. 2):在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的 ...
- 《Mathematical Analysis of Algorithms》中有关“选择第t大的数”的算法分析
开头废话 这个问题是Donald.E.Knuth在他发表的论文Mathematical Analysis of Algorithms中提到的,这里对他的算法分析过程给出了更详细的解释. 问题描述: 给 ...
- 第 k 小的数
一.寻找两个有序数组的中位数 1.1 问题描述 给定两个大小为 m 和 n 的不同时为空的有序数组 nums1 和 nums2.找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m ...
- Axure RP闪退问题
Axure RP 在mac 环境,当时安装的是8.好久没用了,最近打开,一开就闪退. 网上找了一下,显示的都是各种文件夹没权限的问题,实验了一下不管用. /Applications/develop/A ...
- 记一次Task抛异常,调用线程处理而引发的一些随想
记一次Task抛异常,调用线程处理而引发的一些随想 多线程调用,任务线程抛出异常如何在另一个线程(调用线程)中捕获并进行处理的问题. 1.任务线程在任务线程执行语句上抛出异常. 例如: private ...
- G - 土耳其冰淇凌 Gym - 101194D(二分答案 + 贪心检验)
熊猫先生非常喜欢冰淇淋,尤其是冰淇淋塔.一个冰淇淋塔由K个冰淇淋球堆叠成一个塔.为了使塔稳定,下面的冰淇淋球至少要有它上面的两倍大.换句话说,如果冰淇淋球从上到下的尺寸是A0, A1, A2,···, ...
- Spring Web Flow 笔记
在Spring 中配置 Web Flow <?xml version="1.0" encoding="UTF-8"?> <beans xmln ...
- 使用appium框架测试安卓app时,获取toast弹框文字时,前一步千万不要加time.sleep等等待时间。
使用appium框架测试安卓app时,如果需要获取toast弹框的文案内容,那么再点击弹框按钮之前,一定记得千万不要加time.sleep()等待时间,否则有延迟,一直获取不到: 获取弹框的代码: m ...
- Idea离线安装plugins插件 如Lombok
由于公司不允许使用外网,之前用的idea 15 安装了一次.但是idea15的提示不够友好,今天升级idea2017.3.2,同样又需要安装,那就写个教程吧. 网上其他的安装教程不通用,也是针对不同i ...
- java添加对象成功后想知道当前添加对象的id
我使用的是springboot Mybatis写的项目,结构如下 mapper.xml(以下2个属性必须要有,主键id 一般是自动生成的) mapper.java (注意新增的返回值不需要,一般情况 ...