024-JVM-自定义类加载器

超、凢脫俗 2022-12-29 14:04 203阅读 0赞

上一篇:023-JVM-类加载器源码分析https://yuhongliang.blog.csdn.net/article/details/111566920

分析完源码,下面自定义类加载器。

1. 把编译后的Miao.class放在D:\tmp\jvm目录下

在这里插入图片描述

2. 代码实现,及分析

  1. package com.yuhl.c2020;
  2. import java.io.ByteArrayOutputStream;
  3. import java.io.File;
  4. import java.io.FileInputStream;
  5. /** * @author yuhl * @Date 2020/12/22 21:49 * @Classname MyClassLoader * @Description 自定义类加载器 */
  6. public class MyClassLoader extends ClassLoader{
  7. @Override
  8. protected Class<?> findClass(String name) throws ClassNotFoundException {
  9. //加载D:/tmp/jvm的文件Maio.class
  10. File f = new File("D:/tmp/jvm", name.replace(".", "/").concat(".class"));
  11. try {
  12. //以流的形式读取
  13. FileInputStream fis = new FileInputStream(f);
  14. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  15. int b = 0;
  16. while ((b=fis.read()) !=0) {
  17. baos.write(b);
  18. }
  19. byte[] bytes = baos.toByteArray();
  20. baos.close();
  21. fis.close();//可以写的更加严谨
  22. //调用defineClass方法生成class,这个class就是Miao.class
  23. return defineClass(name, bytes, 0, bytes.length);
  24. } catch (Exception e) {
  25. e.printStackTrace();
  26. }
  27. return super.findClass(name); //throws ClassNotFoundException
  28. }
  29. public static void main(String[] args) throws Exception {
  30. ClassLoader myClassLoader = new MyClassLoader();
  31. Class clazz = myClassLoader.loadClass("com.yuhl.c2020.Miao");
  32. Class clazz1 = myClassLoader.loadClass("com.yuhl.c2020.Miao");
  33. System.out.println(clazz == clazz1);//true
  34. Miao miao = (Miao)clazz.newInstance();
  35. miao.cry();//mmmmmmm!
  36. System.out.println(myClassLoader.getClass());//class com.yuhl.c2020.MyClassLoader
  37. System.out.println(myClassLoader.getClass().getClassLoader()); //sun.misc.Launcher$AppClassLoader@18b4aac2
  38. System.out.println(myClassLoader.getParent());//sun.misc.Launcher$AppClassLoader@18b4aac2
  39. System.out.println(getSystemClassLoader());//sun.misc.Launcher$AppClassLoader@18b4aac2
  40. }
  41. }

3. 运行结果

  1. true
  2. mmmmmmm!
  3. class com.yuhl.c2020.MyClassLoader
  4. sun.misc.Launcher$AppClassLoader@18b4aac2
  5. sun.misc.Launcher$AppClassLoader@18b4aac2
  6. sun.misc.Launcher$AppClassLoader@18b4aac2

4. defineClass()方法

  1. protected final Class<?> defineClass(String name, byte[] b, int off, int len,
  2. ProtectionDomain protectionDomain)
  3. throws ClassFormatError
  4. {
  5. protectionDomain = preDefineClass(name, protectionDomain);
  6. String source = defineClassSourceLocation(protectionDomain);
  7. Class<?> c = defineClass1(name, b, off, len, protectionDomain, source);
  8. postDefineClass(c, protectionDomain);
  9. return c;
  10. }

调用

  1. private native Class<?> defineClass1(String name, byte[] b, int off, int len,
  2. ProtectionDomain pd, String source);

到此native方法,可知具体的生成此对象的代码有c++实现。

5. Main.class加载过程分析-总结

  1. 到AppClassLoader手中,AppClassLoader查询下自己的缓存(如果在自己势力范围内且已经加载过则可以查询到的哦!),没有,则传递给ExtClassLoader
  2. 到ExtClassLoader手中,ExtClassLoader查询下自己的缓存(如果在自己势力范围内且已经加载过则可以查询到的哦!),没有,则传递给BootStrapClassLoader
  3. 到BootStrapClassLoader手中,BootStrapClassLoader查询下自己的缓存(如果在自己势力范围内且已经加载过则可以查询到的哦!),则准备加载此类,此时去找了下自己的实力范围(没有加载的那些类中)发现没有这个类,我去,再次传递给ExtClassLoader。
  4. 第二次到ExtClassLoader手中,则准备加载此类,此时去找了下自己的实力范围(没有加载的那些类中)发现没有这个类,我去,再次传递给AppClassLoader。
  5. 第二次到AppClassLoader手中,则准备加载此类,此时去找了下自己的实力范围(没有加载的那些类中)发现没有这个类,我去,怎么办呢?有自定义的类加载器去加载。
  6. 自定义类加载器,调用findClass()方法加载成功。
    下一篇:025-JVM-虚拟机执行代码的模式解释执行+及时编译JIT https://yuhongliang.blog.csdn.net/article/details/111598534

发表评论

表情:
评论列表 (有 0 条评论,203人围观)

还没有评论,来说两句吧...

相关阅读

    相关 java jvm-定义

    除了可以用系统默认的类加载器,我们还可以用实现自己的类加载器,类加载器实现步骤如下: 1.定义一个类继承ClassLoader 2.重写findClass方法,用来查找具

    相关 定义

    1. 双亲委派模型 1.1 什么是双亲委派模型? 首先,先要知道什么是类加载器。简单说,类加载器就是根据指定全限定名称将class文件加载到JVM内存,转为Clas

    相关 定义

    loadClass方法实现了双亲委派模型。 1. 首先,检查一下指定名称的类是否已经加载过,如果加载过了,就不需要再加载,直接返回。 2. 如果此类没有加载过,那么,再判