jvm的传唱-类加载

PS:承接上一篇文档,由于初次写文档记录类内容,对于博客园目前的文档编译不熟悉,第一篇文章写的太不好看了,这次换了个模式 ,看看能好看点不,便于阅读。

先通过代码看看类加载器的种类和效果

 1 package com.bface.calculate;
 2 
 3 /**
 4  * @ClassName ClassLoaderLecode
 5  * @Description TODO
 6  * @Author cy
 7  * @Date 2021/7/20 14:26
 8  * @Version 1.0
 9  */
10 public class ClassLoaderLecode {
11     public static void main(String[] args) {
12         //获取系统类加载器--> 它负责加载环境变量classpath或系统属性java.class.path 指定路径下的类
13         //
14         ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
15         System.out.println("系统类加载器"+ systemClassLoader);
16         //获取扩展类加载器-->由sun.misc.Launcher$ExtClassLoader实现 2、从java.ext.dirs系统属性所指定的目录中加载类库,
17         //或从JDK的安装目录的jre/lib/ext 子目录(扩展目录)下加载类库
18         ClassLoader parent = systemClassLoader.getParent();
19         System.out.println("扩展类加载器"+parent);
20         //启动类加载器-->这个类加载器使用c/c++实现,嵌套再jvm内部 2、它用来加载Java的核心类库(JAVA_HOME/jre/lib/rt.jar、 resource.jar或sun.boot.class.path路径下的内容),用于提供JVM自身需要的类
21         ClassLoader parent1 = parent.getParent();
22         System.out.println("启动类加载器"+parent1);
23 
24         //获取用户自定的类的类默认类加载器
25         ClassLoader classLoader = ClassLoaderLecode.class.getClassLoader();
26         System.out.println("自定义类的类加载器"+classLoader);
27     }
28 
29 }
View Code

        为什么要使用这种模式呢,这里简单说两句,1.保障同一个类型 尤其是底层库类的唯一性,防止非法篡改,在jvm中判断一个对象的类型是与类加载器有关的,不同的类加载器即便对于开发人员来说一样的对象代码,表示出来的类型也是不一样的,所以还是能区别出来。

       如何实现自定义的类加载器呢,每次通过先委托父类加载器加载,当父类加载器无法加载时,再自己加载。其实 ClassLoader 类默认的 loadClass 方法已经帮我们写好了,我们无需去写。

       有的小伙伴可能会疑问,为什么要自定义类加载器,平时开发好像没怎么用到,有啥用呢?我总结自己觉得可能用到的地方,有的地方写的第三方jar包需要给别人使用,为了保障代码相对安全不被轻易解读,可以通过自定义类加载器在加载时进行加密处理,这样相对来说吧 是能解决安全问题的。

      开始编写自定义类加载器代码如下,大家可以参考借鉴

  1 package com.bface.calculate;
  2 
  3 import javax.jnlp.ExtendedService;
  4 import java.io.BufferedInputStream;
  5 import java.io.ByteArrayOutputStream;
  6 import java.io.FileInputStream;
  7 import java.io.IOException;
  8 import java.util.Calendar;
  9 
 10 /**
 11  * @ClassName ClassLoaderLecode
 12  * @Description TODO
 13  * @Author cy
 14  * @Date 2021/7/20 14:26
 15  * @Version 1.0
 16  */
 17 public class ClassLoaderLecode {
 18     public static void main(String[] args) {
 19         //获取系统类加载器--> 它负责加载环境变量classpath或系统属性java.class.path 指定路径下的类
 20         //
 21         ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
 22         System.out.println("系统类加载器" + systemClassLoader);
 23         //获取扩展类加载器-->由sun.misc.Launcher$ExtClassLoader实现 2、从java.ext.dirs系统属性所指定的目录中加载类库,
 24         //或从JDK的安装目录的jre/lib/ext 子目录(扩展目录)下加载类库
 25         ClassLoader parent = systemClassLoader.getParent();
 26         System.out.println("扩展类加载器" + parent);
 27         //启动类加载器-->这个类加载器使用c/c++实现,嵌套再jvm内部 2、它用来加载Java的核心类库(JAVA_HOME/jre/lib/rt.jar、 resource.jar或sun.boot.class.path路径下的内容),用于提供JVM自身需要的类
 28         ClassLoader parent1 = parent.getParent();
 29         System.out.println("启动类加载器" + parent1);
 30 
 31         //获取用户自定的类的类默认类加载器
 32         ClassLoader classLoader = ClassLoaderLecode.class.getClassLoader();
 33         System.out.println("自定义类的类加载器" + classLoader);
 34 
 35 
 36         ClassLoaderLecode classLoaderLecode = new ClassLoaderLecode();
 37         try {
 38             ZdyClassLoader zdyClassLoader = classLoaderLecode.new ZdyClassLoader("D:\\IdeaProjects\\leecode\\out\\production\\leecode\\com\\bface\\calculate\\");
 39             Class<?> arrayLecode = zdyClassLoader.loadClass("ArrayLecode");
 40             System.out.println("我是由" + arrayLecode.getClassLoader().getClass().getName() + "类加载器加载的");
 41 
 42         } catch (ClassNotFoundException e) {
 43             e.printStackTrace();
 44         }
 45     }
 46 
 47     class ZdyClassLoader extends ClassLoader {
 48         private String codePath;
 49 
 50         public ZdyClassLoader(ClassLoader parent, String codePath) {
 51 
 52         }
 53 
 54         public ZdyClassLoader(String codePath) {
 55             this.codePath = codePath;
 56 
 57         }
 58 
 59         @Override
 60         protected Class<?> findClass(String name) throws ClassNotFoundException {
 61             BufferedInputStream bis = null;
 62             ByteArrayOutputStream baos = null;
 63             try {
 64 
 65                 //1.字节码路径
 66                 String fileName = codePath + name + ".class";
 67                 //2.获取输入流
 68                 bis = new BufferedInputStream(new FileInputStream(fileName));
 69                 //3.获取输出流
 70                 baos = new ByteArrayOutputStream();
 71                 //4.io读写
 72 
 73                 int len;
 74                 byte[] data = new byte[1024];
 75                 while ((len = bis.read(data)) != -1) {
 76                     baos.write(data, 0, len);
 77                 }
 78                 //5.获取内存中字节数组
 79                 byte[] byteCode = baos.toByteArray();
 80                 //6.调用defineClass 将字节数组转成Class对象
 81                 Class<?> defineClass = defineClass(null, byteCode, 0, byteCode.length);
 82                 return defineClass;
 83             } catch (IOException e) {
 84                 e.printStackTrace();
 85             } finally {
 86                 try {
 87                     if (bis != null) {
 88                         bis.close();
 89                     }
 90                     if (baos != null) {
 91                         baos.close();
 92                     }
 93                 } catch (IOException e) {
 94                     e.printStackTrace();
 95                 }
 96             }
 97             return null;
 98         }
 99     }
100 
101 }
View Code
"C:\Program Files\Java\jdk1.8.0_66\bin\java.exe" -Dvisualvm.id=603520010088200 "-javaagent:D:\ProgramSoft\JetBrains\IntelliJ IDEA 2019.3.3\lib\idea_rt.jar=63737:D:\ProgramSoft\JetBrains\IntelliJ IDEA 2019.3.3\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_66\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_66\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_66\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_66\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_66\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_66\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_66\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_66\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_66\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_66\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_66\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_66\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_66\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_66\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_66\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_66\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_66\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_66\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_66\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_66\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_66\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_66\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_66\jre\lib\rt.jar;D:\IdeaProjects\leecode\out\production\leecode" com.bface.calculate.ClassLoaderLecode
系统类加载器sun.misc.Launcher$AppClassLoader@14dad5dc
扩展类加载器sun.misc.Launcher$ExtClassLoader@1b6d3586
启动类加载器null
自定义类的类加载器sun.misc.Launcher$AppClassLoader@14dad5dc
我是由com.bface.calculate.ClassLoaderLecode$ZdyClassLoader类加载器加载的

 

 

 

  

posted @ 2021-07-20 15:45  另类文明传道者  阅读(37)  评论(0编辑  收藏  举报