当前位置: 首页 > article >正文

Java对象内存模型、如何判定对象已死亡?

一、Java对象内存模型

Java对象在内存中由三部分组成:

image.png含类元数据指针(指向方法区的Class对象)和Mark Word(存储对象哈希码、锁状态、GC分代年龄等信息)。

若为数组对象,还包含数组长度数据。

1,内存模型 -- Mark Word

Mark Word是Java对象头(Object Header)的核心部分,用于存储对象运行时元数据,其结构随锁状态和GC阶段动态变化。以下是32/64位系统下的典型布局:

1),无锁状态(Normal)

位域

内容

25/29bit

对象哈希码(hashCode)

4bit

对象分代年龄(GC年龄,最大15)

1bit

偏向锁标识(0表示未启用)

2bit

锁标志位(01)

2),偏向锁(Biased)

位域

内容

23/54bit

持有偏向锁的线程ID

2bit

Epoch(用于批量重偏向)

1bit

偏向锁标识(1表示启用)

2bit

锁标志位(01)

3),轻量级锁(Lightweight Lock)

位域

内容

30/62bit

指向栈中锁记录的指针

2bit

锁标志位(00)

4),重量级锁(Heavyweight Lock)

位域

内容

30/62bit

指向监视器(Monitor)的指针

2bit

锁标志位(10)

5),GC标记状态

位域

内容

30/62bit

空(未使用)

2bit

锁标志位(11)

关键设计原理

1)空间复用:通过锁标志位(最后2bit)区分不同状态,同一存储区域在不同阶段复用2。

2)锁升级优化:从无锁→偏向锁→轻量级锁→重量级锁逐步升级,减少同步开销35。

3)GC协作:分代年龄存储于Mark Word,配合可达性分析实现分代回收。

2,内存模型 -- Class Pointer

Class Pointer是Java对象头中的关键字段,用于指向方法区中该对象的类元数据(Class对象),其设计直接影响对象访问效率和内存占用。


    核心作用‌
      • 类元数据关联‌:存储对象所属类的类型信息(如方法表、字段表等)。
      • 方法调用支持‌:通过类指针定位虚方法表(vtable)实现动态绑定。

      • GC与反射基础:为垃圾回收和反射操作提供类结构信息。

    内存布局设计:

场景

指针大小

说明

64位系统(默认)

4字节(压缩)

启用-XX:+UseCompressedClassPointers

64位系统(关闭压缩)

8字节

需显式配置-XX:-UseCompressedClassPointers

32位系统

4字节

无压缩选项,固定大小

   访问方式对比:

    1)句柄访问

使用句柄访问,会在堆中开辟一块内存空间作为句柄池,句柄中储存了对象实例数据(属性值结构体) 的内存地址,访问类型数据的内存地址(类信息,方法类型信息),对象实例数据一般也在heap中开辟,类型数据一般储存在方法区中。

优点

存储稳定的句柄地址,在对象被移动(gc) 时只会改变句柄中的实例数据指针,引用稳定。

缺点

增加了一次指针定位的时间开销。

    2)直接指针访问:

直接指针访问方式指直接储存对象在heap中的内存地址,但对应的类型数据访问地址需要 在实例中存储。

优点

节省了一次指针定位的开销

缺点

对象移动需更新所有引用

3,内存模型 -- 指针压缩

     1),压缩的目的:

      • 为了保证CPU普通对象指针(oop)缓存

      • 为了减少GC的发生,因为指针不压缩是8字节,这样在64位操作系统的堆上其他资源空间就少了。

    2),压缩条件‌:

      • 堆内存 ≤ 32GB(超过时压缩失效)。

      • 默认开启,通过-XX:+UseCompressedOops同时压缩对象引用指针。


内存大于32G后,指针压缩失效是因为:4G*8 = 32G。32位系统的CPU 最大支持2^32 = 4G。如果是64位系统,最大支持 2^64, 但是对其填充是按照8字节进行填充,指针压缩可以理解为在32位系统在64位上面使用,因为32位系统的CPU寻址空间最大支持4G,对其填充*8 = 32G,这就是内存>32G指针压缩失效的原因。

    关闭指针压缩:-XX:-UseCompressedOops

3,内存模型 -- 对齐填充

对齐填充的目的是,保证对象起始地址为8字节整数倍,提升内存访问效率。

内存对齐规则

  • 32位系统默认4字节对齐,64位系统默认8字节对齐。

  • 开启指针压缩(默认开启)时,对象头固定12字节,元数据指针由8字节压缩至4字节。

  • 堆内存超过32GB时指针压缩失效,导致对象头膨胀。


二,JVM内存模型

  • 内存模型分为私有区:进程计数器,虚拟机栈,本地方法栈。集线程共享区:堆和方法区。Java堆,是Java虚拟机管理的最大的一块内存,也是GC的主战场,里面存放的是几乎所有的对象实例和数组数据。

堆里面分为两个区域:新生代 和 老年代,新生代放新建的对象,当经过一定GC次数之后还存活的对象会放入老生代。新生代还有 3个区域:一个Eden +两个Survivor(S0/S1)。

垃圾回收的时候会将Eden中存活的对象放到一个未使用的Survivor中,并把当前的Endn和正在使用的 Survivor清除掉。

对象创建的过程是在堆上分配着实例对象,那么对象实例的具体结构如下:

对象的创建规则

    • 对象优先分配在Eden区,如果Eden区没有足够的空间时,虚拟机执行一次Minor GC。

    • 大对象直接进入老年代。这样做的目的是避免在Eden区和两个Survivor区之间发生大量的内存拷贝(新生代采用复制算法收集内存)。

    • 长期存活的对象进入老年代。虚拟机为每个对象定义了一个年龄计数器,如果对象经过了1次Minor GC那么对象会进入Survivor区,之后每经过一次Minor GC那么对象的年龄加1,直到达到阀值对象进入老年区。

    • 动态判断对象的年龄。如果Survivor区中相同年龄的所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象可以直接进入老年代。

    • 空间分配担保。每次进行Minor GC时,JVM会计算Survivor区移至老年区的对象的平均大小,如果这个值大于老年区的剩余值大小则进行一次Full GC,如果小于检查HandlePromotionFailure设置,如果true则只进行Monitor GC,如果false则进行Full GC。

三、对象死亡判定机制

1. 判定算法

1) 可达性分析(主流实现)

    从GC Roots出发遍历引用链,未被链访问的对象标记为可回收

GC Roots包括‌:

      • 线程栈中的局部变量

      • 方法区中类静态变量

      • JNI引用的Native对象

      • 系统类加载器加载的Class对象

(2) 引用计数法(存在缺陷)

    • 为对象维护引用计数器,引用增加时计数+1,失效时-1

    • 无法解决循环引用问题(如对象A与B互相引用但无外部引用)


2. 判定流程

(1) 第一次标记
对象被判定不可达后,JVM标记为“待回收”并检查是否需要执行finalize()方法:

    • 若对象未覆盖finalize()或已执行过,则直接回收

    • 若有必要执行,对象进入F-Queue队列等待Finalizer线程触发

(2) 第二次标记

    • finalize()执行期间若对象重新建立与GC Roots的引用链(如将this赋值给全局变量),则移出回收队列
    • 未逃脱的对象最终被回收

3. 引用类型对回收的影响

引用类型

回收条件

典型应用场景

强引用

引用链断开即回收

普通对象赋值

软引用

内存不足时强制回收

缓存实现(如图片缓存)

弱引用

下次GC必定回收

WeakHashMap等容器

虚引用

仅用于跟踪对象回收状态

NIO DirectBuffer管理

注意‌:软/弱引用需配合ReferenceQueue使用,虚引用不能单独访问对象。


四、内存泄漏典型案例

场景示例:

javaCopy Code// 循环引用导致无法回收(即使外部引用置空)  
classNode {  Object data;  Node next;  
}  
Nodea=newNode();  
Nodeb=newNode();  
a.next = b;  
b.next = a;  
a = b = null;   // 对象仍互相引用,但已不可达:ml-citation{ref="4" data="citationList"}

排查工具‌:

    • jmap -histo 查看对象数量异常增长
    • MAT分析堆转储文件定位引用链

通过内存模型与可达性分析机制的结合,可精准把控对象生命周期并优化内存管理策略。

往期文章:

 Spring Boot 常用的注解整理全集

  Spring Boot 配置明文密码加密,防泄漏

 Spring AI基于DeepSeek实战,使AI开发更高效

 【JAVA多线程】JDK中的各种锁,看这一篇就够了

 现在的背调,都可以这么玩了?

图片

相关文章:

Java对象内存模型、如何判定对象已死亡?

一、Java对象内存模型 Java对象在内存中由三部分组成: 含类元数据指针(指向方法区的Class对象)和Mark Word(存储对象哈希码、锁状态、GC分代年龄等信息)。 若为数组对象,还包含数组长度数据。 1&#xff0c…...

spark任务的提交流程

目录 spark任务的提交流程1. 资源申请与初始化2. 任务划分与调度3. 任务执行4. 资源释放与结果处理附:关键组件协作示意图扩展说明SparkContext介绍 spark任务的提交流程 用户创建一个 Spark Context;Spark Context 去找 Cluster Manager 申请资源同时说明需要多少 CPU 和内…...

ELK简介和docker版安装

使用场景 主要还是给开发人员“打捞日志”用的。 ELK 是由三个开源工具组成的套件(Elasticsearch、Logstash 和 Kibana),主要用于日志的收集、分析和可视化。以下是 ELK 常见的使用场景: 日志集中化管理 收集来自多个服务器或服…...

利用条件编译实现RTT可控的调试输出

在嵌入式开发中,调试信息的输出通常对定位问题至关重要。然而,为了保证代码在正式发布时的性能和体积,调试信息往往需要在不修改主逻辑代码的前提下禁用。 代码一览 // debug.h #pragma once// #define DEBUG#ifdef DEBUG#include "SEG…...

【软件设计师】计算机网络考点整理

以下是软件设计师考试中 ​​计算机网络​​ 的核心考点总结,帮助您高效备考: ​​一、网络体系结构与协议​​ ​​OSI七层模型 & TCP/IP四层模型​​ 各层功能(物理层-数据链路层-网络层-传输层-会话层-表示层-应用层)对应协…...

智慧化工园区安全风险管控平台建设方案(Word)

1 项目概况 1.1 园区概况 1.1.1 XX化工园区简况 1.1.2 企业现状 1.1.3 园区发展方向 1.1.4 园区信息化现状 1.2 项目建设背景 1.2.1 政策背景 1.3 项目建设需求分析 1.3.1 政策需求分析 1.3.2 安全生产监管需求分析 1.3.3 应急协同管理需求分析 1.3.4 工业互联网安…...

【uniapp】 iosApp开发xcode原生配置项(iOS平台Capabilities配置)

如果你需要配置诸如:Access Wi-Fi Information 简单地说就是这个地址 ios平台capabilities配置 本来这种配置就是在Xcode的平台中选中即可,他们的信息会存储在XCode工程的.entitlements和Info.plist文件。 按照uniapp文档说的, HBuilderX4.…...

MYSQL优化(1)

MYSQL调优强调的是如何提高MYSQL的整体性能,是一套整体方案。根据木桶原理,MYSQL的最终性能取决于系统中性能表现最差的组件。可以这样理解,即使MYSL拥有充足的内存资源,CPU资源,如果外存IO性能低下,那么系…...

C++可变参数宏定义语法笔记

1. 基础语法 定义格式: #define MACRO_NAME(fixed_args, ...) macro_body#define LOG(fmt, ...) printf(fmt, __VA_ARGS__) LOG("Value: %d, Name: %s", 42, "Alice"); // 展开为 printf("Value: %d, Name: %s", 42, "Alice&q…...

基于BERT预训练模型(bert_base_chinese)训练中文文本分类任务(AI老师协助编程)

新建项目 创建一个新的虚拟环境 创建新的虚拟环境(大多数时候都需要指定python的版本号才能顺利创建): conda create -n bert_classification python3.9激活虚拟环境: conda activate myenvPS:虚拟环境可以避免权限问题,并隔离…...

Windows逆向工程提升之IMAGE_EXPORT_DIRECTORY

公开视频 -> 链接点击跳转公开课程博客首页 -> ​​​链接点击跳转博客主页 目录 什么是 IMAGE_EXPORT_DIRECTORY? PE 文件与 Export Table 的关系 PE 文件的整体视角 Export Table 在 PE 中的定位 IMAGE_EXPORT_DIRECTORY 结构 数据结构定义 字段详解…...

python与flask框架

一、理论 Flask是一个轻量级的web框架,灵活易用。提供构建web应用所需的核心工具。 Flask依赖python的两个库 Werkzeug:flask的底层库,提供了WSGI接口、HTTP请求和响应处理、路由等核心功能。 Jinja2:模板引擎&#xff0…...

【普及+/提高】洛谷P2613 【模板】有理数取余——快读+快速幂

题目来源 P2613 【模板】有理数取余 - 洛谷 题目描述 给出一个有理数 cba​,求 cmod19260817 的值。 这个值被定义为 bx≡a(mod19260817) 的解。 输入格式 一共两行。 第一行,一个整数 a。 第二行,一个整数 b。 输出格式 一个整数&a…...

从数据到智能:openGauss+openEuler Intelligence的RAG架构实战

随着人工智能和大规模语言模型技术的崛起,传统的搜索引擎由于其只能提供简单的关键字匹配结果,已经越来越无法满足用户对于复杂、多样化和上下文相关的知识检索需求。与此相对,RAG(Retrieval-Augmented Generation)技术…...

【Linux】初见,基础指令

前言 本文将讲解Linux中最基础的东西-----指令,带大家了解一下Linux中有哪些基础指令,分别有什么作用。 本文中的指令和选项并不全,只介绍较为常用的 pwd指令 语法:pwd 功能:显示当前所在位置(路径&#xf…...

什么是实时流数据?核心概念与应用场景解析

在当今数字经济时代,实时流数据正成为企业核心竞争力。金融机构需要实时风控系统在欺诈交易发生的瞬间进行拦截;电商平台需要根据用户实时行为提供个性化推荐;工业物联网需要监控设备状态预防故障。这些场景都要求系统能够“即时感知、即时分…...

工业RTOS生态重构:从PLC到“端 - 边 - 云”协同调度

一、引言 在当今数字化浪潮席卷全球的背景下,工业领域正经历着深刻变革。工业自动化作为制造业发展的基石,其技术架构的演进直接关系到生产效率、产品质量以及企业的市场竞争力。传统的PLC(可编程逻辑控制器)架构虽然在工业控制领…...

数据结构与算法学习笔记(Acwing 提高课)----动态规划·状态机模型

数据结构与算法学习笔记----动态规划状态机模型 author: 明月清了个风 first publish time: 2025.5.20 ps⭐️背包终于结束了,状态机模型题目不多。状态机其实是一种另类的状态表示方法,将某一个点扩展为一个状态进行保存并在多个状态之间转移&#xf…...

基于开源链动2+1模式AI智能名片S2B2C商城小程序的社群构建与新型消费迎合策略研究

摘要:随着个性化与小众化消费的崛起,消费者消费心理和模式发生巨大变化,社群构建对商家迎合新型消费特点、融入市场经济发展至关重要。开源链动21模式AI智能名片S2B2C商城小程序的出现,为社群构建提供了创新工具。本文探讨该小程序…...

高性能RPC框架--Dubbo(五)

Filter: filter过滤器动态拦截请求(request)或响应(response)以转换或使用请求或响应中包含的信息。同时对于filter过滤器不仅适合消费端而且还适合服务提供端。我们可以自定义在什么情况下去使用filter过滤器 Activa…...

计算机视觉与深度学习 | PSO-MVMD粒子群算法优化多元变分模态分解(Matlab完整代码和数据)

以下是一个基于PSO优化多元变分模态分解(MVMD)的Matlab示例代码框架,包含模拟数据生成和分解结果可视化。用户可根据实际需求调整参数。 %% 主程序:PSO优化MVMD参数 clc; clear; close all;% 生成模拟多变量信号 fs = 1000; % 采样频率 t = 0:1/fs:...

搭建自己的语音对话系统:开源 S2S 流水线深度解析与实战

网罗开发 (小红书、快手、视频号同名) 大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等…...

feign调用指定服务ip端口

1 背景 在springcloud开发时候,同时修改了feign接口和调用方的代码,希望直接在某个环境调用修改的代码,而线上的服务又不希望被下线因为需要继续为其他访问页面的用户提供功能后端服务,有时候甚者包含你正在修改的功能。 2 修改…...

【深尚想!爱普特APT32F1023H8S6单片机重构智能电机控制新标杆】

在智能家电与健康器械市场爆发的今天,核心驱动技术正成为产品突围的关键。传统电机控制方案面临集成度低、开发周期长、性能瓶颈三大痛点,而爱普特电子带来的APT32F1023H8S6单片机无感三合一方案,正在掀起一场智能电机控制的技术革命。 爆款基…...

vue2 中的过滤器以及vue3中的替换方案

在 Vue 2 中,过滤器(filters) 是一种非常实用的语法糖,用于在模板中对数据进行格式化输出处理。我们来深入理解过滤器的原理、使用方式、最佳实践以及其局限性。 vue2 🧠 本质是什么? Vue 2 的过滤器是一…...

Unity EventCenter 消息中心的设计与实现

在开发过程中,想要传递信号和数据,就得在不同模块之间实现通信。直接通过单例调用虽然简单,但会导致代码高度耦合,难以维护。消息中心提供了一种松耦合的通信方式:发布者不需要知道谁接收事件,接收者不需要…...

瑞萨单片机笔记

1.CS for CC map文件中显示变量地址 Link Option->List->Output Symbol information 2.FDL库函数 pfdl_status_t R_FDL_Write(pfdl_u16 index, __near pfdl_u08* buffer, pfdl_u16 bytecount) pfdl_status_t R_FDL_Read(pfdl_u16 index, __near pfdl_u08* buffer, pfdl_…...

300. 最长递增子序列【 力扣(LeetCode) 】

文章目录 零、原题链接一、题目描述二、测试用例三、解题思路3.1 动态规划3.2 贪心 二分 四、参考代码4.1 动态规划4.2 贪心 二分 零、原题链接 300. 最长递增子序列 一、题目描述 给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。 子序列 是由数组…...

MySQL远程连接10060错误:防火墙端口设置指南

问题描述: 如果你通过本机服务器远程连接MySQL,出现10060错误,那可能是你的防火墙的问题 解决: 第一步:查看防火墙规则 通过以下命令查询,看ports是否开放了3306端口,目前只开放了22端口 f…...

使用 OpenCV 实现 ArUco 码识别与坐标轴绘制

🎯 使用 OpenCV 实现 ArUco 码识别与坐标轴绘制(含Python源码) Aruco 是一种广泛用于机器人、增强现实(AR)和相机标定的方形标记系统。本文将带你一步一步使用 Python OpenCV 实现图像中多个 ArUco 码的检测与坐标轴…...