高薪程序员必修课-java中 类加载器以及JVM类加载机制

前言

        在Java中,类加载器(ClassLoader)是Java虚拟机(JVM)的一个重要组成部分,负责将.class文件加载到内存中并生成对应的Class对象。类加载器的主要任务是动态加载Java类,即在程序运行时根据需要加载类,而不是在编译时就全部加载。

JVM类加载机制

JVM的类加载机制遵循一定的规则和顺序,主要包括以下几个步骤:

  1. 加载(Loading)

    加载阶段是指查找并加载类的二进制数据(.class文件)到JVM中的内存中。加载类的任务由类加载器完成,JVM内置了三个主要的类加载器:

    • Bootstrap ClassLoader:也称为引导类加载器,负责加载JVM自身需要的类,如java.lang.Object等核心类库,它是JVM的一部分,通常用本地代码实现,无法直接在Java代码中获取到。

    • Extension ClassLoader:扩展类加载器,负责加载JVM扩展目录(<JAVA_HOME>/lib/ext目录)中的类库。在Java中可以通过ClassLoader.getSystemClassLoader().getParent()获取到扩展类加载器。

    • System ClassLoader:也称为应用程序类加载器,负责加载应用程序classpath下的类,即开发者自己编写的类。在Java中可以通过ClassLoader.getSystemClassLoader()获取到应用程序类加载器。

  2. 链接(Linking)

    链接阶段包括三个子阶段:

    • 验证(Verification):确保加载的类符合JVM规范,如字节码验证,验证类文件是否有效。

    • 准备(Preparation):为类的静态变量分配内存,并设置默认初始值(零值)。

    • 解析(Resolution):将类中的符号引用替换为直接引用,即转化为可以直接使用的内存地址。

  3. 初始化(Initialization)

    初始化阶段是类加载的最后一个阶段,负责执行类变量的初始化和静态代码块的执行。初始化类的条件包括:

    • 创建类的实例。
    • 访问类的静态变量或静态方法。
    • 初始化类的子类。

    类的初始化是按照初始化顺序执行静态变量和静态代码块,且只会执行一次。

  4. 使用(Using)

    在使用阶段,类被实际使用,包括创建对象、调用方法等操作。

  5. 卸载(Unloading)

    类卸载阶段是指JVM在满足一定条件时,卸载不再需要的类,释放相关的内存空间。类卸载的条件包括类的实例都已经被GC回收,并且该类的ClassLoader也没有被引用。

类加载器(ClassLoader)

类加载器是Java的一个重要概念,它负责加载Java类到内存中,并生成对应的Class对象。类加载器根据不同的加载需求和类路径,将类加载到JVM中,它的主要特点包括:

  • 双亲委派模型:JVM采用双亲委派模型来组织类加载器。即当一个类加载器接收到加载类的请求时,它会先委托给父类加载器加载,只有在父类加载器无法完成加载时,子类加载器才会尝试加载。这样可以保证类的加载顺序和避免重复加载。

  • 类加载器层次:JVM中的类加载器形成了层次结构,从而形成了加载类的优先级。Bootstrap ClassLoader位于顶层,Extension ClassLoader和System ClassLoader位于其下,开发者可以根据需要自定义ClassLoader来加载类。

  • 自定义类加载器:开发者可以通过继承ClassLoader类来自定义类加载器,以实现特定的加载需求,如从网络中加载类、加密类加载等。

示例

以下是一个简单的自定义类加载器示例,用于从指定路径加载类:

public class CustomClassLoader extends ClassLoader {
    private String classPath;

    public CustomClassLoader(String classPath) {
        this.classPath = classPath;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        try {
            byte[] data = loadClassData(name);
            return defineClass(name, data, 0, data.length);
        } catch (IOException e) {
            throw new ClassNotFoundException(name);
        }
    }

    private byte[] loadClassData(String className) throws IOException {
        String fileName = classPath + File.separatorChar + className.replace('.', File.separatorChar) + ".class";
        try (InputStream ins = new FileInputStream(fileName)) {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            int bufferSize = 1024;
            byte[] buffer = new byte[bufferSize];
            int bytesNumRead;
            while ((bytesNumRead = ins.read(buffer)) != -1) {
                baos.write(buffer, 0, bytesNumRead);
            }
            return baos.toByteArray();
        }
    }

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        String classPath = "/path/to/classes";
        CustomClassLoader loader = new CustomClassLoader(classPath);
        Class<?> clazz = loader.loadClass("com.example.MyClass");
        Object obj = clazz.newInstance();
        // 使用加载的类实例
    }
}

总结

        类加载器和JVM类加载机制是Java语言动态性和灵活性的基础之一。了解类加载的过程、类加载器的种类和工作原理,对于深入理解Java的类加载机制和解决类加载问题至关重要。

⭐️⭐️ ⭐️ ⭐️ ⭐️ 好书推荐
《Java项目开发全程实录》(第4版)

【内容简介】

        《Java项目开发全程实录(第4版)》以企业QQ、蓝宇快递打印系统、开发计划管理系统、酒店管理系统、图书馆管理系统、学生成绩管理系统、进销存管理系统、神奇Book—图书商城、企业门户网站、棋牌游戏系统之网络五子棋10个实际项目开发程序为案例,从软件工程的角度出发,按照项目的开发顺序,系统、全面地介绍了J2SE和J2EE项目的开发流程。从开发背景、需求分析、系统功能分析、数据库分析、数据库建模、网站开发和网站发布或者程序打包与运行方面进行讲解,每一过程都进行了详细的介绍。

📚 京东购买链接:Java项目开发全程实录(第4版)icon-default.png?t=N7T8https://u.jd.com/5QShvEG

  • 30
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值