【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. ABA 问题

    CAS 导致 ABA 问题CAS 算法实现了一个重要的前提,需要取出内存中某时刻的数据,并在当下时刻比较并替换,那么这个时间差会导致数据的变化. 比如说一个线程 one 从内存位置 V 中取出A,这时 ...

  2. web必知,多终端适配

    导读 移动端适配,是我们在开发中经常会遇到的,这里面可能会遇到非常多的问题: 1px问题 UI图完美适配方案 iPhoneX适配方案 横屏适配 高清屏图片模糊问题 ... 上面这些问题可能我们在开发中 ...

  3. 【STM32】晶振,主时钟,外设频率介绍

    首先,我用的是STM32F407,下方所有图片都是出自这芯片的文档,如果型号和我不同,需要找到对应的芯片说明文档,也许会有出入 先看一张时钟图 这里会着重说明高速的部分,低速(不管内部还是外部)只给R ...

  4. Linux基础命令---host域名查询工具

    host host是一个常用的DNS查询工具,经常用来查询域名.检查域名解析是否正确. 此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.Fedora.   1.语法       ...

  5. oracle 以SYSDBA远程连接数据库

    在服务器用sysdba登陆 grant sysdba to system 然后在远程就可以sysdba登陆数据库了

  6. CentOS6设置Django开发环境

    今天在我的Centos6.5机器上安装 Django 开发环境,在安装完使用 "django-admin.py startproject myapp" 创建应用的时候报了下面的错误 ...

  7. Dubbo服务限流

    为了防止某个消费者的QPS或是所有消费者的QPS总和突然飙升而导致的重要服务的失效,系统可以对访问流量进行控制,这种对集群的保护措施称为服务限流. Dubbo中能够实现服务限流的方式较多,可以划分为两 ...

  8. ssm+mysql+jsp打造在线考试系统WeKnow-学生端

    一.登陆模块 前台提交账号和密码传到后台处理控制层 1.1 首先是控制器 @RequestMapping(value="/studentLogin", method=Request ...

  9. 【保姆级教程】Ubuntu18.04+Geforce 980Ti+安装CUDA10.2+Cudnn

    首先感谢师兄的博客!前半部分按照这个照做没有问题! https://www.bilibili.com/read/cv9162965/ 第一步:下载CUDA 在官网下载,查询自己的GPU型号对应的CUD ...

  10. 企业级BI是自研还是采购?

    企业级BI是自研还是采购? 上一篇<企业级BI为什么这么难做?>,谈到了企业级BI项目所具有的特殊背景,以及在"破局"方面的一点思考,其中谈论的焦点主要是在IT开发项目 ...