【jvm】02-手写自己的类加载器
【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-手写自己的类加载器的更多相关文章
- JVM 类的生命周期、类加载器
		类的加载.连接与初始化 • 1. 加载:查找并加载类的二进制数据 • 2. 连接 – 2.1 验证:确保被加载的类的正确性 ... 
- 【JVM】查看JVM加载的类及类加载器的方法
		查看JVM加载了哪些类 java -verbose[:class|gc|jni] 在输出设备上显示虚拟机运行信息. java -verbose:class 在程序运行的时候有多少类被加载!你可以用ve ... 
- JVM知识(二):类加载器原理
		我们知道我们编写的java代码,会经过编译器编译成字节码(class文件),再把字节码文件装载到JVM中,最后映射到各个内存区域中,我们的程序就可以在内存中运行了.那么问题来了,这些字节码文件是怎么装 ... 
- 深入了解java虚拟机(JVM)  第十二章 类加载器
		一.什么是类加载器 类加载器是一个用来加载类文件的类,Java源代码通过javac编译器编译成类文件,然后JVM来执行类文件中的字节码来执行程序.需要注意的是,只有被同一个类加载器加载的类才可能会相等 ... 
- 【JVM学习笔记】线程上下文类加载器
		有许多地方能够看到线程上下文类加载的设置,比如在sun.misc.Launcher类的构造方法中,能够看到如下代码 先写一个例子建立感性认识 public class Test { public st ... 
- 写一个自定义类加载器demo
		public class MyTest16 extends ClassLoader { private String classLoaderName; private String fileExten ... 
- JVM源码分析之自定义类加载器如何拉长YGC
		概述 本文重点讲述毕玄大师在其公众号上发的一个GC问题一个jstack/jmap等不能用的case,对于毕大师那篇文章,题目上没有提到GC的那个问题,不过进入到文章里可以看到,既然文章提到了jstac ... 
- 深入JVM系列(三)之类加载、类加载器、双亲委派机制与常见问题
		一.概述 定义:虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的java类型.类加载和连接的过程都是在运行期间完成的. 二. 类的 ... 
- 【JVM第二篇--类加载机制】类加载器与双亲委派模型
		写在前面的话:本文是在观看尚硅谷JVM教程后,整理的学习笔记.其观看地址如下:尚硅谷2020最新版宋红康JVM教程 一.什么是类加载器 在类加载过程中,加载阶段有一个动作是"通过一个类的全限 ... 
随机推荐
- HDFS【hadoop3.1.3 windows开发环境搭建】
			目录 一.配置hadoop3.1.3 windows环境依赖 配置环境变量 添加到path路径 在cmd中测试 二.idea中的配置 创建工程/模块 添加pom.xml依赖 日志添加--配置log4j ... 
- Struts 2 基础篇【转】
			转载至 : http://www.blogjava.net/huamengxing/archive/2009/10/21/299153.html Struts2架构图 有视频讲解百度一下就可以找到了 ... 
- Ruby Gems更换淘宝源方法
			官方的 Rubygems 源由于有些资源放在 Amazon S3 上面,所以有时会抽风,在 Linux 下我用 proxychains gem install xxx 实现了指定程序实行 Shadow ... 
- 【Linux】【Services】【SaaS】Docker+kubernetes(13. 部署Jenkins/Maven实现代码自动化发布)
			1. 简介 Jenkins: 官方网站:https://jenkins.io/ 下载地址:https://jenkins.io/download/ war包下载:http://mirrors.jenk ... 
- spring的核心容器ApplicationContext
			//bean.xml配置文件 <?xml version="1.0" encoding="UTF-8"?><beans xmlns=" ... 
- GIS应用|快速开发在线路径导航应用
			导航应用可用于路径规划及仿真,并且常作为一个重要模块融入到各类企业管理业务中,如面向物流管理.商品配送.车辆监控等场景,那么如何开发一个简单的在线路径导航应用呢?SuperMap Online为您解答 ... 
- 车载以太网第二弹|测试之实锤-AVB测试实践
			背景 AVB(Audio Video Bridging)音视频桥接,是由IEEE 802.1标准委员会的IEEE AVB任务组制定的一组技术标准,包括精确时钟同步.带宽预留和流量调度等协议规范,用于构 ... 
- 华为HMS Core图形引擎服务携手三七游戏打造移动端实时DDGI技术
			在2021年HDC大会的主题演讲中提到,华为HMS Core图形引擎服务(Scene Kit)正协同三七游戏一起打造实时DDGI(动态漫反射全局光照:Dynamic Diffuse Global Il ... 
- CF499B Lecture 题解
			Content 有一个教授用 \(\texttt{A}\) 语言讲课.你觉得他讲的太快了,所以决定使用 \(\texttt{A}\) 语言和 \(\texttt{B}\) 语言记笔记. 已知 \(\t ... 
- CF950A Left-handers, Right-handers and Ambidexters 题解
			Content 有 \(l\) 个人是左撇子,有 \(r\) 个人是右撇子,另外有 \(a\) 个人既惯用左手又惯用右手.现在想组成一个队伍,要求队伍中惯用左手的人和惯用右手的人相等,试求出团队里面的 ... 
