通过定义两个类加载器加载同一字节码文件来证明Class实例为什么不是全局唯一的

1.将一个名为Demo(没有后缀)的字节码文件放在D盘根目录

2.定义两个类加载器

自定义ClassLoader三要素:

    1. 继承自ClassLoader,重写findClass()
    1. 获取字节码二进制流
    1. defineClass加载生成Class实例
package pkg.custom;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream; /**
* 自定义ClassLoader三要素:
* 1. 继承自ClassLoader,重写findClass()
* 2. 获取字节码二进制流
* 3. defineClass加载生成Class实例
*/
public class MyClassLoader1 extends ClassLoader {
private final String CLASS_PATH = "d://Demo"; protected Class<?> findClass(String name) {
try {
//获取字节码二进制流
FileInputStream in = new FileInputStream(this.CLASS_PATH);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int len = -1;
while ((len = in.read(buf)) != -1) {
baos.write(buf, 0, len);
}
in.close();
byte[] classBytes = baos.toByteArray();
//加载Class字节码
return defineClass(classBytes, 0, classBytes.length);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
} //===========================================================
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream; public class MyClassLoader2 extends ClassLoader {
private final String CLASS_PATH = "d://Demo" ;
protected Class<?> findClass(String name) {
try {
FileInputStream in = new FileInputStream(this.CLASS_PATH) ;
ByteArrayOutputStream baos = new ByteArrayOutputStream() ;
byte[] buf = new byte[1024] ;
int len = -1 ;
while((len = in.read(buf)) != -1){
baos.write(buf , 0 , len);
}
in.close();
byte[] classBytes = baos.toByteArray();
return defineClass( classBytes , 0 , classBytes.length) ;
} catch (Exception e) {
e.printStackTrace();
}
return null ;
}
}

3.Main函数

public class Application {
public static void main(String[] args) throws ClassNotFoundException {
ClassLoader c1 = new MyClassLoader1() ;
//利用自定义加载器1加载对象
//调用ClassLoader.loadClass()加载字节码会自动调用findClass方法
Class<?> clz1 = c1.loadClass("Demo");
System.out.println(clz1.getClassLoader() + "|hashcode:" + clz1.hashCode()); ClassLoader c2 = new MyClassLoader2() ;
//利用自定义加载器2加载对象
Class<?> clz2 = c2.loadClass("Demo");
System.out.println(clz2.getClassLoader() + "|hashcode:" + clz2.hashCode());
}
}

运行main,得到输出结果:

pkg.custom.MyClassLoader1@74a14482|hashcode:1735600054
pkg.custom.MyClassLoader2@7f31245a|hashcode:325040804

可以看出由两个不同的类加载器加载,两者的哈希值不同,即所得到的类对象是不同的。

结论:

  • 同一个Class被不同的类加载器加载后在JVM中产生的类对象是不同的
  • 在同一个类加载器作用范围内Class实例加载时才会保持唯一性

Java编程:为什么Class实例可以不是全局唯一的更多相关文章

  1. 为什么Class实例可以不是全局唯一的——自定义类加载器

    为什么Class实例可以不是全局唯一的 通过定义两个类加载器加载同一字节码文件来证明Class实例为什么不是全局唯一的 1.将一个名为Demo(没有后缀)的字节码文件放在D盘根目录 2.定义两个类加载 ...

  2. 《Java编程思想》学习笔记(二)——类加载及执行顺序

    <Java编程思想>学习笔记(二)--类加载及执行顺序 (这是很久之前写的,保存在印象笔记上,今天写在博客上.) 今天看Java编程思想,看到这样一道代码 //: OrderOfIniti ...

  3. #Java编程思想笔记(一)——static

    Java编程思想笔记(一)--static 看<Java编程思想>已经有一段时间了,一直以来都把笔记做在印象笔记上,今天开始写博客来记录. 第一篇笔记来写static关键字. static ...

  4. Java编程思想重点笔记(Java开发必看)

    Java编程思想重点笔记(Java开发必看)   Java编程思想,Java学习必读经典,不管是初学者还是大牛都值得一读,这里总结书中的重点知识,这些知识不仅经常出现在各大知名公司的笔试面试过程中,而 ...

  5. JAVA编程讲座-吴老

    JAVA系列公开课第4讲:多态系列课程:从JAVA编程零基础讲起,同时结合工作中遇到的具体实例,语言清晰易懂,连续10周+深入讲解,打下编程基础,让我们一起打来自动化测试的大门时间:4月25日(周一) ...

  6. Google Java编程风格指南

    出处:http://hawstein.com/posts/google-java-style.html 声明:本文采用以下协议进行授权: 自由转载-非商用-非衍生-保持署名|Creative Comm ...

  7. 谷歌Java编程规范

    Google Java编程风格指南 January 20, 2014 作者:Hawstein 出处:http://hawstein.com/posts/google-java-style.html 声 ...

  8. Java编程中“为了性能”尽量要做到的一些地方

    最近的机器内存又爆满了,除了新增机器内存外,还应该好好review一下我们的代码,有很多代码编写过于随意化,这些不好的习惯或对程序语言的不了解是应该好好打压打压了. 下面是参考网络资源总结的一些在Ja ...

  9. JAVA编程“性能说”(java编程需要做的26件事)

    转载于 http://www.csdn.net/article/2012-06-01/2806249 最近的机器内存又爆满了,除了新增机器内存外,还应该好好review一下我们的代码,有很多代码编写过 ...

随机推荐

  1. 开源基于docker的任务调度器pipeline,比`quartzs` 更强大的分布式任务调度器

    pipeline 分布式任务调度器 目标: 基于docker的布式任务调度器, 比quartzs,xxl-job 更强大的分布式任务调度器. 可以将要执行的任务打包为docker镜像,或者选择已有镜像 ...

  2. (数据科学学习手札125)在Python中操纵json数据的最佳方式

    本文示例代码及文件已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 在日常使用Python的过程中,我们经常会 ...

  3. javascript获取焦点对象ID

    document.activeElement 方法:if(document.activeElement.id="textbox1") { }

  4. #使用C#winform编写渗透测试工具--子域名挖掘

    使用C#winform编写渗透测试工具--子域名挖掘 这篇文章主要介绍使用C#winform编写渗透测试工具--子域名挖掘.在渗透测试中,子域名的收集十分重要,通常一个网站的主站的防御能力特别强,而他 ...

  5. linux对拍

    转自 hzoi-fengwu :https://www.cnblogs.com/hzoi-fengwu/p/14872962.html 1 #include<bits/stdc++.h> ...

  6. NCB | 定量蛋白质组学揭示细胞外泌体通用标志物Syntenin-1

    外泌体 (exosomes) 是由哺乳动物细胞通过"内吞-融合-外排"等机制,主动向胞外释放的纳米级 (直径40~60 nm) 双层囊泡小体,携带蛋白质.核酸.脂质等多种生物活性分 ...

  7. UE4点选源码分析

    在UE插件开发中,时常会用到场景预览窗口的功能,也经常会有点选场景里的物体而同步改变工具界面的需求,网上教程多为讲解如何打开一个预览界面.在最近的一次需求开发中,我粗读了关卡编辑器和蓝图编辑器的Vie ...

  8. Numpy数组的组合与分割详解

    在介绍数组的组合和分割前,我们需要先了解数组的维(ndim)和轴(axis)概念. 如果数组的元素是数组,即数组嵌套数组,我们就称其为多维数组.几层嵌套就称几维.比如形状为(a,b)的二维数组就可以看 ...

  9. Git-06-远程仓库

    本地仓库推送到远程仓库 1 创建ssh key 用户主目录下运行如下命令,然后一路回车 ssh-keygen -t rsa -C "1029612787@qq.com" 2 找到公 ...

  10. Java通过SSLEngine与NIO实现HTTPS访问

    Java使用NIO进行HTTPS协议访问的时候,离不开SSLContext和SSLEngine两个类.我们只需要在Connect操作.Connected操作.Read和Write操作中加入SSL相关的 ...