深入理解 Java 虚拟机内存区域

Java 虚拟机(JVM)是 Java 程序运行的核心环境,它通过内存管理为程序提供高效的执行支持。JVM 在运行时将内存划分为多个区域,每个区域都有特定的作用和生命周期。本文将详细介绍 JVM 的运行时数据区域及其功能,并探讨与内存相关的常见问题,如内存溢出(OOM)和栈溢出(SOF)。
在这里插入图片描述


JVM 运行时数据区域

JVM 将其管理的内存划分为若干区域,包括线程私有和线程共享两类。以下是主要区域的概览:

1. 程序计数器(Program Counter Register)

  • 作用:线程私有的小型内存区域,记录当前线程执行的字节码指令地址,用于控制程序流程(如分支、循环、跳转等)。
  • 特点
    • 若执行 Java 方法,则记录字节码地址;若执行 Native 方法,则为空(Undefined)。
    • 是唯一不会抛出 OutOfMemoryError 的区域。
  • 生命周期:随线程创建而生,随线程结束而灭。

2. Java 虚拟机栈(Java Virtual Machine Stacks)

  • 作用:线程私有,管理 Java 方法的执行。每个方法调用对应一个栈帧(Stack Frame),包含局部变量表、操作数栈、动态连接和方法返回地址。
  • 栈帧结构
    • 局部变量表:存储方法参数和局部变量。
    • 操作数栈:存放中间计算结果和临时变量。
    • 动态连接:支持方法调用时的符号引用解析。
    • 方法返回地址:记录方法返回位置。
  • 异常
    • 栈深度超限:StackOverflowError
    • 内存不足:OutOfMemoryError
  • 调整:通过 -Xss 参数设置栈大小。

3. 本地方法栈(Native Method Stack)

  • 作用:线程私有,为 Native 方法服务,功能与虚拟机栈类似。
  • 异常:同样可能抛出 StackOverflowErrorOutOfMemoryError

4. Java 堆(Java Heap)

  • 作用:线程共享,存储对象实例,是垃圾收集器(GC)的主要管理区域。
  • 分代结构
    • 新生代:包括 Eden 和 Survivor(S0、S1),存放新对象。
    • 老年代:存放长期存活的对象。
    • 元空间(JDK 8 后取代永久代):使用本地内存。
  • 年龄限制:对象年龄记录在对象头,最大值为 15(4 位二进制),由 -XX:MaxTenuringThreshold 设置。
  • 异常:内存不足时抛出 OutOfMemoryError
  • 调整:通过 -Xms(初始值)和 -Xmx(最大值)配置堆大小。

5. 方法区(Method Area)

  • 作用:线程共享,存储类信息、常量、静态变量和编译后的代码。
  • 演变
    • JDK 7 前:称为永久代(PermGen),通过 -XX:MaxPermSize 设置。
    • JDK 8 后:改为元空间(Metaspace),通过 -XX:MaxMetaspaceSize 设置,使用本地内存。
  • 异常:扩展失败抛出 OutOfMemoryError

6. 运行时常量池(Runtime Constant Pool)

  • 作用:方法区的一部分,存储 Class 文件中的字面量(如字符串常量)和符号引用。
  • 特点:具备动态性,运行时可通过 String.intern() 添加常量。
  • 异常:内存不足抛出 OutOfMemoryError

7. 直接内存(Direct Memory)

  • 作用:非 JVM 规范定义区域,通过 NIO(如 DirectByteBuffer)直接分配堆外内存。
  • 调整:通过 -XX:MaxDirectMemorySize 设置,默认与 -Xmx 一致。
  • 异常:分配失败抛出 OutOfMemoryError

内存区域对比

区域作用范围可能异常
程序计数器线程私有
虚拟机栈线程私有StackOverflowError, OutOfMemoryError
本地方法栈线程私有StackOverflowError, OutOfMemoryError
Java 堆线程共享OutOfMemoryError
方法区线程共享OutOfMemoryError
运行时常量池线程共享OutOfMemoryError
直接内存非运行时区OutOfMemoryError

对象在 JVM 中的生命周期

1. 对象创建

  • 步骤
    1. 遇到 new 指令,检查常量池中类的符号引用并加载类。
    2. 在堆中分配内存(指针碰撞或空闲列表)。
    3. 初始化对象(调用 <init>() 方法)。
  • 内存分配方式
    • 指针碰撞:堆内存规整时使用。
    • 空闲列表:堆内存不规整时使用,依赖垃圾收集器是否带压缩功能。
  • 并发安全:通过 CAS 或 TLAB(线程本地分配缓冲)确保分配安全。

2. 对象内存布局

  • 对象头
    • Mark Word:存储运行时数据(如哈希码、GC 年龄、锁状态)。
    • 类型指针:指向类的元数据。
    • 数组长度(仅数组对象):记录数组大小。
  • 实例数据:存储字段内容。
  • 对齐填充:确保内存对齐。

3. 对象访问

  • 句柄访问reference 指向句柄池,稳定但间接。
  • 直接指针(HotSpot 默认):reference 直接指向对象地址,速度更快。

内存溢出与栈溢出

1. OutOfMemoryError (OOM)

除程序计数器外,其他区域都可能因内存不足抛出 OOM。常见场景包括:

  • 堆溢出:对象过多,-Xmx 不足。
  • GC 开销超限:GC 时间超 98% 且回收不足 2%。
  • 元空间不足:类加载过多。
  • 直接内存溢出:NIO 分配超限。
  • 线程创建失败:系统内存不足以支持新线程。

2. StackOverflowError (SOF)

  • 原因
    • 递归过深。
    • 大量循环或死循环。
  • 参数:通过 -Xss 调整栈大小。

示例分析

以下是一个简单程序的内存分配过程:

public class JVMCase {public final static String MAN_SEX_TYPE = "man"; // 常量池public static String WOMAN_SEX_TYPE = "woman";   // 方法区public static void main(String[] args) {Student stu = new Student(); // 堆中创建对象,栈中存引用stu.setName("nick");JVMCase jvmcase = new JVMCase();print(stu); // 静态方法入栈jvmcase.sayHello(stu); // 非静态方法入栈}
}
  • 类加载时,静态变量和常量分配在方法区。
  • main 执行时,对象在堆中创建,引用存于栈中,方法调用依次入栈。

结语

理解 JVM 内存区域是掌握 Java 性能调优的基础。从线程私有的程序计数器到共享的 Java 堆和方法区,每个区域各司其职。通过合理配置参数(如 -Xmx-Xss-XX:MaxMetaspaceSize),并结合工具(如 jmap、MAT)分析内存问题,可以有效避免 OOM 和 SOF,提升程序稳定性。

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

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

相关文章

PDF转JPG(并去除多余的白边)

首先&#xff0c;手动下载一个软件&#xff08;poppler for Windows&#xff09;&#xff0c;下载地址&#xff1a;https://github.com/oschwartz10612/poppler-windows/releases/tag/v24.08.0-0 否则会出现以下错误&#xff1a; PDFInfoNotInstalledError: Unable to get pag…

深入剖析MyBatis缓存机制:原理、源码与实战指南

引言 MyBatis作为一款优秀的ORM框架,其缓存机制能显著提升数据库查询性能。但许多开发者仅停留在“知道有缓存”的层面,对其实现原理和细节知之甚少。本文将结合可运行的代码示例和源码分析,手把手带您彻底掌握MyBatis缓存机制。 一、MyBatis缓存分类 MyBatis提供两级缓存…

Vue 使用 vue-router 时,多级嵌套路由缓存问题处理

Vue 使用 vue-router 时&#xff0c;多级嵌套路由缓存问题处理 对于三级菜单&#xff08;或多级嵌套路由&#xff09;&#xff0c;vue 都是 通过 keep-alive 组件来实现路由组件的缓存。 有时候三级或者多级路由时&#xff0c;会出现失效情况。以下是三级菜单缓存的例子。 最…

QSplitter保存和读取

官方文档提供的方案 保存 connect(ui->splitter, &QSplitter::splitterMoved, [](){settings.setValue("splitterSizes", ui->splitter->saveState()); });读取 ui->splitter->restoreState(settings.value("splitterSizes").toByteA…

VanillaVueSvelteReactSolidAngularPreact前端框架/库的简要介绍及其优势

VanillaVueSvelteReactSolidAngularPreact前端框架/库的简要介绍及其优势。以下是这些前端框架/库的简要介绍及其优势&#xff1a; 1. Vanilla 定义&#xff1a;Vanilla 并不是一个框架&#xff0c;而是指 原生 JavaScript&#xff08;即不使用任何框架或库&#xff09;。优势…

Java多线程与高并发专题——关于CopyOnWrite 容器特点

引入 在 CopyOnWriteArrayList 出现之前&#xff0c;我们已经有了 ArrayList 和 LinkedList 作为 List 的数组和链表的实现&#xff0c;而且也有了线程安全的 Vector 和Collections.synchronizedList() 可以使用。 首先我们来看看Vector是如何实现线程安全的 &#xff0c;还是…

Jmeter接口测试详解

今天笔者呢&#xff0c;想给大家聊聊Jmeter接口测试流程详解&#xff0c;废话不多说直接进入正题。 一、jmeter简介 Jmeter是由Apache公司开发的java开源项目&#xff0c;所以想要使用它必须基于java环境才可以&#xff1b; Jmeter采用多线程&#xff0c;允许通过多个线程并…

DeepSeek开启AI办公新模式,WPS/Office集成DeepSeek-R1本地大模型!

从央视到地方媒体&#xff0c;已有多家媒体机构推出AI主播&#xff0c;最近杭州文化广播电视集团的《杭州新闻联播》节目&#xff0c;使用AI主持人进行新闻播报&#xff0c;且做到了0失误率&#xff0c;可见AI正在逐渐取代部分行业和一些重复性的工作&#xff0c;这一现象引发很…

通过Golang的container/list实现LRU缓存算法

文章目录 力扣&#xff1a;146. LRU 缓存主要结构 List 和 Element常用方法1. 初始化链表2. 插入元素3. 删除元素4. 遍历链表5. 获取链表长度使用场景注意事项 源代码阅读 在 Go 语言中&#xff0c;container/list 包提供了一个双向链表的实现。链表是一种常见的数据结构&#…

【大学生体质】智能 AI 旅游推荐平台(Vue+SpringBoot3)-完整部署教程

智能 AI 旅游推荐平台开源文档 项目前端地址 ☀️项目介绍 智能 AI 旅游推荐平台&#xff08;Intelligent AI Travel Recommendation Platform&#xff09;是一个利用 AI 模型和数据分析为用户提供个性化旅游路线推荐、景点评分、旅游攻略分享等功能的综合性系统。该系统融合…

【渗透测试】基于时间的盲注(Time-Based Blind SQL Injection)

发生ERROR日志告警 查看系统日志如下&#xff1a; java.lang.IllegalArgumentException: Illegal character in query at index 203: https://api.weixin.qq.com/sns/jscode2session?access_token90_Vap5zo5UTJS4jbuvneMkyS1LHwHAgrofaX8bnIfW8EHXA71IRZwsqzJam9bo1m3zRcSrb…

redis数据类型以及底层数据结构

redis数据类型以及底层数据结构 String&#xff1a;字符串类型&#xff0c;底层就是动态字符串&#xff0c;使用sds数据结构 Map:有两种数据结构&#xff1a;1.压缩列表&#xff1a;当hash结构中存储的元素个数小于了512个。并且元 …

DeepSeek R1-32B医疗大模型的完整微调实战分析(全码版)

DeepSeek R1-32B微调实战指南 ├── 1. 环境准备 │ ├── 1.1 硬件配置 │ │ ├─ 全参数微调:4*A100 80GB │ │ └─ LoRA微调:单卡24GB │ ├── 1.2 软件依赖 │ │ ├─ PyTorch 2.1.2+CUDA │ │ └─ Unsloth/ColossalAI │ └── 1.3 模…

window下的docker内使用gpu

Windows 上使用 Docker GPU需要进行一系列的配置和步骤。这是因为 Docker 在 Windows 上的运行环境与 Linux 有所不同,需要借助 WSL 2(Windows Subsystem for Linux 2)和 NVIDIA Container Toolkit 来实现 GPU 的支持。以下是详细的流程: 一、环境准备 1.系统要求 Window…

Ubuntu 下 nginx-1.24.0 源码分析 - cycle->modules[i]->type

Nginx 中主要有以下几种模块类型 类型 含义 NGX_CORE_MODULE 核心模块&#xff08;如进程管理、错误日志、配置解析&#xff09;。 NGX_EVENT_MODULE 事件模块&#xff08;如 epoll、kqueue 等 IO 多路复用机制的实现&#xff09;。 NGX_HTTP_MODULE HTTP 模块&#xf…

八、排序算法

一些简单的排序算法 8.1 冒泡排序 void Bubble_sort(int a[] , int len){int i,j,flag,tmp;for(i=0 ; i < len-1 ; i++){flag = 1;for(j=0 ; j < len-1-i ; j++){if(a[j] > a[j+1]){tmp = a[j];a[j] = a[j+1];a[j+1] = tmp;flag = 0;}}if(flag == 1){break;}}…

Sqlserver安全篇之_手工创建TLS用到的pfx证书文件

Sqlserver官方提供的Windows Powershell脚本 https://learn.microsoft.com/zh-cn/sql/database-engine/configure-windows/configure-sql-server-encryption?viewsql-server-ver16 # Define parameters $certificateParams {Type "SSLServerAuthentication"Subje…

npm install -g @vue/cli 方式已经无法创建VUE3项目

采用该方式&#xff0c;启动VUE3项目&#xff0c;运行命令&#xff0c;出现报错&#xff1a; npm install -g vue/cli PS D:\> npm install -g vue/cli npm warn deprecated inflight1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lr…

3.8[a]cv

函数核心目标 实现屏幕空间内三角形的光栅化&#xff0c;将三角形覆盖的像素点颜色填充到帧缓冲区&#xff0c;同时处理深度测试&#xff08;Z-Buffer&#xff09;。这是渲染管线中几何阶段到像素阶段的关键步骤 包围盒计算&#xff08;Bounding Box&#xff09;​** ​功能&…

导入 Excel 规则批量修改或删除 Excel 表格内容

我们前面介绍过按照规则批量修改 Excel 文档内容的操作&#xff0c;可以对大量的 Excel 文档按照一定的规则进行统一的修改&#xff0c;可以很好的解决我们批量修改 Excel 文档内容的需求。但是某些场景下&#xff0c;我们批量修改 Excel 文档内容的场景比较复杂&#xff0c;比…