【JVM】类的⽣命周期和类加载的过程

在Java中,类的生命周期和类加载过程是Java虚拟机(JVM)管理的核心部分。类的生命周期包括从类被加载到内存直到类被卸载的整个过程。类加载过程可以细分为多个阶段:加载、链接(包括验证、准备、解析)、初始化和使用。以下是详细的描述:

类的生命周期

  1. 加载(Loading)

    • 定义:将类的字节码从不同的源(如文件、网络等)加载到内存中,并生成一个代表这个类的Class对象。
    • 过程
      1. 通过类的全限定名获取定义此类的二进制字节流
      2. 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
      3. 在内存中生成一个代表这个类的Class对象,作为方法区数据结构的访问入口。
  2. 链接(Linking)

    • 定义:将类的二进制数据合并到JVM的运行时环境中。
    • 过程
      1. 验证(Verification):确保字节码的正确性和安全性。
        • 目的是保证加载的类符合JVM规范,不会危害虚拟机。
        • 验证的内容包括文件格式验证、元数据验证、字节码验证等。
      2. 准备(Preparation):为类的静态变量分配内存,并将其初始化为默认值。
        • 静态变量分配内存并初始化为零值,如int型的变量被初始化为0boolean型的变量被初始化为false
      3. 解析(Resolution):将常量池中的符号引用转换为直接引用。
        • 将类、字段、方法的符号引用替换为直接引用,这一过程通常在类初始化后进行,但也可以在运行时的某个阶段进行。
  3. 初始化(Initialization)

    • 定义:对类的静态变量赋初值,并执行静态代码块。
    • 过程
      • 执行类构造器<clinit>()方法。此方法是由编译器自动收集类中的所有静态变量的赋值动作和静态代码块中的语句合并产生的。
      • 若类有父类,则先初始化父类。
  4. 使用(Usage)

    • 定义:类加载到内存后,可以被实例化、调用其静态方法和字段。
    • 过程
      • 创建类的实例、调用类的静态字段和方法。
  5. 卸载(Unloading)

    • 定义:类在内存中占用的资源被释放。
    • 过程
      • 类卸载是由JVM的垃圾收集器完成的。当类的所有实例都被垃圾回收时,并且该类的ClassLoader实例也没有被引用,类将被卸载。

类加载器(Class Loader)

Java的类加载器负责动态地加载类。JVM提供了以下几种类型的类加载器:

  1. 启动类加载器(Bootstrap ClassLoader)

    • 加载:核心类库,如rt.jar,在JRE的lib目录下。
    • 实现:由C++实现,嵌入在JVM内部。
  2. 扩展类加载器(Extension ClassLoader)

    • 加载:扩展类库,位于jre/lib/ext目录或由系统变量java.ext.dirs指定的路径下的类库。
    • 实现:由Java实现,类名为sun.misc.Launcher$ExtClassLoader
  3. 应用程序类加载器(Application ClassLoader)

    • 加载:应用程序的类路径(classpath)下的类库。
    • 实现:由Java实现,类名为sun.misc.Launcher$AppClassLoader
  4. 自定义类加载器(Custom ClassLoader)

    • 定义:用户可以自定义类加载器,通过继承java.lang.ClassLoader类来实现。
    • 用途:满足特定的类加载需求,例如从网络加载类、对类进行加密和解密等。

类加载过程

  1. 加载(Loading)

    • 由类加载器读取类文件的二进制数据,并将其转换为方法区中的运行时数据结构。
    • 创建一个代表这个类的Class对象。
  2. 链接(Linking)

    • 验证(Verification):确保字节码文件的正确性和安全性。
    • 准备(Preparation):为类的静态变量分配内存,并将其初始化为默认值。
    • 解析(Resolution):将常量池中的符号引用转换为直接引用。
  3. 初始化(Initialization)

    • 执行类构造器<clinit>()方法。
    • 按照类加载顺序,从父类到子类依次执行。
  4. 使用(Usage)

    • 创建类的实例、访问静态变量和静态方法。
  5. 卸载(Unloading)

    • 当类的所有实例被垃圾收集器回收,并且没有对该类的引用时,类卸载,释放内存。

类加载的双亲委派模型

双亲委派模型确保类加载器在加载类时,先委派给父类加载器尝试加载类。如果父类加载器无法加载,才由当前加载器尝试加载。这一机制确保核心类库不会被重复加载,也防止了核心类库被篡改。

过程:
  1. 检查当前类加载器是否已加载此类
  2. 委派给父类加载器加载
  3. 父类加载器递归上述过程
  4. 如果父类加载器未能加载此类,由当前加载器加载

示例代码

以下是一个简单的自定义类加载器示例:

import java.io.*;public class CustomClassLoader extends ClassLoader {private String classPath;public CustomClassLoader(String classPath) {this.classPath = classPath;}@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {byte[] classData = loadClassData(name);if (classData == null) {throw new ClassNotFoundException();} else {return defineClass(name, classData, 0, classData.length);}}private byte[] loadClassData(String className) {String fileName = classPath + File.separatorChar + className.replace('.', File.separatorChar) + ".class";try (InputStream inputStream = new FileInputStream(fileName);ByteArrayOutputStream byteStream = new ByteArrayOutputStream()) {int nextValue = 0;while ((nextValue = inputStream.read()) != -1) {byteStream.write(nextValue);}return byteStream.toByteArray();} catch (IOException e) {e.printStackTrace();return null;}}public static void main(String[] args) throws Exception {CustomClassLoader classLoader = new CustomClassLoader("path/to/classes");Class<?> clazz = classLoader.loadClass("com.example.MyClass");Object instance = clazz.getDeclaredConstructor().newInstance();System.out.println(instance.getClass().getClassLoader());}
}

该自定义类加载器通过指定的路径加载类文件,展示了类加载的基本过程和原理。

总结

类的生命周期包括加载、链接、初始化、使用和卸载五个阶段。类加载过程则涉及到多个细节,包括验证、准备、解析和初始化。双亲委派模型确保了类加载的安全性和一致性。掌握这些知识可以更好地理解和优化Java应用程序的性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/29272.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

代码签名证书申请指南

申请代码签名证书的具体流程可以归纳为以下几个步骤&#xff1a; 1、确定证书类型&#xff1a; 根据您的需求选择合适的代码签名证书类型。常见的有OV&#xff08;Organization Validation&#xff0c;组织验证&#xff09;代码签名证书和EV&#xff08;Extended Validation&am…

Elasticsearch-ES查询单字段去重

ES 语句 整体数据 GET wkl_test/_search {"query": {"match_all": {}} }结果&#xff1a; {"took" : 123,"timed_out" : false,"_shards" : {"total" : 1,"successful" : 1,"skipped" : 0…

R语言自定义vlookup函数

############################################################## #######自定义函数integrate_and_match_values用于提取数据 ############################################################# integrate_and_match_values <- function(target_data,target_id_col,target_…

(一)Kafka 安全之使用 SSL 的加密和身份验证

目录 一. 前言 二. 使用 SSL 的加密和身份验证 2.1. 为每个 Kafka Broker 生成 SSL 密钥和证书 2.1.1. 主机名验证&#xff08;Host Name Verification&#xff09; 2.1.2. 注意&#xff08;Note&#xff09; 一. 前言 SSL&#xff08;Secure Sockets Layer&#xff09;是…

Oracle数据库面试题-14

81. 解释RAC&#xff08;Real Application Clusters&#xff09;的工作原理。 RAC&#xff08;Real Application Clusters&#xff09;是Oracle Corporation开发的高可用性解决方案&#xff0c;它允许用户将多个数据库实例集群在一起&#xff0c;以提高数据库系统的可用性和性…

【Java】已解决java.lang.IllegalAccessException异常

文章目录 一、问题分析背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决java.lang.IllegalAccessException异常 一、问题分析背景 在Java开发中&#xff0c;java.lang.IllegalAccessException是一个常见的运行时异常&#xff0c;它通常发生在尝试…

【人工智能】人工智能就业岗位发展方向有哪些?

人工智能领域的岗位多样&#xff0c;涵盖了从技术研发到应用实施、从产品设计到市场运营等各个方面&#xff0c;以下是人工智能就业岗位的主要发展方向 研发与应用岗位&#xff1a; 机器学习工程师&#xff1a;负责开发和实施机器学习算法&#xff0c;解决各种问题&#xff0c…

CDA二级(Level II)数据分析师——考试内容梳理二

逻辑回归&#xff1a;Ln(P/(1-P)-30.06X0.05X2-0.02X3X1 岭回归的扰动性越大&#xff0c;模型越不容易受到共线性的影响&#xff1b; LOSSO只是缓解了由于共线性导致的估计误差的问题&#xff0c;而不是解决共线性 &#xff1b; AUC值接近0.5时&#xff0c;我们认为这个模型…

ARM32开发--FreeRTOS-事件组

系列文章目录 知不足而奋进 望远山而前行 目录 系列文章目录 文章目录 前言 目标 内容 概念 事件标志位 开发流程 功能介绍 创建事件组 触发事件 等待事件触发 同步 清理事件 案例 总结 前言 在嵌入式系统开发中&#xff0c;任务之间的同步和通信是至关重要的…

智慧矿山项目建设整体解决方案(938页 )

智慧矿山&#xff0c;究竟是什么&#xff1f; 在深入探讨之前&#xff0c;让我们先来提出一个深刻的问题&#xff1a;我们能否借助科技的力量&#xff0c;让矿山作业不仅安全、高效&#xff0c;还能做到环保可持续&#xff1f;答案是肯定的。智慧矿山&#xff0c;正是这一理念…

支撑每秒 600 万订单无压力,SpringBoot + Disruptor 太猛了!

一、背景 工作中遇到项目使用Disruptor做消息队列,对你没看错,不是Kafka,也不是rabbitmq;Disruptor有个最大的优点就是快,还有一点它是开源的哦,下面做个简单的记录. 二、Disruptor介绍 Disruptor 是英国外汇交易公司LMAX开发的一个高性能队列&#xff0c;研发的初衷是解决内存…

【postgresql初级使用】条件表达式触发器,兼顾DML执行性能,又能执行复杂逻辑,只在结帐时计算总帐

条件触发器 ​专栏内容&#xff1a; postgresql使用入门基础手写数据库toadb并发编程 个人主页&#xff1a;我的主页 管理社区&#xff1a;开源数据库 座右铭&#xff1a;天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物. 文章目录 条件触发器概…

【docker入门】

在软件开发过程中&#xff0c;环境配置是一个至关重要的步骤&#xff0c;它不仅影响开发效率&#xff0c;也直接关联到软件的最终质量。正确的环境配置可以极大地减少开发中的潜在问题&#xff0c;提升软件发布的流畅度和稳定性。以下是几个关键方面&#xff0c;以及如何优化环…

【机器学习】第6章 支持向量机(SVM)

一、概念 1.支持向量机&#xff08;support vector machine&#xff0c;SVM&#xff09;&#xff1a; &#xff08;1&#xff09;基于统计学理论的监督学习方法&#xff0c;但不属于生成式模型&#xff0c;而是判别式模型。 &#xff08;2&#xff09;支持向量机在各个领域内的…

如何在不丢失数据的情况下解锁安卓手机密码

手机是我们生活中必不可少的工具&#xff0c;可以帮助我们与朋友和家人保持联系&#xff0c;了解最新消息&#xff0c;甚至经营我们的业务。然而&#xff0c;当我们在 Android 手机或 iPhone 上设置密码时&#xff0c;我们经常会忘记密码&#xff0c;或者根本没有设置密码。当这…

IntelliJ IDEA 使用 Maven 时不加载本地私服的最新版本快照(snapshot)JAR 包

IntelliJ IDEA 使用 Maven 时不加载本地私服的最新版本快照&#xff08;snapshot&#xff09;JAR 包 目录 IntelliJ IDEA 使用 Maven 时不加载本地私服的最新版本快照&#xff08;snapshot&#xff09;JAR 包1. 检查 settings.xml2. IDEA Maven 配置3. 强制更新 Snapshot4. 使用…

学习笔记——路由网络基础——路由度量值

3、路由度量值 (1)基本概念 路由度量值表示到达这条路由所指目的地址的代价。度量值数值越小越优先&#xff0c;度量值最小路由将会被添加到路由表中。度量值很多时候被称为开销(Cost)。 路由度量(路由开销 cost)对于同一个路由协议&#xff0c;当到达某目标网段有多条路由供…

SQL Server入门-安装和测试(2008R2版)

环境&#xff1a;win10&#xff0c;SQL Server 2008 R2 因为工作需要用到SQL Server&#xff08;而且要用2008R2版&#xff09;&#xff0c;完全不熟&#xff0c;所以来学习学习。 SQL Server是微软开发的关系型数据库&#xff0c;支持SQL。同时还有微软还开发了自己的T-SQL&am…

Fontconfig head is null, check your fonts or fonts configuration问题解决

报错信息&#xff1a; Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [R equest processing failed: com.alibaba.excel.exception.ExcelGenerateException: java.lang.InternalError: java.lang.reflect.InvocationTargetExcep…

11 类型泛化

11 类型泛化 1、函数模版1.1 前言1.2 函数模版1.3 隐式推断类型实参1.4 函数模板重载1.5 函数模板类型形参的默认类型&#xff08;C11标准&#xff09; 2、类模版2.1 类模板的成员函数延迟实例化2.2 类模板的静态成员2.3 类模板的递归实例化2.4 类模板类型形参缺省值 3、类模板…