《深入理解Java虚拟机》读书笔记——Java内存区域与内存溢出异常

《深入理解Java虚拟机》读书笔记----Java内存区域及内存溢出异常 Java内存区域及内存溢出异常运行时数据区域程序计数器Java虚拟机栈本地方法栈Java堆方法区运行时常量池HotSpot虚拟机对象对象的创建对象的内存布局对象的访问定位堆溢出排查Java堆内存溢出虚拟机栈和本地方法栈溢出方法区和运行时常量池溢出 前言:最近粗略读完了《深入理解Java虚拟机》,根据自己做的读书笔记,整理输出,希望对大家有所帮助。能力有限可能会有些错误或纰漏,希望大家海涵!同时也致敬作者周志明前辈,这本书不愧是”JVM圣经“,写的真的好,推荐大家去看看原书! 众所周知,JVM拥有自动内存管 阅读详情

一、内存区域(运行时数据区域)划分:

IMG_20170723_165258_HDR.jpg

  1. 程序计数器

    • 线程安全,每条线程都有一个独立的程序计数器
    • 字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令
    • 分支、循环、跳转、异常处理、线程恢复等都是依靠它实现
  2. Java虚拟机栈

    • 也是线程私有,生命周期与线程相同
    • 描述的是Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程
    • 局部变量表存放编译期可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用和returnAddress类型(指向一条字节码指令的地址);其中long和double占用两个局部变量空间,其余的一个。
    • 局部变量表所需的空间在编译期间完成分配,且在方法运行期间不会改变大小
    • Java虚拟机规范对这个区域规定了两种异常状况:
      • 如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;
      • 如果虚拟机可以动态扩展,如果扩展时无法申请到足够多的内存,就会抛出OutOfMemoryError异常。
  3. 本地方法栈

    • 与虚拟机栈非常相似
    • 与虚拟机栈区别在于虚拟机栈为虚拟机执行Java方法(字节码)服务,本地方法栈则为虚拟机使用的Native方法服务。
  4. Java堆

    • 是被所有线程共享;唯一目的就是存放对象实例
    • Java虚拟机规范:所有的对象实例以及数组都要在堆上分配。但随着JIT编译器的发展与逃逸分析技术逐渐成熟等原因,所有对象都分配在堆上也就不是那么绝对。
    • 是垃圾收集器管理的主要区域,很多时候也被称为“GC堆”。
  5. 方法区

    • 与Java堆一样,是各个线程共享的内存区域
    • 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
    • HotSpot虚拟机使用永久代来实现方法区
    • 运行时常量池是方法区的一部分

二、HotSpot虚拟机对象探秘

  1. 对象的创建
    • 虚拟机遇到一条new指令(创建对象)时,首先检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的是否已被加载、解析和初始化过。若没有则先执行相应的类加载过程。类加载检查通过后,虚拟机为新生对象分配内存。
    • 内存分配方式:
      • 指针碰撞:假设Java堆中内存是绝对规整的,所有用过的内存都放在一边,空余的内存放在另一边,中间放着一个指针作为分界点的指示器,所分配的内存仅仅是把那个指针向空闲空间那边挪动一段与对象大小相等的距离。
      • 空闲列表:如果Java堆中的内存不是规整的,已使用的内存和空闲的内存相互交错,此时无法使用指针碰撞;则虚拟机维护一个列表,记录哪些内存块是可用的,在分配的时候从列表中找到一块足够大的空间划分给对象实例,并更新列表上的记录。
    • 分配内存时保证线程安全
      • 对分配内存空间的动作进行同步处理——实际上虚拟机采用CAS配上失败重试的方式保证更新操作的原子性;
      • 把内存分配的动作按照线程划分在不同的空间之中进行,即每个线程在Java堆中预先分配一小块内存,称为本地线程分配缓冲
  2. 对象的内存布局
    • 在HotSpot虚拟机中,对象在内存中存储的布局分为3块区域:
      1. 对象头(Header)。 包含两部分信息,如下:
        • 第一部分用于存储对象自身的运行时数据,如哈希码、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等
        • 另一部分是类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。
      2. 实例数据(Instance Data)。是对象存储的有效信息,也是在程序代码中所定义的各种类型的字段内容。
      3. 对齐填充(Padding)。仅仅起着占位符的作用。
  3. 对象的访问方式
    1. 使用句柄。
      • Java堆中划分一块内存作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息,如图:
      • 好处:reference中存储的是稳定的句柄地址,在对象被移动(如垃圾收集时)时只会改变句柄中的示例数据指针,而reference本身不需要修改。
    2. 直接指针。
      • reference中存储的直接就是对象地址。
      • 好处:速度更快,节省了一次指针定位的时间开销
  4. 实战:OutOfMemoryError异常
    • Java堆溢出
    • 虚拟机栈和本地方法栈溢出
    • 方法区和运行时常量池溢出
    • 本机直接内存溢出
100天精通Python(爬虫篇)——第122天:基于selenium接管已启动的浏览器(反反爬策略) 阅读详情

相关推荐

【软考高级架构设计师】——2025年上半年软考真题(回忆版)

a)异构计算和算法优化b)资源抽象和容器控制c)安全和隔离(大致是这个意思)

小志的博客 4830

对Java虚拟机栈深度的理解

在读“深入理解Java虚拟机”一书时看到这个概念:在Java虚拟机规范中,对这个区域规定了两种异常状况:如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果虚拟机栈可以动态扩展(当前大部分的Java虚拟机都可动态扩展,只不过Java虚拟机规范中也允许固定长度的虚拟机栈),如果扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常。 理解...

赵树祥的博客 3822

KEGG两类报错--①No gene can be mapped--②URL ‘https://rest.kegg.jp/link/hsa/pathway‘…

版本问题,重新安装一下clusterProfiler包。网络问题,可以等待之后再试一下(试过不是)(以上可以排除基因不存在的错误因素)

weixin_57699783的博客 2万+

Java虚拟机OOM之虚拟机栈和本地方法栈溢出(4)

一、在 Java 虚拟机规范中,对虚拟机栈这个区域规定了两种异常状况:(1)如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError 异常; (2)如果虚拟机栈可以动态扩展(当前大部分的 Java 虚拟机都可动态扩展,只不过 Java 虚拟机规范中也允许固定长度的虚拟机栈),当扩展时无法申请到足够 的内存时会抛出 OutOfMemoryError 异常。 (3)与

徐刘根的博客 7750

使用Linux安装yum报错 E: Unable to correct problems, you have held broken packages.

使用Linux安装yum报错 E: Unable to correct problems, you have held broken packages.

weixin_43205954的博客 2462

使用MCAL的Fee模块集成ETAS存储协议栈

由于ETAS Fee模块导致初始化时间较长,且集成占用的内存较大,所以最终考虑使用MCAL中的Fee模块来集成ETAS的Nvm模块,本文介绍具体的集成方法注意:本文所涉及的集成前提是原有的ETAS协议栈已正常使用使用IFX Fee需要手动配置Fee,可能有出错的风险,最好是利用脚本自动生成代码来实现。另外,需要注意IFX的Fee中block数据没有CRC校验,如果使用该Fee,建议Nvm中加CRC校验(ETAS Fee中block自带CRC,可以不需要Nvm Crc),防止数据被意外篡改导致的异常。

赞的博客 404

《深入理解 Java 虚拟机》读书笔记:Java 内存区域与内存溢出异常

《深入理解 Java 虚拟机》读书笔记:Java 内存区域与内存溢出异常

w36680130的博客 116

YOLOv11涨点改进 | Conv篇/小目标改进 | YOLOv11引入SPDConv卷积特征无损下采样模块,增加YOLOv11小目标P2检测层(助力小目标任务高效涨点)

本文提出了一种创新的SPDConv模块来优化YOLOv11模型,通过空间到深度(SPD)层和非步幅卷积层实现特征无损下采样。该方法有效解决了传统CNN中因跨步卷积和池化层导致的细粒度信息丢失问题,特别提升了小目标检测性能。实验表明,SPDConv在目标检测和图像分类任务中显著优于现有SOTA模型。文章详细介绍了模块原理、核心代码实现,并提供了YOLOv11集成SPDConv的具体方法,包括配置文件修改和P2层增强等优化技巧。该技术为计算机视觉任务提供了一种高效的特征保留方案。

Ai缝合怪、助力小伙伴高效发论文 586

【深入理解JAVA虚拟机】读书笔记——Java内存区域与内存溢出异常

学习参考资料:周志明老师的著作《深入理解Java虚拟机(第3版)》 1.运行时数据区域 根据《Java虚拟机规范》的规定,Java虚拟机所管理的内存将会分为以下几个运行时数据区域,如下图所示。 其中每个线程有自己独自的虚拟机栈、本地方法栈、程序计数器 1.1程序计数器 程序计数器(Program Counter Register) 是一块较小的内存空间,通过改变这个计数器的值来选取下一条需要执行的字节码指令。 刚才我们说程序计数器是私有的,这是因为Java虚拟机在执行多线程时,采用的是线程轮流切换,.

遇事不决问清风的博客 1516

【Java开发者必看】LangChain4j实战指南:使用AIService轻松集成聊天记忆Chat Memory到SpringBoot应用,通过封装多轮复杂对话,使聊天记忆的实现变得简单

聊天记忆是指在与用户的多轮对话过程中,能够记住之前的交互内容,从而提供更加连贯和个性化的回复。LangChain4j支持通过ChatMemoryProvider接口实现聊天记忆功能。

Spring Boot-Common On With You 448

QML从入门到实战 - 完整学习路线

想入门 QML 开发?来 “从零开始学 QML” 专栏,海量源码 + 实战案例 + 大型项目拆解,手把手教你搞定跨平台 UI 设计,小白也能轻松掌握!

BenBierBa的博客 3479

深入理解Java虚拟机 读书笔记(二)Java内存区域与内存溢出异常

深入理解Java虚拟机 读书笔记(二)自动内存管理一、运行时数据区域1. 程序计数器2. Java虚拟机栈3. 本地方法栈局部变量表4. Java堆分配缓冲区(TLAB)5. 方法区运行时常量池6. 直接内存二、对象探秘1. 对象的创建指针碰撞空闲列表线程安全2. 对象的内存布局对象头实例数据对齐填充3. 对象的访问定位直接指针访问句柄访问优缺点对比三、实战OutOfMemoryError1. 内存溢出和内存泄漏2. Java堆3. 虚拟机栈和本地方法栈4. 方法区和运行时常量池5. 本机直接内存溢出 一、

z2656453168的博客 1178

大模型量化方法总结

本文主要对大模型量化方法进行了总结,希望对学习大语言模型的同学们有所帮助。 文章目录 1. 前言 2. 模型精度 3. 量化方法 3.1 方法一 3.2 方法二 3.3 方法三

herosunly的博客 1万+

【深入理解Java虚拟机】读书笔记——Java内存区域与内存溢出异常

Java内存区域与内存溢出异常 一、 运行时数据区域 总共也就这么 5 个区(直接内存不属于 JVM 运行时数据区的一部分),除了程序计数器其他的地方都有可能出现 OOM (OutOfMemoryError),其中像是程序计数器和两个栈(Java 虚拟机栈 & 本地方法栈)都是每个线程要有一个的,所以肯定是线程隔离的。而其他 2 个区就是线程共享的了,也就是说,如果有多个线程要同时访问这两个区的数据,是会出现线程安全问题的。 程序计数器 当前线程所执行的字节码的行号指示器,字节码解.

Vermont_的博客 408

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

读书笔记——《深入理解Java虚拟机》系列之Java内存区域与常见内存溢出异常

第一次读这本书时,就被文中的一句话所折服:“Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的‘高墙’,墙外面的人想进去,墙里面的人却想出来。”的确,对于使用C++编程的程序员来说,他们肩负着对每一个对象所占内存空间的维护责任;而对于Java程序员来说,动态分配内存机制让我们无需对申请的内存进行free,不容易出现内存的泄露和溢出。

Jesmin的优快云博客 575

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

深入理解 Java 虚拟机》读书笔记:Java 内存区域与内存溢出异常

前言 最近开始看这本书,记得前段时间拿起这本书的时候,心情是相当沉重的!当时的剧本是这样的—— 有点无聊啊!(偶然撇过书架)这么多书得看到什么时候啊,要不要拿一本翻翻呢?但是在家里好像有点看不下去啊,是太安逸了吗?最近那本《图解 HTTP》也还没看完,感觉暂时有点不想看了。(走到书架前)还是挑几本优先级比较高的带到███下班的时候看吧。(沉思)嗯,这本带过去~ 当我拿起《深入理解 Jav...

JavaAOE的博客 241

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

《深入理解Java虚拟机第三版》读书笔记(2)Java内存区域与内存溢出异常

《深入理解Java虚拟机第三版》读书笔记(2)Java内存区域与内存溢出异常 Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来。 一、运行时数据区域 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而一直存在,有些区域则是依赖用户线程的启动和结束而建立和销毁。 1、程序计数器 程序计数器(Program Counter Regist

qq_43533806的博客 129

深入理解Java虚拟机 读书笔记: (二)Java内存区域与内存溢出异常

1. 概述 Java 语言拥有虚拟机,可以进行自动化内存管理,不需要为程序中的产生的对象进行内存管理,不容易出现内存泄漏和内存溢出问题。与此同时,一旦出现内存泄漏和溢出方面的问题,那排查错误、修正问题将会成为一项异常艰难的工作。 2. 运行时数据区域 2.1 概念图 2.2 程序计数器 程序计数器(Program Counter Register):是一块较小的内存空间,当前线程所执行的字节码的行号指示器。 作用: 通过计数器的值来判断下一条需要执行的字节码指令,它是程序控制流的指示器,进行分支、循环、

xueguchen的博客 535

《深入理解Java虚拟机》读书笔记:第2章 Java内存区域与内存溢出异常

1、概述 Java虚拟机在执行Java程序的过程中会把它管理的内存区域划分成不同的区域。这些区域都有各自的用途以及创建和销毁时间,有的区域随着虚拟机进程的启动而存在,有的区域以来用户线程的启动而建立和销毁。Java虚拟机内存管理划分如下图: [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kwzYvIbh-1620832056530)(jmm.jpeg)] 2、程序计数器 程序计数器是一个较小的内存区域,它是线程私有的内存,可以看作是当前线程执行的字节码的行号指示器。一个处理器

334

深入理解java虚拟机-读书笔记1-Java内存区域与内存溢出异常

自动内存管理机制 - java内存区域与内存溢出异常 - 垃圾收集器与内存分配策略 - 虚拟机性能监控与故障处理工具 - 调优案例分析与实战java虚拟机运行时数据区,如下图所示: 程序计数器: 一块较小的内存空间,可以看做时当前线程所执行的字节码的行号指示器。 由于Java虚拟机的多线程时通过线程轮流切换并分配执行时间的方式来实现的,为了线程切换后能恢复到正确的执行位置,每

wsongmao的博客 488

《深入理解Java虚拟机》读书笔记1——Java内存区域与内存溢出异常

1.运行时数据区域        Java虚拟机所管理的内存将会包含以下几个运行时数据区域,如下图所示。 1.1程序计数器        程序计数器是一块较小的内存空间,它的作用可以看做是当前线程锁执行的字节码的行号指示器。在虚拟机的概念模型里,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支,循环、跳转、异常处理、线程恢复等基础

零下九度 1263

深入理解JAVA虚拟机(JAVA内存区域与内存溢出异常)-读书笔记

深入理解JAVA虚拟机(JAVA内存区域与内存溢出异常)-读书笔记

weixin_42292484的博客 194

Java内存区域与内存溢出异常——深入理解Java虚拟机读书笔记(一)

第二章 Java内存区域与内存溢出异常 运行时内存区域 程序计数器 Program Counter Register(线程私有) 程序计数器是当前线程所执行的字节码的行号指示器,字节码解释器工作时会通过改变程序计数器的值来选取下一条需要运行的字节码指令。 执行Java方法-记录正在执行的虚拟机字节码指令的地址 执行Native方法-空(Undefined) *不会出现OutOfMemoryErr...

jtsyh2008的博客 249
上一篇: ambari-server安装(ubuntu、deepin、debian通用)
下一篇: 《深入理解Java虚拟机》读书笔记——垃圾收集器与内存分配策略
code_better
博客等级 码龄11年 48粉丝 43原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值