1.jvm虚拟机内存模型
类加载子系统
运行时数据区: 堆 栈 本地方法栈 方法区(元空间):常量+静态变量+类元信息 程序计数器 字节码执行引擎
2.类加载过程
加载; 在硬盘上查找并通过IO读入字节码文件,使用类时才会加载,例如调用类的main()方法,new对象等等 验证: 校验字节码文件的正确性 准备: 给类的静态变量分配内存,并赋予默认值 解析: 将符号引用替换为直接引用,该阶段会把一些静态方法(符号引用,比如main()方法)替换为指向数据所存内存的指针, 或句柄等(直接引用),这是所谓的静态连接过程(类加载期间完成),动态链接是在程序运行期间完成的将符号引用替换为 直接引用 初始化: 对类的静态变量初始化为指定的值,执行静态代码块
public class Tuling { public static void main(String[] args) { System.out.println(String.class.getClassLoader()); System.out.println(com.sun.crypto.provider.DESedeKeyFactory.class.getClassLoader().getClass().getName()); System.out.println(Tuling.class.getClassLoader().getClass().getName()); System.out.println(ClassLoader.getSystemClassLoader().getClass().getName()); }
运行结果:
null sun.misc.Launcher$ExtClassLoader sun.misc.Launcher$AppClassLoader sun.misc.Launcher$AppClassLoader
3.类加载器:
启动类加载器: jvm运行的位于jre/lib 目录下的核心类库 比如:rt.jar, charsets.jar等
扩展类加载器: 负责加载 位于jie的lib目录下的ext扩展目录中的jar类包
应用程序类加载器: 负责加载classPath路径下的类包,主要就是加载你自己写的那些类
自定义加载器:负责加载用户自定义路径下的类包
4. 查看jvm字节码执行情况
javap -c Tuling.class
5. 自定义类加载器 和类加载器不生效的处理
https://www.cnblogs.com/sunhao1234/p/12343967.html
// 自定义类加载器
package com.tuling;
/** * Title: User * Description: TODO * * @author hfl * @version V1.0 * @date 2020-11-23 */ public class User { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override protected void finalize() throws Throwable { System.out.println("关闭资源,user " + name + "即将回收"); } public void sout(){ System.out.println("=============自己的加载器加载类调用方法============"); } }
package com.tuling; import java.io.FileInputStream; import java.lang.reflect.Method; /** * Title: MyClassLoaderTest * Description: TODO * * @author hfl * @version V1.0 * @date 2020-11-23 */ public class MyClassLoaderTest { static class MyClassLoader extends ClassLoader { private String classPath; public MyClassLoader(String classPath) { this.classPath = classPath; } private 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; } @Override protected Class<?> findClass(String name) throws ClassNotFoundException { try { byte[] data = loadByte(name); return defineClass(name, data, 0, data.length); } catch (Exception e) { e.printStackTrace(); throw new ClassNotFoundException(); } } } public static void main(String[] args) throws Exception { MyClassLoader classLoader = new MyClassLoader("D:/test"); Class<?> clazz = classLoader.loadClass("com.tuling.User"); Object obj = clazz.newInstance(); Method method = clazz.getDeclaredMethod("sout", null); method.invoke(obj, null); System.out.println(clazz.getClassLoader().getClass().getName()); } }
运行结果:
=自己的加载器加载类调用方法
com.tuling.MyClassLoaderTest$MyClassLoader
完