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

深入理解JVM运行时数据区(内存布局 )5大部分 | 异常讨论

前言:

        JVM运行时数据区(内存布局)是Java程序执行时用于存储各种数据的内存区域。这些区域在JVM启动时被创建,并在JVM关闭时销毁。它们的布局和管理方式对Java程序的性能和稳定性有着重要影响。  


目录

一、由以下5大部分组成

1.Heap 堆区(线程共享)

2.程序计数器(线程私有)

什么是线程私有?

特点:不会抛出OOM

3.Java虚拟机栈(线程私有)

4.本地方法栈(线程私有)

5.元数据区(线程共享) ( Java8前叫方法区 )

6.小结-思维导图: ​编辑

二、内存布局中的异常问题

1.堆内存溢出

 2.虚拟机栈和本地方法栈溢出

三、思考题- 判断每个变量在哪个区?


一、由以下5大部分组成

1.Heap 堆区(线程共享)

概念:

堆是JVM中最大的一块内存区域,用于存储所有的对象实例和数组。它是线程共享的。

 特点

堆中的内存空间是垃圾收集器(Garbage Collector)管理的主要区域。JVM通过垃圾收集机制回收不再使用的对象,以防止内存泄漏。

结构

       堆通常分为年轻代(Young Generation)和老年代(Old Generation)。年轻代又细分为Eden区和两个Survivor区(S0和S1)。新创建的对象首先分配到年轻代。

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

        经过几次垃圾收集后仍存活的对象将被移到老年代。 

 


2.程序计数器(线程私有)

什么是线程私有?

每个线程都有自己的程序计数器。

概念:

       在JVM中,线程的执行是通过线程轮流切换(也称为上下文切换)来实现的。在这种机制下,每个线程都得到一小段时间片来执行它的指令。当时间片用完或者发生其他中断时,处理器会切换到另一个线程继续执行。由于处理器在任何一个时刻只能执行一条线程的指令,所以在进行线程切换时,必须用独立的程序计数器保存当前线程的执行状态,以便在切换回来时能够从正确的位置继续执行。

       程序计数器是一个很小的内存区域,专门用于记录当前线程正在执行的指令地址。也就是说,程序计数器保存了当前线程下一条将要执行的字节码指令的地址。

     对于本地方法来说,程序计数器则为空。

特点:不会抛出OOM

    由于它的内存需求极小,并且仅用于存储指令地址,因此JVM规范中没有规定它会抛出“OutOfMemoryError”异常,这使得它成为JVM中唯一 一个不会因为内存不足而导致异常的区域。


3.Java虚拟机栈(线程私有)

概念:

        Java虚拟机栈的⽣命周期和线程相同,其为每个线程创建的私有内存区域每个线程在执行方法时,会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。常说的堆内存、栈内存中,栈内存指的就是虚拟机栈。

作用

1.局部变量表  :保存了方法参数和局部变量,所需的内存空间在编译期间完成分配,当进⼊⼀个⽅法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在执⾏期间不会改变局部变量表⼤小。

2.操作数栈: 用于操作数的计算和方法调用

3.动态链接: 保存了方法调用中的引用(指向运⾏时常量池的方法引用)。

4.方法返回地址:PC寄存器的地址。

异常:

       如果线程请求的栈深度大于虚拟机允许的深度,将抛出StackOverflowError异常。如果虚拟机在栈扩展时无法分配足够的内存,也会抛出OutOfMemoryError异常。

   


4.本地方法栈(线程私有)

概念

       本地方法栈中存储了本地方法的调用信息。本地方法栈与虚拟机栈类似,区别在于它为本地方法(Native Methods)服务。本地方法栈也是线程私有的。

     本地方法是指那些使用非Java语言编写的、并通过Java调用的函数或方法。在Java中,本地方法通常使用C或C++编写,并通过本地库接口来进行调用。

简单了解JVM执行Java程序的基本流程 | 一次编译,到处运行-CSDN博客 

该博客介绍了什么是本地方法库。


5.元数据区(线程共享) ( Java8前叫方法区 )

作用

       用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。在方法区中,保存了类的结构信息,例如字段表、方法的字节码、常量池等。JVM在加载类时,会在方法区中为其分配空间,存储类的相关信息。它是线程共享的,也就是说,所有线程都可以访问方法区中的数据。

       字段表:列出了该类声明的所有字段(成员变量和静态变量),包括字段的名称、类型、修饰符(如 privatestatic 等)等。字段表不存储字段的值,而是存储字段的结构和元数据。

演变:

       在《Java虚拟机规范中》把此区域称之为“⽅法区”,而在HotSpot虚拟机的实现中,在JDK7时此 区域叫做永久代(PermGen),JDK8中叫做元空间(Metaspace)。

元空间的改进:

  1. 使用本地内存:与永久代不同,元空间使用的是本地内存(即操作系统管理的内存),而不是 JVM 堆内存。这意味着元空间的大小不再受 JVM 堆内存的限制,而是可以根据实际需要动态增长(只要系统内存允许)。

  2. 自动调整:元空间的内存分配可以根据应用程序的需要动态调整,减少了内存溢出问题的发生。JVM 提供了 -XX:MaxMetaspaceSize 参数来限制元空间的最大大小,但如果不设置,该空间可以根据需求自动增长。

  3. 更高效的内存管理:元空间的实现使得 JVM 的内存管理更加高效,因为它减少了永久代中的一些垃圾回收开销,并且更好地适应了应用程序的内存需求。

运行时常量池:

运行时常量池方法区的⼀部分,存放字面量与符号引用。

字面量: 字符串(JDK8移动到堆中)final常量基本数据类型的值

符号引用: 类和结构的完全限定名、字段的名称和描述符、⽅法的名称和描述符


6.小结-思维导图: 

 


二、内存布局中的异常问题

1.堆内存溢出

堆:放对象的地方。

可以设置JVM参数-Xms:设置堆的最⼩值、-Xmx:设置堆最⼤值。

在对象数量达到最大堆容量后就会产生内存溢出异常。

出现Java堆内存溢出时,

异常堆栈信息"java.lang.OutOfMemoryError"会进⼀步提⽰"Java heap space"。很明确的告知我们,OOM发生在堆上。

此时要对Dump出来的⽂件进行分析,分析问题的产⽣到底是出现了内存泄漏

  • 内存泄漏:表示对象不再被程序使用,但由于某些错误引用无法被 GC 回收。这会逐渐耗尽内存,最终导致 OutOfMemoryError。泄漏对象是不必要的、意外存在的。
  • 内存溢出:表示应用程序的确需要那么多内存来存活当前的对象。如果内存不足以满足需求,就会出现 OutOfMemoryError。此时这些对象是必要的,只是 JVM 堆内存不够

 2.虚拟机栈和本地方法栈溢出

       由于我们HotSpot虚拟机将虚拟机栈与本地⽅法栈合⼆为⼀,因此对于HotSpot来说,栈容量只需要 由-Xss参数来设置。

两种异常:

抛出StackOverFlow异常: 线程请求的栈深度大于虚拟机所允许的最大深度(例如,递归调用过深)。

抛出OOM异常:虚拟机在拓展栈时无法申请到⾜够的内存空间(例如内存紧张、大量线程的场景)。

如何应对

应对 StackOverflowError

- 检查递归调用的逻辑,确保递归有合理的终止条件。

- 调整程序结构,减少不必要的深层次方法调用。

- 如果必须使用深度递归,考虑通过 JVM 参数 -Xss 增加单个线程的栈大小(但这可能会增加 OOM 的风险)。

- 应对 OutOfMemoryError

- 降低应用程序的内存使用,尤其是减少不必要的线程创建。

- 增加系统的物理内存,或通过 JVM 参数增加最大堆内存。

- 通过优化代码,减少栈的频繁扩展需求,例如减少对象创建或方法调用的频率。

三、思考题- 判断每个变量在哪个区?

public class test5 {int a; // 成员变量static int b; // 静态变量test2 test2 = new test2(); // 成员变量String s = "猜猜每个变量在哪个区?"; // 字符串成员变量public static void main(String[] args) {test1 t = new test1(); // 局部变量}
}

答案揭晓:

test5 类本身的元数据(如类的结构、方法、字段等信息表)存储在方法区中。在 JDK 8 中,这个区域被称为元数据区(Metaspace)。

成员变量 a: 存储在堆内存中,属于每个 test5 对象的实例。


静态变量 b: 存储在方法区的静态存储区中,属于 test5 类本身,而不是任何特定对象。

成员变量 test2: 作为引用类型(对象)的成员变量,存储在堆内存中。它指向 new test2() 创建的对象,后者也存储在堆内存中。

成员变量 s:  是引用类型(对象)的成员变量,存储在堆内存中。它指向字符串常量池中的 "猜猜每个变量在哪个区?" 对象。在 JDK 8 中,字符串常量池已经移动到了堆内存中。

局部变量 t: 局部变量,存储在栈内存中。它指向 new test1() 创建的对象,后者存储在堆内存中。

相关文章:

深入理解JVM运行时数据区(内存布局 )5大部分 | 异常讨论

前言: JVM运行时数据区(内存布局)是Java程序执行时用于存储各种数据的内存区域。这些区域在JVM启动时被创建,并在JVM关闭时销毁。它们的布局和管理方式对Java程序的性能和稳定性有着重要影响。 目录 一、由以下5大部分组成 1.…...

JAVA根据表名获取Oracle表结构信息

响应实体封装 import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor;/*** author CQY* version 1.0* date 2024/8/15 16:33**/ Data NoArgsConstructor AllArgsConstructor Builder public class OracleTableInfo …...

网络性能优化

网络性能优化是确保网络稳定性、速度和可靠性的关键步骤。优化过程通常包括诊断问题、识别瓶颈以及实施具体的解决方案。以下是关于如何进行网络性能优化的详细指南: 一、问题诊断 网络性能监控 网络流量分析工具:使用Wireshark、NetFlow、Ntop等工具监…...

[C++String]接口解读,深拷贝和浅拷贝,string的模拟实现

💖💖💖欢迎来到我的博客,我是anmory💖💖💖 又和大家见面了 欢迎来到C探索系列 作为一个程序员你不能不掌握的知识 先来自我推荐一波 个人网站欢迎访问以及捐款 推荐阅读 如何低成本搭建个人网站…...

理性看待、正确理解 AI 中的 Scaling “laws”

编者按:LLMs 规模和性能的不断提升,让人们不禁产生疑问:这种趋势是否能一直持续下去?我们是否能通过不断扩大模型规模最终实现通用人工智能(AGI)?回答这些问题对于理解 AI 的未来发展轨迹至关重…...

【OCR 学习笔记】二值化——全局阈值方法

二值化——全局阈值方法 固定阈值方法Otsu算法在OpenCV中的实现固定阈值Otsu算法 图像二值化(Image Binarization)是指将像素点的灰度值设为0或255,使图像呈现明显的黑白效果。二值化一方面减少了数据维度,另一方面通过排除原图中…...

Java - IDEA开发

使用IDEA开发Java程序步骤: 创建工程 Project;创建模块 Module;创建包 Package;创建类;编写代码; 如何查看JDK版本 Package介绍: package是将项目中的各种文件,比如源代码、编译生成的字节码、配置文件、…...

Oracle(62)什么是内存优化表(In-Memory Table)?

内存优化表(In-Memory Table)是指将表的数据存储在内存中,以提高数据访问和查询性能的一种技术。内存优化表通过利用内存的高速访问特性,显著减少I/O操作的延迟,提升数据处理的速度。这种技术在需要高性能数据处理的应…...

#window家庭版安装hyper-v#

由于window 11 家庭版没有hyper-v虚拟机服务,则需要安装一下,使用如下操作 1:新建一个txt文件,拷贝如下脚本到里面 pushd "%\~dp0" dir /b %SystemRoot%\servicing\Packages\*Hyper-V*.mum >hyper-v.txt for /f %%i in (findst…...

【云原生】Pass容器研发基础——汇总篇

云原生基础汇总 系列综述: 💞目的:本系列是个人整理为了云计算学习的,整理期间苛求每个知识点,平衡理解简易度与深入程度。 🥰来源:每个知识点的修正和深入主要参考各平台大佬的文章&#xff0c…...

【Py/Java/C++三种语言详解】LeetCode743、网络延迟时间【单源最短路问题Djikstra算法】

可上 欧弟OJ系统 练习华子OD、大厂真题 绿色聊天软件戳 od1441了解算法冲刺训练(备注【CSDN】否则不通过) 文章目录 相关推荐阅读一、题目描述二、题目解析三、参考代码PythonJavaC 时空复杂度 华为OD算法/大厂面试高频题算法练习冲刺训练 相关推荐阅读 …...

交替输出

交替输出 题目:线程 1 输出 a 5 次,线程 2 输出 b 5 次,线程 3 输出 c 5 次。现在要求输出 abcabcabcabcabc wait notify 版 public class SyncWaitNotify {private volatile int flag;private volatile int loopNumber;public SyncWaitNo…...

JS(三)——更改html内数据

获取 DOM 元素&#xff0c;然后修改其属性或内容。使用 getElementById 方法获取特定 ID 的元素&#xff1a; <p id"myParagraph">这是初始的文本</p> const paragraph document.getElementById(myParagraph); paragraph.innerHTML 这是修改后的文本…...

CSS小玩意儿:文字适配背景

一&#xff0c;效果 二&#xff0c;代码 1&#xff0c;搭个框架 添加一张背景图片&#xff0c;在图片中显示一行文字。 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" conte…...

C++:平衡二叉搜索树之红黑树

一、红黑树的概念 红黑树&#xff0c; 和AVL都是二叉搜索树&#xff0c; 红黑树通过在每个节点上增加一个储存位表示节点的颜色&#xff0c; 可以是RED或者BLACK&#xff0c; 通过任何一条从根到叶子的路径上各个节点着色方式的限制&#xff0c;红黑树能够确保没有一条路径会比…...

CentOS 7 系统优化

CentOS 7 系统优化 1、配置YUM源 阿里云的YUM源配置&#xff1a; CentOS 7使用以下命令&#xff1a; sudo wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repoCentOS 8使用以下命令&#xff1a; sudo wget -O /etc/yum.repos.d/CentOS…...

扫雷游戏——附源代码

扫雷游戏的源代码比较简单&#xff0c;不设计比较复杂的代码&#xff0c;主要是多个函数的组合&#xff0c;每个函数执行自己的功能&#xff0c;最终支持游戏的完成。 1.菜单 我们需要一个提醒信息来让用户进行选择。 void menu() {printf("***********************\n&…...

Vue3列表(List)

效果如下图&#xff1a;在线预览 APIs List 参数说明类型默认值bordered是否展示边框booleanfalsevertical是否使用竖直样式booleanfalsesplit是否展示分割线booleantruesize列表尺寸‘small’ | ‘middle’ | ‘large’‘middle’loading是否加载中booleanfalsehoverable是否…...

HarmonyOS NEXT - Navigation组件封装BaseNavigation

demo 地址: https://github.com/iotjin/JhHarmonyDemo 代码不定时更新&#xff0c;请前往github查看最新代码 在demo中这些组件和工具类都通过module实现了&#xff0c;具体可以参考HarmonyOS NEXT - 通过 module 模块化引用公共组件和utils 官方介绍 组件导航 (Navigation)(推…...

浅看MySQL数据库

有这么一句话&#xff1a;“一个不会数据库的程序员不是合格的程序员”。有点夸张&#xff0c;但是确是如此。透彻学习数据库是要学习好多知识&#xff0c;需要学的东西也是偏难的。我们今天来看数据库MySQL的一些简单基础东西&#xff0c;跟着小编一起来看一下吧。 什么是数据…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

【python异步多线程】异步多线程爬虫代码示例

claude生成的python多线程、异步代码示例&#xff0c;模拟20个网页的爬取&#xff0c;每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程&#xff1a;允许程序同时执行多个任务&#xff0c;提高IO密集型任务&#xff08;如网络请求&#xff09;的效率…...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

C++:多态机制详解

目录 一. 多态的概念 1.静态多态&#xff08;编译时多态&#xff09; 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1&#xff09;.协变 2&#xff09;.析构函数的重写 5.override 和 final关键字 1&#…...

jmeter聚合报告中参数详解

sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample&#xff08;样本数&#xff09; 表示测试中发送的请求数量&#xff0c;即测试执行了多少次请求。 单位&#xff0c;以个或者次数表示。 示例&#xff1a;…...

离线语音识别方案分析

随着人工智能技术的不断发展&#xff0c;语音识别技术也得到了广泛的应用&#xff0c;从智能家居到车载系统&#xff0c;语音识别正在改变我们与设备的交互方式。尤其是离线语音识别&#xff0c;由于其在没有网络连接的情况下仍然能提供稳定、准确的语音处理能力&#xff0c;广…...

沙箱虚拟化技术虚拟机容器之间的关系详解

问题 沙箱、虚拟化、容器三者分开一一介绍的话我知道他们各自都是什么东西&#xff0c;但是如果把三者放在一起&#xff0c;它们之间到底什么关系&#xff1f;又有什么联系呢&#xff1f;我不是很明白&#xff01;&#xff01;&#xff01; 就比如说&#xff1a; 沙箱&#…...

Mac flutter环境搭建

一、下载flutter sdk 制作 Android 应用 | Flutter 中文文档 - Flutter 中文开发者网站 - Flutter 1、查看mac电脑处理器选择sdk 2、解压 unzip ~/Downloads/flutter_macos_arm64_3.32.2-stable.zip \ -d ~/development/ 3、添加环境变量 命令行打开配置环境变量文件 ope…...