JVM-类加载器

类加载器的树状层次结构

  • systems class loader
    用于加载java应用中的类,加载器为APPClassLoader
    如新建一个User类,这个类首先由APPClassLoader导入

  • Extensions Class Loader
    APPClassLoader的parent,用于加载jre/ext/*.jar

  • BootStrap class loader
    ExtClassLoader的parent,由C++实现,通过getParent()获取为null,

双亲委派机制

某个特定类加载器接收到加载请求后,首先将加载任务向其父类加载器委托,直至最父类加载器,如果最父类能够执行加载则成功返回,否则向下传递,由某个子类加载器执行加载

优点:

  • 保证java核心库的安全,不会因为用户编写的代码破坏java核心类

类加载过程

装载

查找并加载类的二进制数据

链接
  • 验证:确保类符合JVM规范,没有安全问题
  • 准备:为静态变量分配内存,并初始化为默认值
  • 解析:把虚拟机常量池中的符号引用转换为直接引用
初始化

为静态变量赋予正确的初始值

自定义类加载器

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;

public class MyClassLoader extends ClassLoader {
    private String rootPath;

    public MyClassLoader(String rootPath) {
        this.rootPath = rootPath;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        //检查类是否已经加载
        Class<?> c = findLoadedClass(name);
        if(c!=null){
            return c;
        }
        //加载类
        byte[] data = getClassData(name);
        if(data==null){
            throw new ClassNotFoundException();
        }else{
            c = defineClass(name,data,0,data.length);
            return c;
        }
    }

    private byte[] getClassData(String className) {

        String path = rootPath+"/"+className.replace('.','/')+".class";
        InputStream is = null;
        ByteArrayOutputStream bos = null;
        try {
            is = new FileInputStream(path);
            bos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int temp = 0;
            while((temp = is.read(buffer))!=-1){
                bos.write(buffer,0,temp);
            }
            return bos.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            try {
                is.close();
                bos.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

测试类:

public class Main {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        MyClassLoader loader = new MyClassLoader("C://zy");
        Class<?> c = loader.loadClass("test.Hello");
        Method m = c.getDeclaredMethod("test");
        m.invoke(c.newInstance());
        System.out.println();
    }
}
posted @   你也要来一颗长颈鹿吗  阅读(26)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示