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 ...
随机推荐
- Linux下段错误(C语言)
问题描述:在Linux下编程有时会出现段错误的提醒,出现这种错误有可能是因为以下几种原因 1.数组越界:如果在初始化或者接收输入时内容超过了定义好的数组元素个数时会出现段错误,Linux的数组越界检查 ...
- JavaScript中去除字符串空格的方法
语法 string.trim() 参数值 无 返回值 类型:string 描述:返回移除头尾空格的字符串 技术细节 JavaScript版本: ECMAScript 5 去除字符串左右两端的空格,在v ...
- WeChat-SmallProgram:引用页面调用组件内的方法
如何创建组件 及 使用 这里不在多说:请参考之前文章 如何定义一个组件 自定义select下拉选项框组件使用 引用组件: <sub-unit-select id="init" ...
- 下拉框select->option中如何把参数传到视图函数中去
例子: <select name="p_id" id=""> {% for p in permissions %} <option value ...
- [vijos1880]选课<树形dp>
题目链接:https://www.vijos.org/p/1180 这是一道树形dp的裸题,唯一的有意思的地方就是用到了多叉树转二叉树 然后本蒟蒻写这一道水题就是因为以前知道这个知识点但是没有怎么去实 ...
- C++中的字符串切片操作
string str = "hello"; str.substr(0,2); //输出"he", 表示[0,2)
- 如何设置微信小程序顶部标题
直接在对应的xxx.json中支配如下,就可以了哈 { "backgroundTextStyle": "light", //字体 "navigatio ...
- .NET MVC中登录过滤器拦截的两种方法
今天给大家介绍两种ASP中过滤器拦截的两种方法. 一种是EF 的HtppModule,另一种则是灵活很多针对MVC的特性类 Attribute 具体什么是特性类可以参考着篇文章:https://www ...
- wireshark抓包实战(一),抓包原理
一.什么样的"包"能被wireshark抓住呢? 1.本机 即直接抓取进出本机网卡的流量包.这种情况下,wireshark会绑定本机的一块网卡. 2.集线器 用于抓取流量泛洪,冲突 ...
- 实战if-else 过多详解
1.本文实例代码仅仅是俩个小例子. package com.example.demo.pattern.ifElse; import java.util.HashMap; import java.uti ...