【jvm】02-手写自己的类加载器

欢迎关注b站账号/公众号【六边形战士夏宁】,一个要把各项指标拉满的男人。该文章已在github目录收录。

屏幕前的大帅比大漂亮如果有帮助到你的话请顺手点个赞、加个收藏这对我真的很重要。别下次一定了,都不关注上哪下次一定。

1.简单手写自己的类加载器

创建一个类继承ClassLoader,然后重写findClass、loadClass这两个方法

findClass的方法

private static byte[] loadByte(String name) throws Exception {
name = name.replaceAll("\\.", "/");
FileInputStream fis = new FileInputStream(classPath + "/" + name
+ ".class");
int len = fis.available();
byte[] data = new byte[len];
fis.read(data);
fis.close();
return data;
} protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
byte[] data = loadByte(name);
//defineClass将一个字节数组转为Class对象,这个字节数组是class文件读取后最终的字节数组。
return defineClass(name, data, 0, data.length);
} catch (Exception e) {
e.printStackTrace();
throw new ClassNotFoundException();
}
}

loadClass直接复制ClassLoader中的方法然后把错误的行数删除就行了

重点改动代码如下,让该自己的加载器加载指定包的文件,注意需要提前编译java文件为class

if (name.startsWith("com.example.demo.lesson")) {
c = findClass(name);
} else {
c = this.getParent().loadClass(name);
}

2.加载一个和jdk中同名的类

创建一个java.lang.Byte的类,然后用自己的类加载器去加载,然后就触发了jdk的沙箱机制,报了一个安全错误

tomcat的类加载器逻辑

如图所示,这里的核心其实就是每一个war包的代码即使含有同名的类也可以加载

做法如下,自己的classloader复制一份然后加载同一个class文件,可以看到启用的是不同的加载器,都被加载了

3.完整代码

package com.example.demo.lesson.jvm.myloader;

import java.io.FileInputStream;

/**
* @author seal email:876651109@qq.com
* @date 2020/9/1 7:23 PM
* @description
*/
public class MyClassLoaderDemo { public static void main(String[] args) throws ClassNotFoundException {
// Class clazz1 = new MyClassLoader().loadClass("com.example.demo.lesson.jvm.loader.A",false);
//Class clazz1 = new MyClassLoader().loadClass("java.lang.Byte",false);
Class clazz2 = new MyClassLoader2().loadClass("com.example.demo.lesson.jvm.loader.A",false);
System.out.println(new MyClassLoaderDemo().getClass().getClassLoader());
// System.out.println(clazz1.getClassLoader());
System.out.println(clazz2.getClassLoader());
} public static String classPath = "F:\\IdeaProjects\\TechingCode\\demoGrace\\src\\main\\java";
private static byte[] loadByte(String name) throws Exception {
name = name.replaceAll("\\.", "/");
FileInputStream fis = new FileInputStream(classPath + "/" + name
+ ".class");
int len = fis.available();
byte[] data = new byte[len];
fis.read(data);
fis.close();
return data;
} static class MyClassLoader extends ClassLoader { @Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
byte[] data = loadByte(name);
//defineClass将一个字节数组转为Class对象,这个字节数组是class文件读取后最终的字节数组。
return defineClass(name, data, 0, data.length);
} catch (Exception e) {
e.printStackTrace();
throw new ClassNotFoundException();
}
} @Override
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException {
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
if (name.startsWith("java.lang.Byte")) {
c = findClass(name);
} else {
c = this.getParent().loadClass(name);
}
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
c = findClass(name); // this is the defining class loader; record the stats
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
} static class MyClassLoader2 extends ClassLoader { @Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
byte[] data = loadByte(name);
//defineClass将一个字节数组转为Class对象,这个字节数组是class文件读取后最终的字节数组。
return defineClass(name, data, 0, data.length);
} catch (Exception e) {
e.printStackTrace();
throw new ClassNotFoundException();
}
} @Override
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException {
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
if (name.startsWith("com.example.demo.lesson")) {
c = findClass(name);
} else {
c = this.getParent().loadClass(name);
}
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
c = findClass(name); // this is the defining class loader; record the stats
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
}
}

4.ConstantPool

Constant pool:
#1 = Methodref #2.#3 // java/lang/Object."<init>":()V
#2 = Class #4 // java/lang/Object
#3 = NameAndType #5:#6 // "<init>":()V
#4 = Utf8 java/lang/Object
#5 = Utf8 <init>
#6 = Utf8 ()V
#7 = Fieldref #8.#9 // com/example/demo/lesson/jvm/construction/Master.master2:Lcom/example/demo/lesson/jvm/construction/Master;
#8 = Class #10 // com/example/demo/lesson/jvm/construction/Master
#9 = NameAndType #11:#12 // master2:Lcom/example/demo/lesson/jvm/construction/Master;
#10 = Utf8 com/example/demo/lesson/jvm/construction/Master
#11 = Utf8 master2
#12 = Utf8 Lcom/example/demo/lesson/jvm/construction/Master;
#13 = Fieldref #8.#14 // com/example/demo/lesson/jvm/construction/Master.master4:Lcom/example/demo/lesson/jvm/construction/Master;
#14 = NameAndType #15:#12 // master4:Lcom/example/demo/lesson/jvm/construction/Master;
#15 = Utf8 master4
#16 = Fieldref #8.#17 // com/example/demo/lesson/jvm/construction/Master.int2:I
#17 = NameAndType #18:#19 // int2:I
#18 = Utf8 int2
#19 = Utf8 I
#20 = Fieldref #8.#21 // com/example/demo/lesson/jvm/construction/Master.int4:I
#21 = NameAndType #22:#19 // int4:I
#22 = Utf8 int4
#23 = Methodref #24.#25 // java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
#24 = Class #26 // java/lang/Integer
#25 = NameAndType #27:#28 // valueOf:(I)Ljava/lang/Integer;
#26 = Utf8 java/lang/Integer
#27 = Utf8 valueOf
#28 = Utf8 (I)Ljava/lang/Integer;
#29 = Fieldref #8.#30 // com/example/demo/lesson/jvm/construction/Master.integerMax2:Ljava/lang/Integer;
#30 = NameAndType #31:#32 // integerMax2:Ljava/lang/Integer;
#31 = Utf8 integerMax2
#32 = Utf8 Ljava/lang/Integer;
#33 = Fieldref #8.#34 // com/example/demo/lesson/jvm/construction/Master.integerMax4:Ljava/lang/Integer;
#34 = NameAndType #35:#32 // integerMax4:Ljava/lang/Integer;
#35 = Utf8 integerMax4
#36 = Fieldref #8.#37 // com/example/demo/lesson/jvm/construction/Master.integerMin2:Ljava/lang/Integer;
#37 = NameAndType #38:#32 // integerMin2:Ljava/lang/Integer;
#38 = Utf8 integerMin2
#39 = Fieldref #8.#40 // com/example/demo/lesson/jvm/construction/Master.integerMin4:Ljava/lang/Integer;
#40 = NameAndType #41:#32 // integerMin4:Ljava/lang/Integer;
#41 = Utf8 integerMin4
#42 = String #43 // str25
#43 = Utf8 str25
#44 = Fieldref #8.#45 // com/example/demo/lesson/jvm/construction/Master.str2:Ljava/lang/String;
#45 = NameAndType #46:#47 // str2:Ljava/lang/String;
#46 = Utf8 str2
#47 = Utf8 Ljava/lang/String;
#48 = String #49 // str27
#49 = Utf8 str27
#50 = Fieldref #8.#51 // com/example/demo/lesson/jvm/construction/Master.str4:Ljava/lang/String;
#51 = NameAndType #52:#47 // str4:Ljava/lang/String;
#52 = Utf8 str4
#53 = Class #54 // java/lang/String
#54 = Utf8 java/lang/String
#55 = String #56 // str30
#56 = Utf8 str30
#57 = Methodref #53.#58 // java/lang/String."<init>":(Ljava/lang/String;)V
#58 = NameAndType #5:#59 // "<init>":(Ljava/lang/String;)V
#59 = Utf8 (Ljava/lang/String;)V
#60 = Fieldref #8.#61 // com/example/demo/lesson/jvm/construction/Master.strN2:Ljava/lang/String;
#61 = NameAndType #62:#47 // strN2:Ljava/lang/String;
#62 = Utf8 strN2
#63 = String #64 // str32
#64 = Utf8 str32
#65 = Fieldref #8.#66 // com/example/demo/lesson/jvm/construction/Master.strN4:Ljava/lang/String;
#66 = NameAndType #67:#47 // strN4:Ljava/lang/String;
#67 = Utf8 strN4
#68 = String #69 // str35
#69 = Utf8 str35
#70 = Methodref #53.#71 // java/lang/String.intern:()Ljava/lang/String;
#71 = NameAndType #72:#73 // intern:()Ljava/lang/String;
#72 = Utf8 intern
#73 = Utf8 ()Ljava/lang/String;
#74 = Fieldref #8.#75 // com/example/demo/lesson/jvm/construction/Master.strI2:Ljava/lang/String;
#75 = NameAndType #76:#47 // strI2:Ljava/lang/String;
#76 = Utf8 strI2
#77 = String #78 // str37
#78 = Utf8 str37
#79 = Fieldref #8.#80 // com/example/demo/lesson/jvm/construction/Master.strI4:Ljava/lang/String;
#80 = NameAndType #81:#47 // strI4:Ljava/lang/String;
#81 = Utf8 strI4
#82 = String #83 // str54
#83 = Utf8 str54
#84 = String #85 // str56
#85 = Utf8 str56
#86 = String #87 // str57
#87 = Utf8 str57
#88 = String #89 // str59
#89 = Utf8 str59
#90 = String #91 // str60
#91 = Utf8 str60
#92 = Fieldref #93.#94 // java/lang/System.out:Ljava/io/PrintStream;
#93 = Class #95 // java/lang/System
#94 = NameAndType #96:#97 // out:Ljava/io/PrintStream;
#95 = Utf8 java/lang/System
#96 = Utf8 out
#97 = Utf8 Ljava/io/PrintStream;
#98 = Fieldref #8.#99 // com/example/demo/lesson/jvm/construction/Master.integerMin1:Ljava/lang/Integer;
#99 = NameAndType #100:#32 // integerMin1:Ljava/lang/Integer;
#100 = Utf8 integerMin1
#101 = Methodref #102.#103 // java/io/PrintStream.println:(Z)V
#102 = Class #104 // java/io/PrintStream
#103 = NameAndType #105:#106 // println:(Z)V
#104 = Utf8 java/io/PrintStream
#105 = Utf8 println
#106 = Utf8 (Z)V
#107 = Fieldref #8.#108 // com/example/demo/lesson/jvm/construction/Master.integerMax1:Ljava/lang/Integer;
#108 = NameAndType #109:#32 // integerMax1:Ljava/lang/Integer;
#109 = Utf8 integerMax1
#110 = Fieldref #8.#111 // com/example/demo/lesson/jvm/construction/Master.strN1:Ljava/lang/String;
#111 = NameAndType #112:#47 // strN1:Ljava/lang/String;
#112 = Utf8 strN1
#113 = String #114 // str29
#114 = Utf8 str29
#115 = String #116 // abc
#116 = Utf8 abc
#117 = Fieldref #8.#118 // com/example/demo/lesson/jvm/construction/Master.master1:Lcom/example/demo/lesson/jvm/construction/Master;
#118 = NameAndType #119:#12 // master1:Lcom/example/demo/lesson/jvm/construction/Master;
#119 = Utf8 master1
#120 = Fieldref #8.#121 // com/example/demo/lesson/jvm/construction/Master.master3:Lcom/example/demo/lesson/jvm/construction/Master;
#121 = NameAndType #122:#12 // master3:Lcom/example/demo/lesson/jvm/construction/Master;
#122 = Utf8 master3
#123 = Fieldref #8.#124 // com/example/demo/lesson/jvm/construction/Master.int3:I
#124 = NameAndType #125:#19 // int3:I
#125 = Utf8 int3
#126 = Fieldref #8.#127 // com/example/demo/lesson/jvm/construction/Master.integerMax3:Ljava/lang/Integer;
#127 = NameAndType #128:#32 // integerMax3:Ljava/lang/Integer;
#128 = Utf8 integerMax3
#129 = Fieldref #8.#130 // com/example/demo/lesson/jvm/construction/Master.integerMin3:Ljava/lang/Integer;
#130 = NameAndType #131:#32 // integerMin3:Ljava/lang/Integer;
#131 = Utf8 integerMin3
#132 = String #133 // str26
#133 = Utf8 str26
#134 = Fieldref #8.#135 // com/example/demo/lesson/jvm/construction/Master.str3:Ljava/lang/String;
#135 = NameAndType #136:#47 // str3:Ljava/lang/String;
#136 = Utf8 str3
#137 = String #138 // str31
#138 = Utf8 str31
#139 = Fieldref #8.#140 // com/example/demo/lesson/jvm/construction/Master.strN3:Ljava/lang/String;
#140 = NameAndType #141:#47 // strN3:Ljava/lang/String;
#141 = Utf8 strN3
#142 = String #143 // str34
#143 = Utf8 str34
#144 = Fieldref #8.#145 // com/example/demo/lesson/jvm/construction/Master.strI1:Ljava/lang/String;
#145 = NameAndType #146:#47 // strI1:Ljava/lang/String;
#146 = Utf8 strI1
#147 = String #148 // str36
#148 = Utf8 str36
#149 = Fieldref #8.#150 // com/example/demo/lesson/jvm/construction/Master.strI3:Ljava/lang/String;
#150 = NameAndType #151:#47 // strI3:Ljava/lang/String;
#151 = Utf8 strI3
#152 = Utf8 int1
#153 = Utf8 ConstantValue
#154 = Integer 9
#155 = Integer 10
#156 = Utf8 str1
#157 = String #158 // str24
#158 = Utf8 str24
#159 = Utf8 Code
#160 = Utf8 LineNumberTable
#161 = Utf8 main
#162 = Utf8 ([Ljava/lang/String;)V
#163 = Utf8 StackMapTable
#164 = Class #165 // "[Ljava/lang/String;"
#165 = Utf8 [Ljava/lang/String;
#166 = Utf8 <clinit>
#167 = Utf8 SourceFile
#168 = Utf8 Master.java

参考资料

《深入理解Java虚拟机》-周志明

【jvm】02-手写自己的类加载器的更多相关文章

  1. JVM 类的生命周期、类加载器

    类的加载.连接与初始化                  • 1. 加载:查找并加载类的二进制数据         • 2. 连接             – 2.1 验证:确保被加载的类的正确性   ...

  2. 【JVM】查看JVM加载的类及类加载器的方法

    查看JVM加载了哪些类 java -verbose[:class|gc|jni] 在输出设备上显示虚拟机运行信息. java -verbose:class 在程序运行的时候有多少类被加载!你可以用ve ...

  3. JVM知识(二):类加载器原理

    我们知道我们编写的java代码,会经过编译器编译成字节码(class文件),再把字节码文件装载到JVM中,最后映射到各个内存区域中,我们的程序就可以在内存中运行了.那么问题来了,这些字节码文件是怎么装 ...

  4. 深入了解java虚拟机(JVM) 第十二章 类加载器

    一.什么是类加载器 类加载器是一个用来加载类文件的类,Java源代码通过javac编译器编译成类文件,然后JVM来执行类文件中的字节码来执行程序.需要注意的是,只有被同一个类加载器加载的类才可能会相等 ...

  5. 【JVM学习笔记】线程上下文类加载器

    有许多地方能够看到线程上下文类加载的设置,比如在sun.misc.Launcher类的构造方法中,能够看到如下代码 先写一个例子建立感性认识 public class Test { public st ...

  6. 写一个自定义类加载器demo

    public class MyTest16 extends ClassLoader { private String classLoaderName; private String fileExten ...

  7. JVM源码分析之自定义类加载器如何拉长YGC

    概述 本文重点讲述毕玄大师在其公众号上发的一个GC问题一个jstack/jmap等不能用的case,对于毕大师那篇文章,题目上没有提到GC的那个问题,不过进入到文章里可以看到,既然文章提到了jstac ...

  8. 深入JVM系列(三)之类加载、类加载器、双亲委派机制与常见问题

    一.概述   定义:虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的java类型.类加载和连接的过程都是在运行期间完成的. 二. 类的 ...

  9. 【JVM第二篇--类加载机制】类加载器与双亲委派模型

    写在前面的话:本文是在观看尚硅谷JVM教程后,整理的学习笔记.其观看地址如下:尚硅谷2020最新版宋红康JVM教程 一.什么是类加载器 在类加载过程中,加载阶段有一个动作是"通过一个类的全限 ...

随机推荐

  1. HDFS【hadoop3.1.3 windows开发环境搭建】

    目录 一.配置hadoop3.1.3 windows环境依赖 配置环境变量 添加到path路径 在cmd中测试 二.idea中的配置 创建工程/模块 添加pom.xml依赖 日志添加--配置log4j ...

  2. Struts 2 基础篇【转】

    转载至 : http://www.blogjava.net/huamengxing/archive/2009/10/21/299153.html Struts2架构图 有视频讲解百度一下就可以找到了 ...

  3. Ruby Gems更换淘宝源方法

    官方的 Rubygems 源由于有些资源放在 Amazon S3 上面,所以有时会抽风,在 Linux 下我用 proxychains gem install xxx 实现了指定程序实行 Shadow ...

  4. 【Linux】【Services】【SaaS】Docker+kubernetes(13. 部署Jenkins/Maven实现代码自动化发布)

    1. 简介 Jenkins: 官方网站:https://jenkins.io/ 下载地址:https://jenkins.io/download/ war包下载:http://mirrors.jenk ...

  5. spring的核心容器ApplicationContext

    //bean.xml配置文件 <?xml version="1.0" encoding="UTF-8"?><beans xmlns=" ...

  6. GIS应用|快速开发在线路径导航应用

    导航应用可用于路径规划及仿真,并且常作为一个重要模块融入到各类企业管理业务中,如面向物流管理.商品配送.车辆监控等场景,那么如何开发一个简单的在线路径导航应用呢?SuperMap Online为您解答 ...

  7. 车载以太网第二弹|测试之实锤-AVB测试实践

    背景 AVB(Audio Video Bridging)音视频桥接,是由IEEE 802.1标准委员会的IEEE AVB任务组制定的一组技术标准,包括精确时钟同步.带宽预留和流量调度等协议规范,用于构 ...

  8. 华为HMS Core图形引擎服务携手三七游戏打造移动端实时DDGI技术

    在2021年HDC大会的主题演讲中提到,华为HMS Core图形引擎服务(Scene Kit)正协同三七游戏一起打造实时DDGI(动态漫反射全局光照:Dynamic Diffuse Global Il ...

  9. CF499B Lecture 题解

    Content 有一个教授用 \(\texttt{A}\) 语言讲课.你觉得他讲的太快了,所以决定使用 \(\texttt{A}\) 语言和 \(\texttt{B}\) 语言记笔记. 已知 \(\t ...

  10. CF950A Left-handers, Right-handers and Ambidexters 题解

    Content 有 \(l\) 个人是左撇子,有 \(r\) 个人是右撇子,另外有 \(a\) 个人既惯用左手又惯用右手.现在想组成一个队伍,要求队伍中惯用左手的人和惯用右手的人相等,试求出团队里面的 ...