加载系统"/>
2.jvm类加载系统
目录
- 概述
- 类加载器
- 执行顺序
- 加载时机与过程
- 类加载的四个时机
- 一个类的一生
- 类加载途径
- 自定义类加载器
- 工作准备
- 编写自定义加载器
- 结果
- 结束
概述
类加载器
jvm 的类加载是通过 ClassLoader 及其子类来完成的。
有以下类加载器
注意: bootstrap 引导程序
根据上图总结如下
- 启动类加载器(Bootstrap ClassLoader):负责加载 JAVA_HOME\lib 目录或通过 -Xbootclasspath 参数指定路径中的且被虚拟机认可(rt.jar) 的类库。
- 扩展类加载器(Extension ClassLoader):负责加载 JAVA_HOME\lib\ext 目录或者通过 java.ext.dirs 系统变量指定路径中的类库。
- 应用程序类加载器(Application ClassLoader):负责加载用户路径 classpath 上的类库 (自己编写的程序在此加载)
- 自定义类加载器(User ClassLoader):加载应用之外的类文件 (例如:JRebel 热部署)
执行顺序
来看一下图:
- 检查顺序是自底向上: 加载过程中会先检查类是否被已加载,从 Custom 到 BootStrap 逐层检查,只要
某个类加载器
已加载就视为此类已加载
,**好处:**保证此类所有 ClassLoader 只加载一次。 - 加载的顺序是自顶向下: 也就是由上层来逐层尝试加载此类。
加载时机与过程
类加载的四个时机
public class Student{private static int age;public static void method(){}
}// Student.age
// Student.method();
// new Student();
Class t = Class.forName("java.lang.Thread")
- 遇到 new、getStatic、putStatic、invokeStatic 四条指令时
- 使用 java.lang.reflect 包方法时,对类进行反射调用
- 初始化一个类时,发现其父类还没初始化,要先初始化其父类
- 当虚拟机启动时,用户需要指定一个主类 main,需要先将主类加载
一个类的一生
当一个 .java 文件被编译成 class 文件
类的生命周,而非对象的生命周期,看下图
类加载主要做了三件事:
- 1.根据
类全限定名称
,二进制字节流加载 class 文件 - 2.字节流静态数据 ,进入方法区 (永久代、元空间)
- 3.创建字节码 Class 对象
类加载途径
加载途径总结如下:
- 1.jar/war
- 2.jsp生成的 class
- 3.数据库中的二进制字节流
- 4.网络中的二进制字节流
- 5.动态代理生成的二进制字节流
自定义类加载器
工作准备
准备好需要加载的类,代码很简单
package com.fun.demo;public class Test {public void say() {System.out.println("hello jvm");}
}
编译完成后放置如下路径: /Users/hyl/Desktop/jk/jvm/lib/com/fun/demo
编写自定义加载器
自定义类加载器 CustomClassLoader 继承 ClassLoader ;重写 findClass()方法,在findClass方法中调用 defineClass() 方法
自定义加载器如下,代码还是很简单的。
package com.fun.classloader;import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;public class CustomClassLoader extends ClassLoader {private String rootPath;public CustomClassLoader(String rootPath) {this.rootPath = rootPath;}@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {// name 传进来的全类名称String absolutePath = rootPath + "/" + name.replace(".", "/") + ".class";try {FileInputStream in = new FileInputStream(absolutePath);byte[] classByte = in.readAllBytes();return defineClass(null, classByte, 0, classByte.length);} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException exception) {exception.printStackTrace();}return null;}
}
测试代码如下:
package com.fun.classloader;import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Objects;public class Test {//public static void main(String[] args) {// String tmp = "com.fun.demo.Test";// System.out.println(tmp.replace(".", "/"));//}public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {CustomClassLoader loader = new CustomClassLoader("/Users/hyl/Desktop/jk/jvm/lib");Class<?> clz = loader.loadClass("com.fun.demo.Test");if (Objects.nonNull(clz)) {Object o = clz.newInstance();Method method = clz.getMethod("say", null);method.invoke(o, null);}}
}
结果
运行 main 方法,得到的效果如下:
结束
至此,jvm 类加载系统就结束了,如有疑问,欢迎评论区留言。
更多推荐
2.jvm类加载系统
发布评论