在 Java 开发中,自动内存管理是 JVM 的核心能力之一,而内存分配与回收的策略直接影响程序的性能和稳定性。本文将详细解析 JVM 的内存分配机制、对象回收规则以及背后的设计思想,帮助开发者更好地理解 JVM 的 "自动化" 内存管理逻辑。

一、内存分配的核心原则

        JVM 的内存分配遵循 "分代思想",即根据对象的存活周期将堆内存划分为新生代和老年代,并针对不同区域采用不同的分配策略。

1. 对象优先在 Eden 区分配

        大多数情况下,新创建的对象会首先被分配到新生代的 Eden 区。当 Eden 区没有足够空间时,JVM 会触发一次 Minor GC(新生代垃圾回收)。

public class GCTest {public static void main(String[] args) {// 分配30MB对象(大于Eden区默认大小)byte[] allocation1 = new byte[30900*1024];}
}

        通过-XX:+PrintGCDetails参数运行后可以观察到:当 Eden 区无法容纳大对象时,会触发 Minor GC,若 Survivor 区仍无法容纳,则会通过分配担保机制将对象直接晋升到老年代。

2. 大对象直接进入老年代

        大对象(需要大量连续内存的对象,如长字符串、数组)会被直接分配到老年代,这是为了避免大对象在新生代频繁复制导致的性能损耗。

        不同垃圾回收器对 "大对象" 的判定标准不同:

  • G1 收集器:根据-XX:G1HeapRegionSize设置的区域大小和-XX:G1MixedGCLiveThresholdPercent阈值判定
  • Parallel Scavenge 收集器:由虚拟机根据堆内存情况动态决定,无固定阈值

3. 长期存活的对象进入老年代

        JVM 为每个对象维护一个 "年龄计数器",用于判断对象是否应晋升到老年代:

  • 对象在 Eden 区出生,经过第一次 Minor GC 后存活并被移至 Survivor 区,年龄设为 1
  • 每在 Survivor 区熬过一次 Minor GC,年龄增加 1 岁
  • 当年龄达到阈值(默认 15 岁,可通过-XX:MaxTenuringThreshold设置)时,晋升到老年代

动态年龄调整
虚拟机并非严格按固定年龄阈值晋升对象。当 Survivor 区中相同年龄的对象总大小超过 Survivor 空间的 50%(可通过-XX:TargetSurvivorRatio调整)时,所有年龄大于或等于该年龄的对象会直接晋升到老年代。

注意不同收集器的默认阈值不同,CMS 收集器默认阈值为 6,Parallel 收集器默认 15。

二、内存回收的触发机制

        JVM 的垃圾回收(GC)按回收范围可分为 Partial GC(部分回收)和 Full GC(整堆回收),其中 Partial GC 又可细分为:

  • Young GC:仅回收新生代
  • Old GC:仅回收老年代(仅 CMS 支持)
  • Mixed GC:回收新生代 + 部分老年代(仅 G1 支持)

1. Young GC 触发条件

        当新生代的 Eden 区分配满时,触发 Young GC。此时会有部分存活对象晋升到老年代,因此 Young GC 后老年代占用量可能上升。

2. Full GC 触发条件

        Full GC 会回收整个堆空间,触发成本较高,常见触发场景包括:

  • 老年代空间不足
  • 方法区(元空间)内存不足
  • 调用System.gc()(建议避免)
  • 空间分配担保失败

3. 空间分配担保机制

        为确保 Minor GC 的安全性,JVM 会在 Minor GC 前进行空间分配担保检查:

  • JDK 6 Update 24 前:检查老年代最大可用连续空间是否大于新生代对象总大小或历次晋升平均大小,否则触发 Full GC
  • JDK 6 Update 24 后:只要老年代连续空间大于新生代总大小历次晋升平均大小,就进行 Minor GC,否则触发 Full GC

三、对象存活的判断方法

        垃圾回收的前提是准确判断对象是否存活,JVM 主要采用两种判断算法:

1. 引用计数法

  • 原理:为每个对象设置引用计数器,引用增加时 + 1,引用失效时 - 1,计数器为 0 则标记为可回收
  • 缺陷:无法解决对象循环引用问题,因此主流 JVM 未采用

2. 可达性分析算法

  • 原理:以 "GC Roots" 为起点,遍历引用链,不可达的对象被标记为可回收
  • GC Roots 包括
    • 虚拟机栈中引用的对象
    • 本地方法栈中引用的对象
    • 方法区中类静态属性引用的对象
    • 方法区中常量引用的对象
    • 同步锁持有的对象

对象死亡的两次标记

  1. 第一次标记:可达性分析后不可达的对象
  2. 第二次标记:检查对象是否需要执行finalize()方法,若无需执行或已执行,则判定为死亡

注意:finalize()方法已被 JDK 9 标记为过时,建议避免使用。

四、引用类型与回收策略

        JDK 1.2 后将引用分为四类,强度依次减弱,影响对象的回收时机:

引用类型特点应用场景
强引用Object obj = new Object()普通对象引用,内存不足时不会回收一般对象引用
软引用SoftReference内存不足时会被回收内存敏感的缓存
弱引用WeakReference无论内存是否充足,GC 时都会回收临时缓存
虚引用PhantomReference不影响对象生命周期,仅用于跟踪回收管理直接内存

软引用和弱引用可配合ReferenceQueue使用,当引用对象被回收时,引用实例会被加入队列,便于后续处理。

五、实战建议与最佳实践

  1. 避免创建大对象:大对象直接进入老年代,可能频繁触发 Full GC
  2. 合理设置新生代大小:新生代过小会导致 Young GC 频繁,过大则会延长 GC 时间
  3. 选择合适的垃圾收集器
    • 追求吞吐量:选择 Parallel Scavenge + Parallel Old
    • 追求低延迟:选择 G1 或 ZGC
  4. 监控 GC 性能:通过-XX:+PrintGCDetails-XX:+PrintGCLogs等参数分析 GC 日志
  5. 慎用System.gc():该方法仅为建议,可能触发 Full GC 影响性能

六、总结

        JVM 的内存分配与回收机制是自动内存管理的核心,其设计遵循 "分代收集" 思想,通过不同区域的针对性策略实现高效的内存管理。理解这些原则有助于开发者写出更优的代码,避免常见的内存问题(如 OOM),并在必要时进行有效的性能调优。

        掌握内存分配规律、GC 触发机制和引用类型特性,是深入理解 JVM 的重要一步,也是应对高并发、高性能场景的必备知识。

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

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

相关文章

Qt获取hid设备信息

Qt 中通过 HID&#xff08;Human Interface Device&#xff09;接口获取指定的 USB 设备&#xff0c;并读取其数据。资源文件中包含了 hidapi.h、hidapi.dll 和 hidapi.lib。通过这些文件&#xff0c;您可以在 Qt 项目中实现对 USB 设备的 HID 接口调用。#include <QObject&…

Anaconda Jupyter 使用注意事项

Anaconda Jupyter 使用注意事项 1.将cell转换为markdown。 First, select the cell you want to convertPress Esc to enter command mode (the cell border should turn blue)Press M to convert the cell to Markdown在编辑模式下按下ESC键&#xff0c;使单元块&#xff08;c…

[硬件电路-20]:模拟信号处理运算与数字信号处理运算的相同点与不同点

模拟信号处理运算与数字信号处理运算是信号处理领域的两大核心方法&#xff0c;二者在信号形式、处理机制、性能特点和应用场景上存在显著差异&#xff0c;但也共享一些基础目标与理论支撑。以下从多个维度进行系统对比分析&#xff1a;一、相同点1. 核心目标一致信号变换与分析…

Redis 高频面试题

1. 缓存穿透 1.1 描述 用户想要查询某个数据,在 Redis 中查询不到,即没有缓存命中,这时就会直接访问数据库进行查询。当请求量超出数据库最大承载量时,就会导致数据库崩溃。这种情况一般发生在非正常 URL 访问,目的不是为了获取数据,而是进行恶意攻击。 1.2 现象 1、应…

OWASP Top 10 攻击场景实战

OWASP (开放式Web应用程序安全项目) Top 10 榜单是全球公认的、针对Web应用最关键安全风险的权威指南。它不是一份详尽无遗的清单&#xff0c;而是一份凝聚了安全专家共识的“高危预警”。本文将不止于罗列这些风险&#xff0c;而是深入每个风险的核心&#xff0c;通过生动的比…

Three.js 实战:使用 PBR 贴图打造真实地面材质

在 Three.js 中&#xff0c;我们可以通过 MeshStandardMaterial 材质配合多张贴图来实现真实的地面效果。这种方式模拟了物理世界中光照与表面材质的复杂交互&#xff0c;常用于构建高质量场景&#xff0c;如数字孪生、建筑可视化、游戏等。 本文将以一个完整示例为基础&#x…

Java基础的总结问题(第一篇)

JDK和JRE的区别&#xff1f;JRE是Java运行环境&#xff08;Java Runtime Environment&#xff09;&#xff0c;包含了JVM和Java核心类库JDK是Java开发工具包&#xff08;Java Developers Kit&#xff09;,包含了JRE和Java常见的开发工具与equals的区别&#xff1f;可以用来比较…

[智能算法]MOEA/D算法的Python实现

一、初始化不同于NSGA-II&#xff0c;MOEA/D在进行迭代之前需要先进行初始化&#xff0c;初始化的主要内容是计算个体向量权重之间的欧氏距离&#xff0c;并得出其邻域集合。# 计算T个邻居 def cpt_W_Bi_T(moead):# 设置的邻居个数错误(自己不能是自己的邻居)if moead.T_size &…

Java设计模式之-组合模式

什么是组合模式&#xff1f; 组合模式允许你将对象组合成树形结构来表示"部分-整体"的层次结构。它让客户端能够以统一的方式处理单个对象和对象组合。 简单来说&#xff0c;就像公司的组织结构&#xff1a; 公司有部门部门有小组小组有员工但无论是对公司、部门还是…

2021-10-29 C++与反转数的和

缘由输入一个三位数 与它倒过来的数相加&#xff0c;输出和-编程语言-CSDN问答 直接写 int n0,nn0,nnn0; cin>>n;nnn; while(nn)nnn*10,nnnnn%10,nn/10; cout<<nnnn<<endl; 缘由https://ask.csdn.net/questions/7552128 int 反转数(int n) { int nn 0…

论安全架构设计(威胁与措施)

安全架构威胁与措施摘要2021年4月&#xff0c;我有幸参与了某保险公司的“优车险”项目的建设开发工作&#xff0c;该系统以车险报价、车险投保和报案理赔为核心功能&#xff0c;同时实现了年检代办、道路救援、一键挪车等增值服务功能。在本项目中&#xff0c;我被安排担任架构…

022_提示缓存与性能优化

提示缓存与性能优化 目录 缓存技术概述缓存工作原理实现方法详解成本优化策略性能优化实践高级应用场景最佳实践指南 缓存技术概述 什么是提示缓存 提示缓存是Claude API的一项优化功能&#xff0c;允许缓存提示的特定部分以便重复使用&#xff0c;从而显著减少处理时间和…

【AI交叉】地理:人工智能如何推动地理科学的智能转型?

随着人工智能&#xff08;AI&#xff09;技术的快速发展&#xff0c;越来越多的传统学科开始与之融合&#xff0c;催生出一系列跨学科的新研究方向和应用场景。地理科学作为研究地球表层自然与人文现象的综合性学科&#xff0c;也在这一浪潮中迎来转型契机。 AI与地理学的交叉正…

iOS高级开发工程师面试——关于网络

iOS高级开发工程师面试——关于网络 一、谈谈对 HTTP、HTTPS 的理解1. HTTP协议:2. HTTPS 协议二、TCP、UDP 和 SocketTCPUDPTCP 和 UDP 的区别?Socket一、谈谈对 HTTP、HTTPS 的理解 1. HTTP协议: 超文本传输协议,他是基于TCP应用层协议。 是无连接 无状态 的,需要通过…

跟着Nature正刊学作图:回归曲线+散点图

&#x1f4cb;文章目录复现目标图片绘图前期准备绘制左侧回归线图绘制右侧散点图组合拼图 (关键步骤&#xff01;)跟着「Nature」正刊学作图&#xff0c;今天挑战复现Nature文章中的一张组合图–左边为 回归曲线、右边为 散点图。这种组合图在展示相关性和分组效应时非常清晰有…

LVS集群调度器

目录 集群和分布式 LVS运行原理 LVS概念 LVS的集群类型 实验配置 安装LVS ipvsadm命令参数 1.管理集群服务中的增删改 2.管理集群服务中的RS增删改 3.lvs调度策略的备份与恢复 4.lvs调度策略的开机启动 LVS-NAT模式 LVS-DR模式 集群和分布式 集群&#xff08;Clu…

【React Natve】NetworkError 和 TouchableOpacity 组件

NetworkError公共组件 import SimpleLineIcons from "expo/vector-icons/SimpleLineIcons"; import { StyleSheet, Text, View } from "react-native";export default function NetworkError() {return (<View style{styles.container}><SimpleL…

Linux 驱动中 Timer / Tasklet / Workqueue 的作用与对比

Linux 驱动中 Timer / Tasklet / Workqueue 的作用与对比 &#x1f9e9; 1. 使用场景概览&#xff08;对比表&#xff09;机制执行上下文是否可睡眠使用场景常用接口Timer中断上下文❌ 不可睡眠延迟执行&#xff08;如防抖、超时处理&#xff09;add_timer() 等Tasklet软中断上…

JavaScript中关于proxy的作用以及和Object.defineProperty的区别

之前写了一篇介绍 Object.defineProperty的&#xff0c;提到proxy&#xff0c;二者有一些共性&#xff0c;也都是前端框架Vue的核心机制&#xff0c;所以再写一篇介绍一下proxy的基础原理和使用。 在 JavaScript 中&#xff0c;Proxy 是 ES6 引入的一个元编程特性&#xff0c;用…

HTTP性能优化实战技术

HTTP性能优化实战技术文章大纲 理解HTTP性能优化的核心指标 关键指标&#xff1a;延迟、吞吐量、TTFB&#xff08;Time To First Byte&#xff09;、页面加载时间影响性能的因素&#xff1a;网络延迟、服务器响应时间、资源大小、协议效率 减少HTTP请求数量 合并资源文件&#…