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 ...
随机推荐
- Mob 之 短信验证集成 SMSSDK
开相关发中总会遇到短信验证这些操作,这周没有来得及写新的东西,借此分享一篇以前学习短信验证的笔记,本文使用的是 Mob 提供的 SMSSDK . 下载 SMSSDK 官网下载地址:SMSSDK 集成 ...
- Blazor入门笔记(1)-从0构建一个组件
1.环境 VS2019 16.5.1 .NET Core SDK 3.1.200 Blazor WebAssembly Templates 3.2.0-preview2.20160.5 2.创建项目 ...
- vagrant 入门案例 - 快速创建 Centos7
中文文档:http://tangbaoping.github.io/vagrant_doc_zh/v2/ 参考: https://blog.csdn.net/yjk13703623757/articl ...
- jenkins 脱机下 安装插件失败
1.首次进入,提示离线 2.网上给出了绝大部分答案是进入Manage Plugins 中在高级下将升级站点的https换成http,但是都没解决我的问题 还是报错,用了大部分时间查阅 最终才发现问题 ...
- 在.NET Core中检查证书的到期日期
在 NUnit 测试中,我需要检查证书的有效期. 下面的代码片段可用于使用自定义证书验证回调检查任何证书属性. 所有你需要做的就是在回调中读取你感兴趣的属性,这样你就可以在之后检查它们. DateTi ...
- Flask 和Django
软件系统发展到今天已经很复杂了,在服务端软件,设计的知识很广泛,为了降低开发难度,提高开发效率,在某些方面去使用别人成熟的框架. 一些事务处理,安全性,数据流控制等都可以让框架处理,而开发人员把更多的 ...
- Flask 入门(八)
flask操作数据库:操作数据: 承接上文: 修改main.py中的代码如下: #encoding:utf-8 from flask_sqlalchemy import SQLAlchemy from ...
- CSS躬行记(5)——渐变
渐变是由两种或多种颜色之间的渐进过渡组成,它是一种特殊的图像类型,分为线性渐变和径向渐变,这两类渐变还会细分为单次和重复两种.渐变图像与传统图像相比,它的优势包括占用更少的字节,避免额外的服务器请求, ...
- 31 Exception 异常处理
/* * Exception in thread "main" java.lang.ArithmeticException: / by zero at com.itheima_01 ...
- itoa、ltoa
#include <stdlib.h> /*整形转字符型*/ char * itoa(int value, char *string, int radix) { char tmp[33]; ...