类加载器可以看下我的收藏:

  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 理解类加载过程 -- 自定义加载器的更多相关文章

  1. Java类加载机制及自定义加载器

    转载:https://www.cnblogs.com/gdpuzxs/p/7044963.html Java类加载机制及自定义加载器 一:ClassLoader类加载器,主要的作用是将class文件加 ...

  2. xLua自定义加载器

    xLua入门基础 环境配置 github下载xLua文件: xLua是腾讯开发,据说比较先进: 下载下来后将Plugins和XLua文件夹考进项目: Plugins多平台权限:XLua和C#交互: t ...

  3. java中三个类别加载器的关系以及各自加载的类的范围

    Java在需要使用类别的时候,才会将类别加载,Java的类别载入是由类别载入器(Class loader)来达到的,预设上,在程序启动之后,主要会有三个类别加载器:Bootstrap Loader.E ...

  4. 深入理解JVM-类加载器深入解析(3)

    深入理解JVM-类加载器深入解析(3) 获得ClassLoader的途径 获得当前类的ClassLoader clazz.getClassLoader() 获得当前线程上下文的ClassLoader ...

  5. JVM类加载(4)—加载器

    定义: 虚拟机设计团队把类加载阶段中“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类.实现这个动作的代码模块称之为“类加载器 ...

  6. 深入理解JVM-类加载器深入解析(2)

    深入理解JVM-类加载器深入解析(2) 加载:就是把二进制形式的java类型读入java虚拟机中 连接: 验证: 准备:为类变量分配内存,设置默认值.但是在到达初始化之前,类变量都没有初始化为真正的初 ...

  7. 我理解的Android加载器

    Android的加载器(loader)是从Android 3.0开始出来的东西.要理解这里需要先理解为什么会出现加载器(也有地方把它说成是装载器)呢? 如果没有加载器... 首先Activity是我们 ...

  8. 深入java虚拟机学习 -- 类的加载机制(三)

    类的初始化时机 在上篇文章中讲到了类的六种主动使用方式,反射是其中的一种(Class.forName("com.jack.test")),这里需要注意一点:当调用ClasLoade ...

  9. <JVM中篇:字节码与类的加载篇>04-再谈类的加载器

    笔记来源:尚硅谷JVM全套教程,百万播放,全网巅峰(宋红康详解java虚拟机) 同步更新:https://gitee.com/vectorx/NOTE_JVM https://codechina.cs ...

随机推荐

  1. 渗透测试之Web安全

    写在前面: 渗透测试包含但不限于Web安全 渗透测试并不相当于Web渗透 Web安全学习是入门渗透测试最容易的途径,门槛最低 Web安全入门: 基础入门 整体框架 SQL注入 XSS攻击 业务逻辑漏洞 ...

  2. Python python 数据类型的相互转换

    # number 之间的相互转换 # int <=> float var1 = 1; print(type(var1)) #<class 'int'> res1 = float ...

  3. 基础英语(一):Unit1

    零,英语学习方法 我看了大量的学习方法,在其它科目都是很管用的,唯独英语,没有任何一个学习方法能够适合适用于我,但是我也从其他的学习方法中总结出了一些规律,那就是任何学习都是脱离不了例子的,任何事物都 ...

  4. ES6全面讲解

    写在之前.讲解了比较常用的ES6知识点,可以快速的入门.有两个比较复杂的知识点(promise,generator)则是留在了其他文章中,在里面详细讲解. 介绍 1.历史 ​ 1.ECMAScript ...

  5. Redis这些知识你知道吗?

    1.什么是redis? Redis 是一个基于内存的高性能key-value数据库. 2.Redis的特点 Redis本质上是一个Key-Value类型的内存数据库,很像memcached,整个数据库 ...

  6. 曹工说Redis源码(1)-- redis debug环境搭建,使用clion,达到和调试java一样的效果

    概要 最近写了spring系列,这个系列还在进行中,然后有些同学开始叫我大神,然后以为我各方面都比较厉害,当然了,我是有自知之明的,大佬大神什么的,当作一个称呼就好,如果真的以为自己就是大神,那可能就 ...

  7. 移动端rem布局实现(vw)

    什么是rem?在W3C官网上是这样描述的:“font size of the root element (根元素的字体大小)”.就是说rem是相当于html的,因为网页的默认字体大小是 16px,所以 ...

  8. php源码的编译

    本片文章主要介绍windows下的php源码的编译. 1.1 编译环境 软件 环境 操作系统 Windows 7 专业版 32bit Visual studio 2012 专业版 PHP 5.5.2. ...

  9. 性能测试环境搭建:XAMPP1.8+PHPwind9.0安装教程

    1.安装准备 1.1软件版本 XAMPP的版本:XAMPP 1.8.2 phpwind的版本:PHPWind 9.0   1.2.安装环境 我的环境:win10 其实安装环境影响不大,win7,win ...

  10. U - Inviting Friends HDU - 3244(二分答案 + 完全背包)

    U - Inviting Friends HDU - 3244 You want to hold a birthday party, inviting as many friends as possi ...