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
- 关于资源售价和售后服务的说明?
- 代码有没有售后服务和技术支持?
- 有没有搭建服务?
- 链接地址失效了怎么办?
- 关于解压密码

