浅析JVM

一、JVM运行流程

如图:
请添加图片描述
JVM由四个部分构成:

  • 1.类加载器
    加载类文件到内存
  • 2.运行时数据区
    写的程序需要加载到这里才能运行
  • 3.执行引擎
    负责解释命令,提交操作系统执行
  • 4.本地接口
    融合不同编程语言为java所用,如Java程序驱动打印机

二、JVM内存区域

请添加图片描述
其中, 方法区 是各个线程共享的一块逻辑内存区域,它用于存储已经被虚拟机加载的类型信息、常量、静态变量、即使编译器编译后的代码缓存等数据。方法区的实现在 Java8后的HotSpot虚拟机采用的是元空间(元空间在本地内存)。
Java8之前,HotSpot虚拟机采用的是永久代(永久代在堆内存)来实现的方法区,这样HotSpot的垃圾收集器能够像管理Java堆内存一样管理这部分内存,省去了为方法区编写内存管理代码的工作。但是其他虚拟机实现方法区时不存在永久代的概念。

三、类加载机制

Java程序不是一次性加载所有类到内存中的。JVM在运行时按需加之类。类加载机制负责将.class文件从磁盘、网络等地方的资源加载到JVM的方法区,并最终在堆内存中创建对应Class对象,作为访问该类型元数据的入口。

1.类加载的生命周期

  • 1.加载
    • 任务:查找并加载类的.class文件
    • 结果:在方法区(jdk1.7)/元空间(jdk1.8)创建类运行时数据结构,并在堆内创建一个代表该类的一个java.lang.Class对象作为访问这些数据的入口。
      java.lang.Class 对象是 Java 类的运行时表示。它包含了类的元数据(如类名、字段、方法、构造函数等信息),并且提供了访问这些元数据的方法。通过 Class 对象,程序可以在运行时动态地获取类的信息、创建类的实例、调用方法、访问字段等。
  • 2.验证:
    • 目的:确保被加载类的字节码文件是安全、合法的,符合JVM规范的,不会危害JVM安全的。
    • 检查内容:
      • 文件格式验证
      • 元数据验证(语义分析:是否有父类、是否继承 final 类、方法覆盖是否合法等)
      • 字节码验证(最复杂:检查方法体中的指令逻辑是否合法、类型转换是否安全、跳转指令是否指向合理位置等)
      • 符号引用验证(发生在解析阶段,检查符号引用能否被正确解析)
  • 3.准备:
    • 目的:为类的静态变量分配内存(在方法区/元空间)并设置初始零值。
  • 4.解析:
    • 目的:将常量池的符号引用改成直接引用
    • 符号引用:一组符号描述引用的目标
    • 直接引用:可以是直接指向目标的指针、相对偏移量或能间接定义到目标的句柄。
    • 解析目标:类或接口、字段、类方法、接口方法、方法类型、方法句柄、调用点限定符。
  • 5.初始化:
    • 目标:执行类的初始化代码(() 方法)。
    • () 方法:由编译器自动收集类中所有类变量的赋值动作和静态语句块 (static{} 块) 中的语句合并生成。
    • 触发时机:首次主动创建一个类时
    • 父类优先: JVM 保证一个类的 () 方法执行前,其父类的 () 方法必须已执行完毕。
    • 线程安全:JVM 会确保 () 方法在多线程环境下被正确地加锁同步执行(只有一个线程能执行)。
  • 6.使用
  • 7.卸载

2.类加载器

负责实现“加载”阶段。JVM 内置三类重要的类加载器,它们之间存在层次关系(双亲委派模型的基础):

  • 1.启动类加载器(Bootstrap ClassLoader):
    • 是JVM自身的一部分
    • 加载 JAVA_HOME/lib 目录下的核心类库(如 rt.jar, resources.jar, charsets.jar)或 -Xbootclasspath 参数指定的路径下的类。
  • 2.扩展类加载器(Extension ClassLoader / Platform ClassLoader - JDK9+):
    • 加载 JAVA_HOME/lib/ext 目录或 java.ext.dirs 系统变量指定路径下的类库。
  • 3.应用程序加载器(Application ClassLoader / System ClassLoader):
    • 加载用户类路径 (ClassPath) 下的类库。开发者编写的类通常由此加载器加载。
    • 是程序中 ClassLoader.getSystemClassLoader() 的默认返回值。

四、双亲委派

当类加载器收到类加载请求时:

  • 1.委派父加载器:不会立刻加载职工类,而是先委派给父加载器来加载。
  • 2.递归委派:直到订层的启动类加载器
  • 3.父加载器尝试加载:
    • 如果父加载器可以完成加载任务(在其负责的范围内找到了该类),则成功返回该类。
    • 如果父加载器无法完成加载任务(在其负责范围内找不到该类),则子加载器才会尝试自己去加载。
    • 如果子加载器也找不到,则抛出 ClassNotFoundException。
      在这里插入图片描述

优势

  • 1.避免重复加载
  • 2.保证核心类库安全:例如,即使你在 ClassPath 下写了一个 java.lang.Object 类,由于双亲委派,请求会最终委派给 Bootstrap Loader,它加载了真正的核心 Object 类,你的自定义 Object 不会被加载。
  • 3.保证基础类的统一性:确保核心类库(如 java.lang.String)对所有子加载器可见且一致。

打破双亲委派的情况

  • SPI (Service Provider Interface): 如 JDBC。核心接口在 rt.jar 由 Bootstrap Loader 加载,但数据库厂商的实现类在 ClassPath 下需要由 AppClassLoader 加载。为了解决这个矛盾,引入了线程上下文类加载器 (Thread Context ClassLoader, TCCL),它通常默认是 AppClassLoader。核心代码(如 DriverManager)在需要加载 SPI 实现时,使用 TCCL 来加载。
  • 热部署/热替换: 如 Tomcat, OSGi。需要同一个类的不同版本共存。自定义类加载器需要能独立加载同一类名的不同版本,不遵循父优先原则,而是先自己尝试加载。
  • 代码热替换 (HotSwap): 在调试时替换修改过的类,需要类加载器能重新加载类。

五、垃圾回收机制

1.判断对象是否存活

1.引用计数法:

  • 原理:为每个对象维护一个计数器,当对象被引用时计数器+1,引用失效时计数器-1,计数器为0时对象可回收。
  • 缺点:无法解决循环引用问题(A 引用 B,B 引用 A,但 A 和 B 都不再被外部引用,计数器不为0)。

2.可达性分析算法

  • 原理: 通过一系列称为 “GC Roots” 的根对象作为起始点集,从这些节点开始向下搜索,搜索过程走过的路径称为 “引用链 (Reference Chain)”。如果一个对象到 GC Roots 没有任何引用链相连(即不可达),则证明此对象是不可用的,可以被回收。
  • GC Roots 对象包括:
    • 虚拟机栈(栈帧中的本地变量表)中引用的对象。
    • 本地方法栈中 JNI(即 Native 方法)引用的对象。
    • 方法区中类静态属性引用的对象。
    • 方法区中常量引用的对象(如字符串常量池里的引用)。
    • Java 虚拟机内部的引用(如基本数据类型对应的 Class 对象,常驻的异常对象 NullPointerException、OutOfMemoryError 等,系统类加载器)。
    • 所有被同步锁(synchronized 关键字)持有的对象。
    • 反映 Java 虚拟机内部情况的 JMXBean、JVMTI 中注册的回调、本地代码缓存等。
  • 主流 JVM 使用此方法。

3.引用类型:

  • 1.强引用:强引用不能被回收。
  • 2.软引用:当内存不足时才会被回收。
  • 3.弱引用:下一次GC就被回收。
  • 4.虚引用:最弱的引用。无法通过虚引用获取对象实例。唯一目的是对象被回收时收到一个系统通知。用于跟踪对象被垃圾回收的活动。

4.垃圾回收算法

  • 1.标记清除法:
    • 步骤:遍历GC Roots标记所有可达对象,清除所有未被标记的对象。
    • 缺点:慢,空间碎片化。
  • 2.复制算法:
    • 步骤:将可用内存按容量划分为大小相等的两块(A 和 B)。每次只使用其中一块(如 A)。当 A 用完了,就将 A 中还存活的对象复制到 B 上,然后一次性清理掉 A 上的所有空间。交换角色(现在使用 B)。
    • 优点:块,无大量不连续碎片内存。
    • 缺点:内存缩小为原来的一半,代价高昂。适用于对象存活率低的场景(如新生代的 Eden 和 Survivor 区)。
  • 3.标记整理法:
    • 步骤:遍历GC Roots标记所有可达对象,清除所有未被标记的对象,并且将存活对象都移动到空间的一端。
    • 优点:没有内存碎片。
    • 缺点:移动存活对象并更新引用地址需要 STW (Stop-The-World) 时间较长。适用于对象存活率高的场景(如老年代)。
  • 4.分代收集算法:
    • 核心思想:根据对象存活周期的不同将堆划分为新生代 (Young Generation) 和老年代 (Old Generation)。
    • 新生代特点: 对象创建频繁,存活率低。
      • 回收算法: 主要采用复制算法(Minor GC / Young GC)。
    • 老年代特点: 对象存活周期长,存活率高。
      • 回收算法: 主要采用标记-清除或标记-整理算法(Major GC / Full GC)。

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

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

相关文章

多个 Job 并发运行时共享配置文件导致上下文污染,固化 Jenkins Job 上下文

基于 context.py 固化 Jenkins Job 上下文的完整方案,适用于你当前的工作流(Python Jenkins Pipeline),解决: 多个 Job 并发运行时共享配置文件导致上下文污染;读取环境变量或 JSON 文件时被其他 Job 修改…

简木易支付系统 功能齐全,对接接口超多

简木易支付系统,作为一款引领行业潮流的卓越支付解决方案,依托先进的 PHP MySQL 技术架构精心打造。在开发过程中,它巧妙运用了功能强大的 ThinkPHP8 框架,完美融合前端主流技术 Vue、Element 以及 Layuiadmin,共同铸…

【软考高项论文】信息系统项目的人力资源管理

摘要 本文围绕信息系统项目的人力资源管理展开论述。以我在2024年参与的为大型国有企业构建供应链管理系统项目为例,阐述了项目人力资源管理的主要流程,包括规划、组建、建设和管理团队四个过程,以及所运用的工具和理论。同时,分…

【EI会议征稿】东北大学主办第三届机器视觉、图像处理与影像技术国际会议(MVIPIT 2025)

一、会议信息 大会官网:www.mvipit.org 官方邮箱:mvipit163.com 会议地点:辽宁沈阳 主办单位:东北大学 会议时间:2025 年 9 月 27 日-9 月 29 日 二、征稿主题 集中但不限于“机器视觉、图像处理与影像技术”等其…

从零开始的云计算生活——第二十三天,稍作休息,Tomcat

目录 一.故事背景 二.Tomcat概述 1、Tomcat介绍 2、Tomcat历史 二、Tomcat原理分析 1、Http工作原理 2、Tomcat整体架构 3、Coyote连接器架构 4、Catalina容器架构 5、Jasper处理流程 6、JSP编译过程 7、Tomcat启动流程 8、Tomcat请求处理流程 三、Tomcat安装与配…

几种基于Doherty结构的GAN氮化镓功放设计方法介绍

功率放大器是现代无线通信系统中最重要的组件之一。理想情况下,它们能够以高线性度和高效率提供高输出功率。但通常在这三个关键的功率放大器性能参数之间需要进行权衡取舍,而且具有最高输出功率和线性度的放大器往往会牺牲效率。 在支持宽带宽和高数据…

前端打印计算单位 cm、mm、px

A4 纵向 宽:21cm,210mm,793.698px 高:29.7cm,297mm,1122.520px A4 横向 宽:29.7cm,297mm,1122.520px 高:21cm,210mm,793.698px …

c# sugersql 获取子表数据排序

在C#中使用Sugar ORM(一个流行的.NET ORM框架)获取子表数据并进行排序,可以通过以下几种方式实现: 1. 使用HasMany或HasOne配置 首先,确保你在配置实体时已经正确设置了HasMany或HasOne关系。例如,假设你…

【nRF52832】【环境搭建 3】【如何新建一个纯单片机开发的工程】

1. 前言 笨叔,又要开始扯淡了!!! 不感兴趣的同学,可以跳过了!!! 笨叔之前在大学里面, 刚接触单片机时。就被 windows 平台 例如 keill 5 、IAR 等一堆开会环境差点劝退。 当时也是坚持咬牙一点点摸索过来的。刚摸索明白,觉得单片…

Spring-loC与DI

目录 1 loC控制反转思想 2 DI依赖注入 3 loC详解 3.1 存储Bean (1)Controller (2)Service (3)Repository (4)Component (5)Configuration &#xf…

职业本科单片机与嵌入式技术实训室建设设想

一、引言 在当今数字化与智能化飞速发展的时代,单片机与嵌入式技术作为信息技术领域的关键支撑,广泛应用于工业控制、智能家居、物联网、汽车电子等众多行业,成为推动产业升级和创新发展的核心驱动力。职业本科教育旨在培养适应生产、建设、…

传统消防演练与 VR 消防演练的区别有哪些

演练形式:传统消防演练往往依托真实的场地,像空旷的广场、废弃的建筑物或是专门的消防训练基地等。参与者能触摸并使用实实在在的消防设备,例如干粉灭火器、二氧化碳灭火器、消防水带等。在演练时,会通过点燃模拟火源、释放烟雾等…

【零基础学AI】 第6讲:数据可视化基础

本节课你将学到 理解数据可视化在AI中的重要作用 掌握Matplotlib的基本架构和核心概念 学会创建各种类型的图表(线图、柱状图、散点图、饼图等) 掌握图表美化和自定义技巧 完成销售趋势图表制作实战项目 开始之前 什么是数据可视化? 数据可…

基于SSM+JSP 的旅游管理系统

【旅游景点管理系统】【送文档】|SSM | JSP 【运行开发环境】 jdk1.8 idea mysql maven tomcat 【技术栈】 Spring SpringMVC mybatis JSP 【项目功能】 两个角色;管理员功能有游客管理、轮播图管理、景点管理、景点类型管理;普…

系统 | 电脑重置 图文教程

背景: 换内存条,换完,声卡网卡崩盘,分析原因可能是未断电操作(什么光感自动断电 还是手动的香),网卡由于代理没关,关完即可。声卡一直没好,电脑店说是硬件问题;自行排查了…

MyBatis深度面试指南

一、MyBatis核心解析:半ORM框架的底层真相 1. 本质与工作流 半ORM定义: 对象映射:通过ResultMap将ResultSet自动转为Java对象(省去JDBC手动映射)。SQL控制:开发者需手动编写SQL,框架不自动生成(与Hibernate核心区别)。工作流四步: 解析mybatis-config.xml → 构建Sq…

使用Docker部署mysql8

1、拉取mysql8的镜像: 1 [rooti-zgn6som8 ~]# docker pull mysql:8.0 2、创建配置和数据文件夹并修改权限: 1 2 3 4 mkdir -p /data/mysql8/conf mkdir -p /data/mysql8/data chmod -R 755 /data/mysql8/ 3、配置一个自定义的配置文件my.cnf: 1 …

Vue3—插槽solt

默认插槽 父组件 <Sidebar><div>{{ strData }}</div></Sidebar> let strData ref(我是你爸爸真伟大&#xff0c;养你这么大);//定义插槽数据子组件 <slot>没有数据&#xff0c;我先默认显示一下 loading。。。。。。。</slot>父组件提供…

时间同步 gptp ptp

目录 车载以太网PTP报文分析**PTP协议基础****PTP报文类型与功能****PTP报文格式解析****时钟同步原理与计算****车载以太网PTP分析工具****典型分析场景****车载场景特殊考虑**gPTP与PTP的对比解析**1. 基本概念****2. 核心差异对比****3. 技术细节对比****报文结构****主时钟…

AWS WebRTC:通过shell实现多进程启动viewer

​ 前面总结了aws webrtc sdk-c项目中多进程启动master的shell脚本,具体参考:https://blog.csdn.net/zhang_jiamin/article/details/148616899 这次总结一下多进程启动viewer的shell脚本,以及过程中遇到的问题和解决方法。 实现说明: 1、获取 sid 和 uid(用于认证) 2、…