java des zeropadding JVM垃圾回收机制-全面详解

java des zeropadding JVM垃圾回收机制-全面详解

1.本地磁盘:Java代码经javac编译生成.class文件;

2.网络下载:如远程RPC调用的类文件、动态加载的网络资源;

3.包解压:war/jar包运行时解压的class文件;

4.数据库/缓存:从数据库、Redis等读取的动态生成class文件;

5.动态代理:通过cglib、JDK动态代理生成代理类class文件(如 Aop);

(二) 类加载全流程

7个阶段:加载->验证->准备->解析->初始化->使用->卸载

1.加载:获取二进制流并生成class对象

通过类的全限定名(包名+类名。如java.lang.)获取类的二进制字节流;

将字节流转化成JVM可识别的运行时数据结构,存入方法区;

在堆中生成一个代表该类的java.lang.Class对象,作为该方法区类信息的访问入口;

实战案例:框架中

启动时,会通过类加载器加载配置文件中指定的Bean类,生成Class对象后完成实例化。

2.链接:验证+准备+解析,保证类的合法性

(1) 验证:校验Class文件格式和语义合法性(4层校验,防止恶意字节码)

文件格式验证:保证符合Class文件规范;

元数据验证:校验类的继承/实现关系(如不能继承final类、接口方法需实现);

字节码验证:分析字节码指令逻辑,防止死循环、栈溢出等非法操作;

符号引用验证:校验符号引用的目标存在(如引用的类 / 方法 / 字段未找到则抛);

实战案例:开发中遇到java.lang.,大概率是 Class 文件被篡改、版本不兼容(如高版本 JDK 编译的类在低版本 JVM 运行)导致验证失败。

(2) 准备:为静态变量分配内存并设置默认值为零

仅处理静态变量(),实例变量在对象实例化时分配在堆中;

静态变量初始值为数据类型零值(如 int=0、=null、=false),而非用户定义的初始值;

实战案例:定义 int num = 10;,准备阶段 num 被设为 0,直到初始化阶段才会赋值为10。

(3) 解析:将符号引用转为直接引用

符号引用:用一组符号描述引用目标(如类名、方法名,无实际内存地址);

直接引用:指向目标的内存指针、偏移量(真实内存地址);

解析对象:类、接口、字段、方法、方法句柄等;

实战案例:调用.()时,解析阶段会将符号引用转为方法区中方法的实际内存地址。

3.初始化:执行类构造器(),设置用户定义的初始值

核心:执行静态变量赋值操作和静态代码块,按代码书写顺序执行;

类构造器():由 JVM 自动生成,无需手动定义,若没有静态变量和静态代码块,则不会生成;

触发时机:主动使用类时触发(如创建实例、调用静态方法 / 变量、反射调用、初始化子类时先初始化父类),被动使用不触发(如引用静态常量、通过子类引用父类静态变量)。

实战案例1:Class.(“com.mysql.cj.jdbc.”)会主动初始化 MySQL 驱动类,执行静态代码块注册驱动,这是 JDBC 传统方式的核心原理;

实战案例2:定义 final int NUM = 10;,因NUM是编译期常量,其他类引用NUM时不会触发此类的初始化(被动使用)。

(三) 类加载器的种类(从顶层到底层)

JVM提供 3 种内置类加载器,开发者可通过继承java.lang.实现定制化类加载器,满足个性化需求。

类加载器

核心职责

加载路径/实例

启动类加载器()

加载 JVM 核心类库(java.lang/java.util等),由 C++ 实现,无 Java 对象

JRE/lib/rt.jar、.jar

扩展类加载器()

加载 Java 平台扩展类库,补充核心类库

JRE/lib/ext/*.jar

应用类加载器()

加载用户类路径() 下的类,是程序开发的默认加载器

项目 /、第三方 jar 包

自定义类加载器

按需加载类,突破 限制

加载网络 / 数据库中的 class 文件

实战案例: 实现了自定义类加载器(),每个 Web 应用对应一个独立的类加载器,实现应用之间的类隔离,避免不同应用的同名类冲突。

(四) 双亲委派机制(JVM类加载的核心原则)

1.核心原则:当一个类加载器收到类加载请求时,首先将请求委派给父类加载器,依次向上直到启动类加载器;只有当父类加载器无法加载(在其加载路径中未找到该类)时,子类加载器才会尝试自己加载。

检查顺序:自底向上(子→父),检查类是否已被加载;

加载顺序:自顶向下(父→子),尝试加载类。

2.核心优势:

避免类重复加载:父类加载器已加载的类,子类加载器不会再次加载;

保证核心类库的安全性:防止自定义类篡改核心类(如自定义java.lang.,因双亲委派会优先由启动类加载器加载核心,自定义类不会被加载)。

3.双亲委派的打破

部分框架为实现类隔离或动态加载,会打破双亲委派(重写的方法),如 、 Boot、OSGi。

实战案例: Boot 的er打破双亲委派,优先加载应用自身的类,再委派给父类加载器,解决了微服务中不同版本依赖的类冲突问题。

(五) SPI 机制(服务提供接口,突破双亲委派的典型应用)

1.核心原理:Java 提供的动态扩展机制,通过接口编程 + 策略模式 + 配置文件实现,允许第三方实现或替换框架的扩展组件。

核心步骤:定义接口→第三方实现接口→在META-INF//下创建接口全限定名的配置文件,写入实现类全限定名→JVM 通过加载实现类。

2.核心特点:由应用类加载器加载,反向委派(子加载器委派给父加载器无法加载的实现类),打破了双亲委派的自顶向下加载规则。

三、JVM运行时数据区

JVM运行时数据区是 JVM 内存管理的核心,分为线程共享区和线程隔离区,线程隔离区随线程创建而创建、销毁而销毁,线程共享区由所有线程共用,只有 JVM 退出时才会释放。

(一) 线程隔离区:程序计数器 + 虚拟机栈 + 本地方法栈

1.程序计数器

核心作用:记录当前线程执行的字节码行号指示器,JVM 通过修改计数器值选取下一条要执行的字节码指令;

关键特性:唯一不会发生 OOM(内存溢出) 的 JVM 内存区域;

作用场景:分支、循环、跳转、异常处理、线程恢复(线程切换后通过计数器恢复执行位置)。

实战案例:多线程环境下,线程 A 被挂起后,程序计数器会保存 A 的执行位置,当 A 再次被调度时java des zeropadding JVM垃圾回收机制-全面详解,直接从该位置继续执行,无需重新执行。

2.虚拟机栈(核心,高频 OOM 区域)

每个方法执行时会创建一个栈帧,栈帧入栈表示方法开始执行,出栈表示方法执行完毕;虚拟机栈的生命周期与线程一致。

栈帧包含 4 个核心组件:

组件

核心作用

局部变量表

存放基本数据类型(int/byte 等)、对象引用、方法参数、局部变量,大小在编译期确定

操作数栈

字节码指令的运算临时存储空间(栈结构,后进先出),用于方法传参、返回结果

动态链接

运行时将常量池的符号引用转为直接引用(区别于解析阶段的静态链接)

方法出口

保存方法返回信息,恢复调用者的执行状态(如方法正常返回 / 异常退出)

实战案例1:递归调用方法时,每次递归都会创建新的栈帧入栈,若递归深度过大,会导致栈帧溢出,抛出

java.lang.(如无终止条件的递归);

实战案例2:设置 JVM 参数-Xss1m(设置虚拟机栈大小为 1M),可调整栈帧的最大数量,解决递归导致的栈溢出问题(需合理设置,过小仍会溢出);

实战案例3:开发中遇到,可通过虚拟机栈的栈帧信息定位异常发生的方法和行号(堆栈跟踪)。

3.本地方法栈

核心作用:支持 修饰的本地方法(由 C/C++ 实现),为本地方法提供栈空间;

与虚拟机栈的区别:虚拟机栈服务于 Java 方法,本地方法栈服务于本地方法;

异常类型:栈深度过大抛出,内存不足抛出OOM。

实战案例:.()是 方法,执行时会在本地方法栈创建栈帧,调用底层 C++ 代码获取系统时间。

(二) 线程共享区:堆 + 方法区

1.堆(Heap,GC 核心区域,最大的 JVM 内存区域)

核心作用:存放所有对象实例和数组,是 Java 对象的主要内存分配区域;

关键特性:被所有线程共享,是垃圾回收(GC)的主要战场,几乎所有的内存回收都针对堆进行;

内存划分:分为新生代、老年代,永久代(JDK7 及以前) 已被移除,替换为元空间(,位于本地内存)。

新生代:存放新创建的对象,分为Eden 区(80%)、From 区(10%)、To 区(10%),采用标记复制算法回收;

老年代:存放新生代中经历多次 GC 仍存活的对象(默认 15 次),采用标记 – 整理 / 标记 – 压缩算法回收。

实战案例1:创建new ()时,对象首先分配在新生代 Eden 区,当 Eden 区满时触发Minor GC(新生代 GC);

实战案例2:设置 JVM 参数-Xmx2g -Xms2g(堆最大和初始内存都为 2G),-XX:=2(新生代:老年代 = 1:2),可调整堆的大小和分区比例,优化 GC 性能;

实战案例3:开发中遇到

java.lang.: Java heap space,原因是堆内存不足(如创建大量大对象、内存泄漏),可通过调大堆内存或排查内存泄漏解决。

2.方法区(永久代 / 元空间)

核心作用:存储已被 JVM 加载的类信息、常量、静态变量、即时编译器编译后的代码缓存;

内存实现:JDK7 及以前为永久代(位于堆中),JDK8 及以后替换为元空间()(位于本地内存,不受 JVM 堆内存限制);

核心子区域:运行时常量池,属于方法区的一部分,存放编译期生成的字面量(如字符串常量)和符号引用,运行时可动态添加常量(如.())。

实战案例1:JDK8 中遇到

java.lang.:java des zeropadding JVM垃圾回收机制-全面详解,原因是元空间内存不足(如动态生成大量类,如 cglib 代理、反射),可设置参数-XX:=2 56m -XX:=512m调整元空间大小;

实战案例2: s = new (“abc”);java des zeropadding,编译期”abc”作为字面量存入运行时常量池,运行时堆中创建一个 对象,s 指向堆中对象。

四、Java对象内存布局

Java 对象在堆中的内存布局固定为 3 部分:对象头() + 实例数据( Data) + 对齐填充(),对齐填充的唯一目的是保证对象总大小为 8 字节的整数倍(JVM 内存管理的高效性要求)。

(一) 对象头(,最复杂的部分,占 8/16 字节)

对象头是 JVM 实现哈希码、GC 分代、锁机制的核心,分为标记字段(Mark Word)、类型指针(Klass ),若为数组对象,还包含数组长度。

标记字段(Mark Word):占 8 字节(64 位 JVM),存储对象运行时状态,采用动态数据结构(根据对象状态复用内存),包含:哈希码、GC 分代年龄、锁状态标志、线程持有的锁、偏向线程 ID、偏向时间戳等;

类型指针(Klass ):占 4/8 字节(可通过-XX:+压缩为 4 字节),指向方法区中该对象的类信息,JVM 通过该指针判断对象的所属类;

数组长度:占 4 字节,仅数组对象拥有,记录数组的元素个数。

实战案例: 锁的升级(无锁→偏向锁→轻量级锁→重量级锁),核心是通过修改对象头的 Mark Word中的锁状态标志实现,无需修改对象的其他数据,提升锁效率。

(二) 实例数据

核心作用:存放对象的所有实例变量(包括继承自父类的实例变量),按变量类型和访问修饰符排序(JVM 优化);

空对象特性:若对象无任何实例变量,实例数据区域无内容,仅保留对象头和对齐填充。

实战案例:定义class User { name; int age; },创建new User()时,实例数据区存放name(对象引用)和age(int 类型)的数值。

(三) 对齐填充

核心规则:保证对象总内存大小为 8 字节的整数倍(64 位 JVM),是 JVM 的强制要求;

填充值:无实际意义,仅为补全内存,由 JVM 自动分配。

示例:一个无实例变量的普通对象(非数组),对象头占 12 字节(Mark Word8 字节 + Klass 字节),需填充 4 字节,总大小为 16 字节(8 的 2 倍)。

五、垃圾回收(GC)核心

GC 是 JVM 的内存回收机制,主要针对堆内存(少量针对方法区 / 元空间),核心是回收无用对象的内存,避免 OOM,分为垃圾判定、回收算法、垃圾回收器三部分。

(一)垃圾判定:如何判断对象是 “无用的”

JVM 采用可达性分析算法判断对象是否存活,核心是通过GC Roots(根对象)作为起点,遍历对象引用链,若对象无任何引用链连接到 GC Roots,则判定为垃圾对象。

1. GC Roots 的常见类型

虚拟机栈(栈帧)中的局部变量表引用的对象;

方法区中静态变量、常量引用的对象;

本地方法栈中 方法引用的对象;

JVM 内部的核心对象(如类加载器、运行时常量池中的对象)。

实战案例:开发中遇到内存泄漏(对象已无用但仍被 GC Roots 引用,无法被 GC 回收),如静态集合持有大量对象引用、关闭流未释放资源、线程池未关闭导致线程引用对象,最终会引发堆内存 OOM。

(二)GC 核心回收算法

JVM 根据对象存活周期采用不同的回收算法,核心是分代算法(将堆分为新生代和老年代),结合标记复制、标记 – 清除、标记 – 整理 / 压缩算法。

回收算法

核心原理

优点

缺点

适用区域

标记复制

将内存分为两块,每次用一块,将存活对象拷贝到另一块,清理原内存

无内存碎片,回收效率高

浪费 50% 内存,不适合大对象

新生代(Eden/)

标记 – 清除

先标记垃圾对象,再统一清除标记的对象

无需移动对象,实现简单

产生大量内存碎片,效率低

极少单独使用

标记 – 整理

标记垃圾对象后,将存活对象向内存一端移动,再清理另一端的垃圾

无内存碎片

移动对象,回收效率低

老年代

标记 – 压缩

标记 – 清除的优化版,将存活对象压缩到内存一端,清理剩余内存

无内存碎片,内存利用率高

移动对象,回收效率低

老年代(主流)

实战案例:新生代 Minor GC 采用标记复制算法,将 Eden 区和 From 区的存活对象拷贝到 To 区,然后清理 Eden 和 From 区,因新生代对象存活率极低(90% 以上为垃圾),标记复制算法的效率优势最大化。

(三)GC 回收时的停顿现象(Stop The World,STW)

核心定义:GC 回收时,用户线程会暂停执行,直到 GC 完成,这是 JVM 的固有特性;

核心原因:避免用户线程在 GC 过程中修改对象引用链,导致 GC 结果不准确;

调优重点:减少 STW 的时间和频率(如使用低停顿的垃圾回收器 G1/ZGC)。

实战案例:老年代触发Full GC时,STW 时间会显著变长(如几百毫秒甚至几秒),导致应用响应超时java des zeropadding,这是生产环境中需要重点避免的问题。

(三)主流垃圾回收器

JVM 提供多种垃圾回收器,分为新生代回收器(、、)、老年代回收器(、、CMS)、整堆回收器(G1、ZGC、),核心推荐CMS和G1(生产环境主流)。

1. CMS 收集器( Mark Sweep,并发标记清除)

CMS 是以最短 STW 时间为目标的老年代回收器,基于标记 – 清除算法实现,核心是并发收集(GC 线程与用户线程同时运行),减少 STW 时间。

(1)回收流程(4 个阶段,2 个阶段 STW)

初始标记:标记 GC Roots 直接关联的对象,STW,速度极快;

并发标记:从初始标记的对象出发,遍历整个引用链,无 STW(GC 线程与用户线程同时运行);

重新标记:修正并发标记期间因用户线程运行导致的标记变动,STW,时间比初始标记长,但远短于并发标记;

并发清除:清理标记的垃圾对象,无 STW(GC 线程与用户线程同时运行)。

(2)核心优点

并发收集:耗时最长的并发标记和并发清除阶段无 STW;

低停顿:STW 时间极短,适合对响应时间要求高的应用(如 Web 服务、接口服务)。

(3)核心缺点(生产环境需重点关注)

产生内存碎片:基于标记 – 清除算法,清理后会产生大量内存碎片,大对象无法分配连续内存时会触发 Full GC;

Mode :GC 过程中,内存无法满足用户线程的分配需求,会触发后备方案( 收集器),导致 STW 时间急剧变长;

无法处理浮动垃圾:并发清除阶段,用户线程新产生的垃圾(浮动垃圾)无法被本次 GC 回收,需等待下一次 GC;

对 CPU 资源敏感:并发收集会占用 CPU 资源,导致应用吞吐量下降(CPU 核心数少的服务器不适合)。

实战案例:电商平台的核心交易接口,对响应时间要求极高(毫秒级),可使用 CMS 收集器,通过-XX:+开启,搭配-XX:+(新生代使用 ,与 CMS 配合)。

2.G1 收集器(-First,垃圾优先)

G1 是 JDK7 引入、JDK9 默认的整堆回收器,可同时回收新生代和老年代,基于标记 – 整理算法+区域化分代实现,是 CMS 的替代方案,兼顾响应时间和吞吐量。

(1)核心特性

区域化堆:将堆划分为多个大小相等的(区域),每个 可动态标记为 Eden、、Old,替代传统的新生代 / 老年代分区;

垃圾优先:优先回收垃圾比例最高的 ,最大化回收效率,减少 STW 时间;

可预测的 STW:支持设置最大 STW 时间(如-XX:=200),G1 会根据目标时间调整回收策略;

无内存碎片:基于标记 – 整理算法,回收后会整理内存,无碎片问题。

(2)核心优点

兼顾响应时间和吞吐量,适合大内存、高并发的生产环境(如堆内存 8G 以上的服务器);

无内存碎片,避免大对象分配导致的 Full GC;

可预测 STW 时间,满足应用的响应时间要求;

整堆回收,无需搭配其他回收器。

(3)核心缺点

对内存分区的管理复杂度高;

小内存堆(如 4G 以下)的性能不如 CMS/。

实战案例:微服务架构的核心服务,堆内存设置为 16G,对响应时间(

GC 收集器开启参数总结

六、JVM 实战调优核心思路(附通用参数)

(一)调优核心目标

1.减少Full GC的频率和STW时间

2.控制Minor GC的频率,避免频繁Minor GC导致应用抖动

3.避免OOM(堆、元空间、虚拟机栈)

4.兼顾应用的响应时间和吞吐量

(二)通用生产环境 JVM 参数(以 G1 收集器为例,堆内存 16G)

# 堆内存(初始=最大,避免内存扩容导致的GC)
-Xms16g -Xmx16g
# 开启G1收集器
-XX:+UseG1GC
# 设置最大STW时间200ms
-XX:MaxGCPauseMillis=200
# 新生代占比(默认5%,可调整为20%-30%)
-XX:NewRatio=4
# 元空间大小
-XX:MetaspaceSize=512m -XX:MaxMetaspaceSize=1g
# 虚拟机栈大小
-Xss1m
# 打印GC日志(生产环境必备,排查问题)
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/usr/local/app/gc.log
# 开启堆内存溢出快照(OOM时生成hprof文件,用于分析)
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/local/app/heapdump.hprof

(三)GC 日志分析实战

生产环境中开启 GC 日志后,可通过、(在线工具)分析日志,重点关注:

1.Minor GC 的频率、STW 时间;

2.Full GC 的触发原因(如内存碎片、元空间不足、大对象分配);

3.堆内存的使用趋势(是否存在内存泄漏)。

实战案例:通过 GC 日志发现 Full GC 频繁触发,原因是老年代内存碎片过多(CMS 收集器),解决方案是替换为 G1 收集器(标记 – 整理算法,无碎片),或开启 CMS 的内存整理参数-XX:+

(Full GC 时整理内存)。

(四)内存泄漏排查实战

1.开启堆溢出快照参数java des zeropadding,OOM 时生成hprof文件;

2.使用MAT( Tool) 分析 hprof 文件,找到内存占用最大的对象和GC Roots 引用链;

3.定位代码中持有对象引用的位置(如静态集合、未关闭的资源、线程池);

4.优化代码,释放无用对象的引用。

实战案例:MAT 分析发现占用堆内存 80%,原因是静态持有大量用户对象引用,且未做过期清理,解决方案是替换为过期缓存(如 Guava Cache、Redis),设置过期时间自动清理。

公告:
1. 本站所有资源来源于用户上传和网络,如有侵权请联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系站长处理!
6. 本站不售卖代码,资源标价只是站长收集整理的辛苦费!如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。
7. 站长QQ号码 2205675299

资源库 - 资源分享下载网 » java des zeropadding JVM垃圾回收机制-全面详解

常见问题FAQ

关于资源售价和售后服务的说明?
本站所有资源的标价均为本站收集资源的辛苦费,不代表资源本身的价值。软件是高智慧高价值的商品,不可能是白菜价。本站资源标价只是赞助费用,收取的赞助费仅用来维持本站的日常运营!毕竟收集整理资料需要投入云计算资源和站长大量的精力。
代码有没有售后服务和技术支持?
由于代码的运行具有不可预见性,本站不保证代码完整可运行,不提供技术支持和售后服务。 本站原创代码都是站长自己开发的,可以有偿提供技术支持服务。 网站里标明【亲测】的代码都是站长亲测过的,其他的代码由于精力有限,没有一一测试,不能保证代码就一定能够使用,更没有技术支持服务,下载前请自行斟酌。
有没有搭建服务?
由于搭建服务比较费时费力,所以本站除了原创代码外均不提供搭建服务。本站分享代码纯属兴趣爱好,不以盈利为目的,请勿咨询有没有搭建服务,谢谢理解。
链接地址失效了怎么办?
请带上资源链接地址联系客服,工作时间内我们看到后将第一时间回复。
关于解压密码
本站资源一般都没有加密,如果发现需要解压密码的,那么就输入 hao.35dc.com 试试。

发表评论

资源库,由老程序员细心甄别、精心筛选,只为提供优质的源码资源

关于我们 联系我们