做顿饭还要先买菜,用Java怎么能不懂类加载(一)

好戏开始:

逻辑思路(蛋生鸡)👇

1、类加载过程

多个java文件经过编译打包生成可运行jar包,最终由java命令运行某个主类的main函数启动程序,这里首先需要通过类加载器把主类加载到JVM。
主类在运行过程中如果使用到其它类,会逐步加载这些类。
注意,jar包里的类不是一次性全部加载的,是使用到时才加载。
 

类加载到使用整个过程有如下几步:

加载 >> 验证 >> 准备 >> 解析 >> 初始化 >> 使用 >> 卸载
 
加载:在硬盘上查找并通过IO读入字节码文件,使用到类时才会加载,例如调用类的main()方法,new对象等等
验证:校验字节码文件的正确性
准备:给类的静态变量分配内存,并赋予默认值
解析:将符号引用替换为直接引用,该阶段会把一些静态方法(符号引用,比如main()方法)替换为指向数据所存内存的指针或句柄等(直接引用),这是所谓的静态链接过程(类加载期间完成),动态链接是在程序运行期间完成的将符号引用替换为直接引用
初始化:对类的静态变量初始化为指定的值,执行静态代码块

 

实现落地(鸡生蛋)👇

2、类加载器和双亲委派机制

上面的类加载过程主要是通过类加载器来实现的,Java里有如下几种类加载器
启动类加载器:        负责加载支撑JVM运行的位于JRE的lib目录下的核心类库,比如rt.jar、charsets.jar等
扩展类加载器:        负责加载支撑JVM运行的位于JRE的lib目录下的ext扩展目录中的JAR类包
应用程序类加载器:负责加载ClassPath路径下的类包,主要就是加载你自己写的那些类
自定义加载器:       负责加载用户自定义路径下的类包
 
看一个类加载器示例:
1 Public class ZhangjiangTestClassLoader{
2   public static void main(String[] args){
3        System.out.println(String.class.getClassLoader());
4         System.out.println(com.sun.crypto.provideer.DESKeyFactory.class.getClassLoader().getClass().getClassName());
5     System.out.println(ZhangjiangTestClassLoader.class.getClassLoader().getClass().getClassName());
6         System.out.println(ClassLoader.getSystemClassLoader().getClass().getClassName());  
7     }    
8 }        
View Code
 
自定义一个类加载器示例:
自定义类加载器只需要继承 java.lang.ClassLoader 类,该类有两个核心方法,一个是loadClass(String, boolean),实现了双亲委派机制,大体逻辑
1. 首先,检查一下指定名称的类是否已经加载过,如果加载过了,就不需要再加载,直接返回。
2. 如果此类没有加载过,那么,再判断一下是否有父加载器;如果有父加载器,则由父加载器加载(即调用parent.loadClass(name, false);).或者是调用bootstrap类加载器来加载。
3. 如果父加载器及bootstrap类加载器都没有找到指定的类,那么调用当前类加载器的findClass方法来完成类加载。还有一个方法是findClass,默认实现是抛出异常,所以我们自定义类加载器主要是重写
findClass方法。 
 
以下是自定义classLoader代码:
 1 public class ZhangjiangClassLoaderTest {
 2   static class ZhangjiangClassLoader extends ClassLoader {  
 3     private String classPath;
 4     public ZhangjiangClassLoader(String classPath) {
 5       this.classPath = classPath;
 6    }
 7 
 8     private byte[] loadByte(String name) throws Exception {
 9       name = name.replaceAll("\\.", "/");
10       FileInputStream fis = new FileInputStream(classPath + "/" + name + ".class";
11       int len = fis.available();
12       byte[] data = new byte[len];
13       fis.read(data);
14       fis.close();
15       return data;
16    }
17 
18     protected Class<?> findClass(String name) throws ClassNotFoundException{
19       try {
20              byte[] data = loadByte(name);
21              //defineClass将一个字节数组转为Class对象,这个字节数组是class文件读取后最终的字节数组
22              return defineClass(name, data, 0, data.length);
23       } catch (Exception e) {
24               e.printStackTrace();
25               throw new ClassNotFoundException();
26        }
27     }
28  }
29 
30   public static void main(String args[]) throws Exception {
31     ZhangjiangClassLoader classLoader = new ZhangjiangClassLoader("D:/test");
32     Class clazz = classLoader.loadClass("com.zhangjiang.jvm.User1");
33     Object obj = clazz.newInstance();
34     Method method= clazz.getDeclaredMethod("sout", null);
35     method.invoke(obj, null);
36     System.out.println(clazz.getClassLoader().getClass().getName());
37   }
38 }
39 
40 
41 运行结果:
42 =======自己的加载器加载类调用方法=======
43 com.zhangjiang.jvm.ZhangjiangClassLoaderTest$ZhangjiangClassLoader
View Code

拓展

1.内网就安全吗?看这个

Java动态类加载,当FastJson遇上内网(博主建议看第3.4部分,第5部分为拓展)

转载链接:https://mp.weixin.qq.com/s/ou3L-IU1CNr9EGkpjH2u0w

2.好的知识是成体系的,脑图看这个

java 类的加载机制+思维导图+面试考题

转载链接:https://mp.weixin.qq.com/s/JabIenGFv0eIdgWbxp0Ieg

文中脑图:https://www.kdocs.cn/view/l/snSW5Qkk4?

3.功能时好时坏?代码错误是根源,排查你要借助类加载知识

从一次线上事故聊到类加载机制(博主建议,从王经理运维故障申报后的描述开始看,重点在loadClasss方法的源码展示部分到结束)

转载链接:https://mp.weixin.qq.com/s/ci3AWUXkB9UXaTjje-AtDQ

4.类加载子系统,用图看更明白

牛掰!20张图解密JVM类加载子系统,瞬间豁然开朗(博主建议:从3.3用户自定义加载器开始看)

转载链接:https://mp.weixin.qq.com/s/zJItCP0HI62Vmv1NXsPfew

5.依赖冲突怎么办?用类隔离啦

Java 类隔离加载的正确姿势(其实就是重写classLoader的findClass与loadClass方法)

转载链接:https://mp.weixin.qq.com/s/ZIKP48aU8_hnp8YbdA0b1g

6.碰到NoSuchMethodError怎么解决?看这个

用了这么久的 Java,你知道 NoSuchMethodError 是怎么产生的吗?(同时设计maven依赖仲裁机制)

转载链接:https://mp.weixin.qq.com/s/RTzuwrawXN_P4HOp-6-eKw

7.送你们一些面试题啦

Java面试常用知识(附简历模板)

转载链接:https://mp.weixin.qq.com/s/RKLrMC0K5z-WjTFv58CtjQ

posted @ 2020-10-07 12:39  powerZhangFly  阅读(184)  评论(2)    收藏  举报