JVM 内存结构基于JDK1.8【JVM篇三】

大家好,我们又见面了,我是你们的朋友全栈君。

在上一篇文章《别翻了,这篇文章绝对让你深刻理解java类的加载以及ClassLoader源码分析【JVM篇二】》中,相信大家已经对Java类加载机制有了全面的了解。那么,类加载之后,字节码数据在Java虚拟机内存中是如何存放的?Java虚拟机在为类实例或成员变量分配内存时是如何分配的?这两个问题涉及到了JVM内存结构的知识,这篇文章将为大家解答。

文章目录:1、内存结构还是运行时数据区?2、运行时数据区3、线程共享:Java堆、方法区3.1、Java堆3.2、JVM堆内存溢出后,其他线程是否可继续工作?3.3、方法区3.4、JDK1.8之前的方法区3.5、JDK1.8之后的方法区3.6、JDK1.8之后的方法区为何变化如此之大?4、线程私有:程序计数器、Java虚拟机栈、本地方法栈4.1、Java虚拟机栈(JVM Stacks)4.2、本地方法栈(Native Method Stacks)4.3、程序计数器5、JVM内存结构总结

1、内存结构还是运行时数据区?要解答本文提到的这些问题,我们首先需要了解一下Java虚拟机的内存结构。

2、运行时数据区JVM被分为三个主要的子系统:类加载器子系统、运行时数据区和执行引擎。本文主要讲解其中的运行时数据区(Runtime Data Areas)。

JVM 内存结构基于JDK1.8【JVM篇三】在Java虚拟机规范中,定义了五种运行时数据区,分别是Java堆、方法区、虚拟机栈、本地方法区、程序计数器。

顺便提一下,运行时常量池也会进入方法区,也就是说方法区中已经包括了常量池。

JVM 内存结构基于JDK1.8【JVM篇三】

3、线程共享:Java堆、方法区我们首先来了解一下线程共享的Java堆和方法区。

3.1、Java堆Java堆是内存空间中占用的最大一块区域,用于存放对象实例及数组,也就是说我们代码中通过new关键字创建的对象都存放在这里。因此,这里也是垃圾回收器的主要活动场所,被称为GC堆。每个JVM进程只有一个Java堆。根据垃圾回收器的规则,我们可以对Java堆进行进一步的划分,具体Java堆内存结构如下图所示:

JVM 内存结构基于JDK1.8【JVM篇三】从上图可以看出,Java堆并不是单纯的一整块区域,实际上Java堆根据对象存活时间的不同,被分为年轻代和老年代两个区域。年轻代还被进一步划分为Eden区、From Survivor 0区和To Survivor 1区。默认的虚拟机配置比例是Eden:From:To = 8:1:1。

仔细看过上面的Java堆结构图的朋友可能会发现-Xms和-Xmn的字样,这正是控制堆的JVM参数。我们可以通过JVM参数动态控制Java堆中的各空间大小。JVM的参数有很多,但常用的就那么几个,用多了很容易记住。下面我们来讲讲关于堆的常见JVM参数:

当Java堆内没有足够的空间去完成实例分配,并且堆也无法扩展时,将会抛出常见的OutOfMemoryError异常,也就是我们常说的OOM异常。

3.2、JVM堆内存溢出后,其他线程是否可继续工作?JVM堆内存溢出后,也就是OOM异常,网上有一道非常火的面试题:JVM堆内存溢出后,其他线程是否可继续工作?

实际上这个问题需要具体场景分析。但是一般情况下,发生OOM的线程都会终止(除非代码写的太烂),该线程持有的对象占用的heap都会被GC回收,释放内存。因为发生OOM之前要进行GC,即便其他线程能够正常工作,也会因为频繁的GC产生较大的影响。

也就是说,发生OOM的线程一般情况下会死亡,也就是会被终止,该线程持有的对象占用的heap都会被GC回收,释放内存。因为发生OOM之前要进行GC,即便其他线程能够正常工作,也会因为频繁的GC产生较大的影响。

3.3、方法区方法区(Method Area)与上面讲的Java堆一样,都是各个线程共享的,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分,但它有一个别名叫做Non-Heap(非堆),目的是与Java堆区分开来。

3.4、JDK1.8之前的方法区就以HotSpot虚拟机来说,在JDK1.8之前,方法区也被称作为永久代。这个方法区会发生我们常见的java.lang.OutOfMemoryError: PermGen space异常,注意是永久代异常信息,我们也可以通过启动参数来控制方法区的大小。

在JDK7之前的HotSpot虚拟机中,纳入字符串常量池的字符串被存储在永久代中,因此导致了一系列的性能问题和内存溢出错误。特别突出的例子就是String的intern()方法。

3.5、JDK1.8之后的方法区JDK8之后就没有永久代这一说法,取而代之的是元空间(meta space),而且将老年代与元空间剥离。元空间放置于本地的内存中,因此元空间的最大空间就是系统的内存空间,从而不会再出现像永久代的内存溢出错误,也不会出现泄漏的数据移到交换区这样的事情。用户可以为元空间设置一个可用空间最大值,不设置的话默认根据类的元数据大小动态增加元空间的容量。对于一个64位的服务器端JVM来说,其默认的-XX:MetaspaceSize值为21MB。也就是说,默认的元空间大小是21MB。

只要类加载器还存活,其加载的类的元数据也是存活的,不会被回收掉,也就是同生共死。

JVM 内存结构基于JDK1.8【JVM篇三】

3.6、JDK1.8之后的方法区为何变化如此之大?做这个改变主要是基于以下两点原因:

1、由于永久代(PermGen)内存经常会溢出,引发恼人的java.lang.OutOfMemoryError: PermGen,因此JVM的开发者希望这一块内存可以更灵活地被管理,不要再经常出现这样的OOM错误。

2、移除永久代(PermGen)可以促进HotSpot JVM与JRockit VM的融合,因为JRockit没有永久代。

4、线程私有:程序计数器、Java虚拟机栈、本地方法栈Java堆以及方法区的数据是共享的,但是有一些部分是线程私有的。线程私有部分可以分为:程序计数器、Java虚拟机栈、本地方法栈三大部分。

4.1、Java虚拟机栈(JVM Stacks)1、Java虚拟机的每一条线程都有自己私有的Java虚拟机栈,这个Java虚拟机栈与线程同时创建,因此它与线程有相同的生命周期。

2、Java虚拟机栈描述的是Java方法执行的内存模型:每一个方法在执行的同时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息,每一个方法从调用直至执行完成的过程,就对应着一个栈帧在Java虚拟机栈中的入栈到出栈的过程。

3、局部变量表存放了编译期可知的各种基本数据类型、对象引用和returnAddress类型。其中64位长度的long和double类型的数据会占用2个局部变量空间(Slot),其余的数据类型只占用1个。局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小。

4、Java虚拟机栈既允许被实现成固定的大小,也允许根据计算动态扩展和收缩。如果采用固定大小的话,每一个线程的Java虚拟机栈容量可以在线程创建的时候独立选定。在Java虚拟机栈中会发生两种异常,这个在虚拟机规范中有指出:

如果线程请求分配的栈容量超过Java虚拟机栈允许的最大容量,Java虚拟机将会抛出StackOverflowError异常;也就是栈溢出错误!方法递归调用产生StackOverflowError异常这种结果。如果Java虚拟机栈可以动态扩展,并且在尝试扩展的时候无法申请到足够的内存或者在创建新的线程时没有足够的内存去创建对应的Java虚拟机栈,那么虚拟机将会抛出OutOfMemoryError异常。也就是OOM内存溢出错误!(线程启动过多)当然,可以通过参数-Xss去调整JVM栈的大小。

4.2、本地方法栈(Native Method Stacks)和虚拟栈相似,只不过它服务于Native方法,线程私有。当Java虚拟机使用其他语言(例如C语言)来实现指令集解释器时,也会使用到本地方法栈。如果Java虚拟机不支持native方法,并且自己也不依赖传统栈的话,可以无需支持本地方法栈。

与Java虚拟机栈一样,本地方法栈区域也会抛出StackOverflowError和OutOfMemoryError异常。

HotSpot虚拟机直接就把本地方法栈和虚拟机栈合二为一。

4.3、程序计数器当前线程所执行的字节码的行号指示器,用于记录正在执行的虚拟机字节指令地址,线程私有。

5、JVM内存结构总结JVM 内存结构基于JDK1.8【JVM篇三】程序计数器:

Java虚拟栈:

Native方法栈:

Java堆:

方法区:

发布者:全栈程序员栈长,转载请注明出处:https://www.php.cn/link/c0243062e292cce3284a1cd9a8e30300原文链接:https://www.php.cn/link/c8377ad2a50fb65de28b11cfc628d75c

以上就是JVM 内存结构基于JDK1.8【JVM篇三】的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/11229.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
什么是CRM系统,它的作用是什么?解读5个核心功能
上一篇 2025年11月15日 14:07:07
移民行业引入CRM会达到什么效果?探讨3个行业优势
下一篇 2025年11月15日 14:07:22

相关推荐

  • Python命令怎样使用profile分析脚本性能 Python命令性能分析的基础教程

    使用Python的cProfile模块分析脚本性能最直接的方式是通过命令行执行python -m cProfile your_script.py,它会输出每个函数的调用次数、总耗时、累积耗时等关键指标,帮助定位性能瓶颈;为进一步分析,可将结果保存为文件python -m cProfile -o ou…

    2026年5月10日
    000
  • Python递归函数追踪与性能考量:以序列打印为例

    本文深入探讨了Python中一种递归打印序列元素的方法,并着重演示了如何通过引入缩进参数来有效追踪递归函数的执行流程和参数变化。通过实际代码示例,文章揭示了递归调用可能带来的潜在性能开销,特别是对调用栈空间的需求,以及Python默认递归深度限制可能导致的错误,为读者提供了理解和优化递归算法的实用见…

    2026年5月10日
    000
  • python中numpy的用法

    NumPy是Python中用于科学计算的强大库,它提供了以下功能:多维数组处理矩阵运算快速傅里叶变换(FFT)线性代数随机数生成 NumPy在Python中的强大功能 NumPy是Python中用于科学计算的一个强大且灵活的库。它提供了用于处理多维数组和矩阵的一组高效工具,是数据分析和机器学习项目的…

    2026年5月10日
    100
  • CSS技巧:在复杂悬停效果中确保图像始终可见

    CSS技巧:在复杂悬停效果中确保图像始终可见CSS技巧:在复杂悬停效果中确保图像始终可见CSS技巧:在复杂悬停效果中确保图像始终可见CSS技巧:在复杂悬停效果中确保图像始终可见

    本教程探讨如何在包含悬停效果的CSS卡片布局中,确保图像始终显示在最顶层而不被裁剪或遮挡。通过调整HTML结构,利用CSS的position和z-index属性,以及引入pointer-events,我们将解决图像被overflow: hidden和扩展叠加层遮盖的问题,实现复杂的视觉交互效果。 在…

    2026年5月10日 用户投稿
    000
  • python如何捕获所有类型的异常_python try except捕获所有异常的方法

    答案:捕获所有异常推荐使用except Exception as e,可捕获常规错误并记录日志,避免影响程序正常退出;需拦截系统信号时才用except BaseException as e。 在Python中,要捕获所有类型的异常,最常见且推荐的方法是使用 except Exception as e…

    2026年5月10日
    000
  • c语言short怎么设置

    C语言中short类型数据为16位有符号整数,范围[-32768, 32767]。设置方法:1. 声明short变量(如:short myShort = 123;);2. 使用短整型字面量(如:myShort = 123S;);3. 使用类型转换(如:short myShort = (short) …

    2026年5月10日
    000
  • WebAssembly中导入JavaScript函数:无胶水代码集成指南

    本文深入探讨了在WebAssembly模块中直接导入和使用JavaScript函数的机制,特别是当使用Emscripten的STANDALONE_WASM和SIDE_MODULE编译模式时。文章详细分析了TypeError: import object field ‘GOT.mem&#8…

    2026年5月10日
    000
  • c语言整除函数怎么表示

    C语言中进行整数除法的函数是 /,其语法为 result = dividend / divisor,结果取整且不会有小数部分。 C 语言整除函数表示方法 C 语言中,用于进行整数除法的函数是 /。 语法: result = dividend / divisor; 其中: 立即学习“C语言免费学习笔记…

    2026年5月10日
    000
  • 人工智能如何为 C 语言代码提供安全增强功能?

    人工智能通过提供以下功能来提升 c 代码安全性:静态分析:识别潜在安全漏洞(例如缓冲区溢出);动态分析:监控代码执行并检测异常行为;模糊测试:生成随机输入以测试代码的异常行为;自动化修复:建议修复措施或自动生成补丁程序。 人工智能赋能 C 代码:提升安全性 人工智能 (AI) 在 C 代码安全方面发…

    2026年5月10日
    100
  • Angular mat-tab 高度自适应与布局优化指南

    本教程旨在解决Angular Material mat-tab组件在Flexbox布局中无法自动填充父容器高度的问题。文章将深入分析问题根源,并提供使用CSS深度选择器(::ng-deep)精确控制mat-tab-body-wrapper和mat-tab-body高度的解决方案,确保组件在指定布局下…

    2026年5月10日
    000
  • html自定义滚动条代码怎么写_html自定义滚动条代码编写指南

    html自定义滚动条代码怎么写_html自定义滚动条代码编写指南html自定义滚动条代码怎么写_html自定义滚动条代码编写指南html自定义滚动条代码怎么写_html自定义滚动条代码编写指南html自定义滚动条代码怎么写_html自定义滚动条代码编写指南

    自定义HTML滚动条可通过CSS的::-webkit-scrollbar伪元素实现,适用于Webkit内核浏览器;首先设置整体滚动条宽高,再定义轨道、滑块样式及悬停效果,可针对特定容器应用;为提升兼容性,Firefox可使用scrollbar-width和scrollbar-color属性适配,IE…

    2026年5月10日 用户投稿
    000
  • Go语言Cgo代码GDB调试失效:Go 1.1版本下的挑战与官方进展

    本文探讨了go语言程序中cgo代码在使用gdb进行调试时遇到的挑战,特别指出go 1.1版本中存在的变量值显示异常问题。该问题是一个已知的官方缺陷(go issue 5221),导致在cgo交互部分gdb调试功能失效,而go 1.0版本则无此问题。文章将通过示例代码重现该现象,并阐述其根源及官方的解…

    2026年5月10日
    000
  • c语言中free(f)的意思

    c语言中free(f)的含义 free(f) 函数在 C 语言中释放由 malloc()、calloc() 或 realloc() 等函数动态分配的内存块。 作用: 释放动态分配的内存块。将指针 f 设置为 NULL。 语法: void free(void *f); 参数: 立即学习“C语言免费学习…

    用户投稿 2026年5月10日
    000
  • CSS Grid 实现表格列等宽布局

    本文旨在提供一种无需指定表格总宽度和各列宽度,即可实现表格列等宽布局的方案。通过利用 CSS Grid 布局的特性,可以使每列的宽度自动适应内容,并保持所有列的宽度一致,从而避免使用 JavaScript 动态计算和设置列宽,实现更简洁高效的布局方式。 在传统的 HTML 表格中,实现列等宽布局通常…

    2026年5月10日
    000
  • Flexbox布局中带标签文本域的重叠问题及解决方案

    本文探讨了在使用css flexbox布局和spectre.css框架时,为文本域添加标签可能导致内容重叠的问题。核心原因在于父容器固定高度与子元素`height: 100%`的冲突,导致文本域未能正确计算标签所占空间。解决方案是移除父容器的固定高度,并为文本域设置响应式的视口高度(`vh`)值,确…

    2026年5月10日
    300
  • c语言中x*x是什么意思

    在 C 语言中,x*x 表示 x 与自身相乘的结果,即 x 的平方。它对应于数学中的 x²,优先级高于加减运算。用于计算面积、体积和求解二次方程,但需要注意浮点数精度可能导致轻微偏差。 x*x 在 C 语言中的含义 在 C 语言中,x*x 表示 x 与自身相乘的结果,即 x 的平方。它对应于数学中的…

    2026年5月10日
    000
  • 为什么Golang函数参数推荐使用值传递 分析值拷贝与指针的开销对比

    为什么Golang函数参数推荐使用值传递 分析值拷贝与指针的开销对比为什么Golang函数参数推荐使用值传递 分析值拷贝与指针的开销对比为什么Golang函数参数推荐使用值传递 分析值拷贝与指针的开销对比为什么Golang函数参数推荐使用值传递 分析值拷贝与指针的开销对比

    go语言推荐函数参数使用值传递,核心原因有三:1.并发安全与可预测性,值传递避免竞态条件,确保函数修改不影响原始数据;2.内存局部性与cpu缓存友好,小型数据拷贝成本低且访问效率高;3.减轻垃圾回收负担,栈上分配的值无需gc跟踪。此外,go编译器通过逃逸分析优化值分配,使值拷贝在多数场景下高效且安全…

    2026年5月10日 用户投稿
    000
  • c语言里面字符是什么意思

    字符在 C 语言中以单个字节存储于 char 变量中,用单引号括起表示常量,例如 ‘A’。字符变量用于存储字符值,可使用函数如 putchar() 输出、getchar() 输入、toupper() 转换大小写。字符数组存储多个字符,如 char name[10]。字符串是带…

    2026年5月10日
    000
  • 创建自动轮播图:JavaScript 实现指南

    创建自动轮播图:JavaScript 实现指南创建自动轮播图:JavaScript 实现指南创建自动轮播图:JavaScript 实现指南创建自动轮播图:JavaScript 实现指南

    本文旨在帮助开发者构建一个自动轮播图,解决手动切换和自动播放的问题。我们将提供完整的 HTML、CSS 和 JavaScript 代码示例,并详细解释实现原理,确保即使是 JavaScript 新手也能轻松掌握。重点在于理解 JavaScript 如何控制轮播图的自动切换和手动控制逻辑,以及如何优化…

    2026年5月10日 用户投稿
    000
  • Go 调用 C 函数时处理 printf 格式字符串警告及内存管理最佳实践

    本文探讨在 go 中调用 c 语言 `printf` 函数时遇到的 `-wformat-security` 警告,解释其产生原因。提供两种主要解决方案:一是通过使用 `puts` 或 `fputs` 替代 `printf` 来避免警告,二是通过 c 类型别名增强类型安全性。文章强调 `c.cstri…

    2026年5月10日
    000

发表回复

登录后才能评论
关注微信