阅读更多

0顶
0踩

编程语言

转载新闻 Java 堆内存溢出梗概分析

2018-03-30 10:13 by 副主编 jihong10102006 评论(0) 有13015人浏览
引用
原文:Java Out of Memory Heap Analysis
链接:https://dzone.com/articles/java-out-of-memory-heap-analysis
译者:dreamanzhao, 无若

任何使用过基于 Java 的企业级后端应用的软件开发者都会遇到过这种低劣、奇怪的报错,这些报错来自于用户或是测试工程师: java.lang.OutOfMemoryError:Java heap space。

为了弄清楚问题,我们必须返回到算法复杂性的计算机科学基础,尤其是“空间”复杂性。如果我们回忆,每一个应用都有一个最坏情况特征。具体来说,在存储维度方面,超过推荐的存储将会被分配到应用程序上,这是不可预测但尖锐的问题。这导致了堆内存的过度使用,因此出现了"内存不够"的情况。

这种特定情况最糟糕的部分是应用程序不能修复,并且将崩溃。任何重启应用的尝试 - 甚至使用最大内存(-Xmx option)- 都不是长久之计。如果不明白什么导致了堆使用的膨胀或突出,内存使用稳定性(即应用稳定性)就不能保障。于是,什么才是更有效的理解关于内存的编程问题的途径?当内存溢出时,明白应用程序的内存堆和分布情况才能回答这个问题。

在这一前提下,我们将聚焦以下方面:
  • 当内存溢出时,获取到 Java 进程中的堆转储。
  • 明白应用程序正在遭遇的内存问题的类型。
  • 使用一个堆分析器,可以使用 Eclipse MAT 这个优秀的开源项目来分析内存溢出的问题。
配置应用,为堆分析做准备

任何像内存溢出这种非确定性的、时有时无的问题对于事后的分析都是一个挑战。所以,最好的处理内存溢出的方法是让 JVM 虚拟机转储一份 JVM 虚拟机内存状态的堆文件。
Sun HotSpot JVM 有一种方法可以引导 JVM 转储内存溢出时的堆状态到一个文件中。其标准格式为 .hprof 。所以,为了实现这种操作,向 JVM 启动项中添加 XX:+HeapDumpOnOutOfMemoryError 。因为内存溢出可能经过很长一段时间才会发生,向生产系统增加这一选项也是必须的。
如果堆转储 .hprof 文件必须被写在一个特定的文件系统位置,那么就添加目录途径到 XX:HeapDumpPath 。只需确保该应用对于指定目录途径始终拥有写入权限。

原因分析

101:了解内存溢出错误的本质

当尝试去评估和了解一个内存溢出错误时,最先做的事情应该是观察内存增长特征。根据情况做出可能性的评估:
  • 尖峰状:这种类型的内存溢出在某种类型的加载上会是比较激烈的。当 JVM 分配内存给 20 个用户时,应用程序可以正常运行。但是,如果到第 100 个用户时可能会遭遇到内存峰值,从而导致内存溢出。有两种可能的办法去解决这个问题。
  • 泄露:由于某些编程问题,内存使用随着时间的推移逐渐增加。

拥有良性垃圾回收机制的健康图表
 

健康一段时间后,随时间推移而泄露的图表
       

引起内存使用凸起、导致内存溢出的内存图表

在我们了解导致使用率激增的内存问题的本质之后,基于从对分析中得到的推断,下面的这些方法或许可以用来避免遭遇内存溢出的错误。

解决内存问题

  • 修复引起内存溢出的代码:由于应用在某段时间内增量添加了一个对象而没有清除其引用(来自正在运行的应用程序的对象引用),导致不得不修复程序错误。例如,这一错误可能是插入了一个哈希表, 其中的业务对象会逐渐增加,然而业务逻辑和事务在完成之后并没有删除这些对象。
  • 增加内存最大值作为一种修复方法。在了解了运行内存特征和堆之后,可能必须增加分配的最大堆内存来避免再次发生内存溢出,因为推荐的最大内存值不能够满足应用程序的稳定性。所以,应用程序可能不得不基于堆分析器的评估,将 Java -Xmx 的 flag 信息更新成一个更高值后再来运行。
堆分析

下面我们将详细分析如何使用一个堆分析工具来分析堆转储。在示例中,将使用到 Eclipse 基金会的开源工具 MAT 。

使用 MAT 进行堆分析

是时候进行深入探讨了。我们将通过一系列的步骤,帮助探索在 MAT 中的不同表现和视图,以获取一个堆内存溢出的示例并思考分析。
1. 打开内存溢出错误发生时产生的 .hprof 堆文件。确保复制转储文件到一个专门的文件夹下,因为 MAT 会创建许多索引文件:文件 -> 打开
2. 打开转储文件,有内存泄漏嫌疑报告和组件报告的选项。选择运行泄漏嫌疑报告。

3. 泄漏嫌疑表打开后,在预览窗口的饼状图会展示在每个对象基础上保留内存的分布情况。它显示了内存中的最大对象(拥有最高保留内存的对象 —— 累积的内存和引用的对象)。
4. 上面的饼图通过聚合拥有最高内存引用(本身内存和总内存)的对象来展示 3 个问题嫌疑人。
让我们逐一分情况查看,评估它是否是内存溢出错误的根本原因。

可疑点 1

由 “<system class loader>” 加载的 454,570 个 “java.lang.ref.Finalizer” 实例占用了 790,205,576(47.96%)个字节。
这就是告诉我们有 454,570 个 JVM finalizer(终结器)实例占据了分配的应用内存的近 50 %。
假设读者知道 Java Finalizer 是做什么的,上面的信息会让我们明白什么呢?
入门阅读:http://stackoverflow.com/questions/2860121/why-do-finalizers-have-a-severe-performance-penalty
本质上,开发者编写了一些定制化的终结器去释放一个实例的资源。这些由终结器收集的实例不在 JVM 使用单独队列的垃圾回收算法的范围之内。实际上,这种途径比起垃圾回收机制的清理路径更长。所以现在我们应该努力搞清楚这些终结器到底终结了什么?
也或许是可疑点 2 ,占据了 20% 的 sun.security.ssl.SSLSocketImpl 。我们能确认是否这些就是要被终结器终结的实例吗?

可疑点 2

现在,让我们打开在 MAT 顶部的工具按钮下面的 Dominator 视图。我们会看到所有的列出的类实例,经由 MAT 解析展示出有效的堆存储。

下一步,在 Dominator 视图,我们尝试理解 java.lang.Finalizer 和 sun.security.ssl.SSLSocketImpl 之间的关系。我们右键点击 sun.security.ssl.SSLSocketImpl 这一列,打开 GC Roots  -> exclude soft/weak references。

现在,MAT 将会开始绘制内存的图表来显示 GC root 的路径以及它所对应的实例引用。这会被显示在另外一个页面上,显示的引用如下:

如上面引用链显示,实例 SSLSocketImpl 来自于 java.lang.ref.Finalizer,整个 SSLSocketImpl 实例大约占用了 88k。我们还注意到 finalizer 链是一个针链表数据结构它指向下一个实例。
推论:在这一点上,我们有一个明确的感觉,Java finalizer 试图在收集 SSLSocketImpl 对象。为了解释为什么还有很多信息没有被收集到,我开始检查代码。

检查代码

代码检查需要查看是不是由 socket 套接字被关闭导致的。在这种情况下,它显示与 I/O 相关的所有流,需要被正确地关闭。在一点上,我们怀疑 JVM 是始作俑者。实际上,在 Open JDK 6.0.XX 的 GC(垃圾收集器)上的代码中有一个 BUG。
我希望这篇文章给你一个模式来分析 Java 应用中的错误是由堆存储还是内部问题导致的。希望你使用堆分析愉快!

扩展阅读

Shallow heap (浅堆) vs. Retained Heap (保留堆)
浅堆是一个对象消耗的内存。根据情况,一个对象需要 32 位或 64 位(取决于其操作系统架构),对于整型为 4 字节,对于 Long 型为 8 字节等等。依据堆转储格式,其内存大小(比如,向 8 对齐)或许适应于更好地塑造虚拟机的真实消耗。
X 的保留集合是当 X 被垃圾回收时,那些将要被移除的对象集合。
X 的保留堆是在 X 的保留集合中所有对象的浅堆之和,也就是 X 存留的内存。
总体讲,一个对象的浅堆就是其在堆中的大小。同一个对象的保留大小就是当对象被垃圾回收时堆内存的总量。
一些对象的主要集合,比如某一特定类的所有对象、或是由某一特定类加载器加载的所有类的所有对象、或仅仅是一些任意的对象,它们的保留集是如果那些主要集的所有对象变得不可接近时所释放的对象集。
保留集包括这些对象和仅通过这些对象才能获取的其它对象。保留集的大小是包含在保留集中的所有对象的堆的大小。
  • 大小: 31.2 KB
  • 大小: 82.6 KB
  • 大小: 15.2 KB
  • 大小: 176.7 KB
  • 大小: 12.3 KB
  • 大小: 123.6 KB
  • 大小: 109.4 KB
来自: 开源中国
0
0
评论 共 0 条 请登录后发表评论

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • Python内存泄漏和内存溢出的解决方案

    像Java程序一样,虽然Python本身也有垃圾回收的功能,但是同样也会产生内存泄漏的问题。 对于一个用 python 实现的,长期运行的后台服务进程来说,如果内存持续增长,那么很可能是有了“内存泄露”。 1、内存泄露的...

  • java 堆内存分析_Java 堆内存溢出梗概分析

    堆分析下面我们将详细分析如何使用一个堆分析工具来分析堆转储。在示例中,将使用到 Eclipse 基金会的开源工具 MAT 。使用 MAT 进行堆分析是时候进行深入探讨了。我们将通过一系列的步骤,帮助探索在 MAT 中的不同...

  • 小白以及计算机类学生的福音!java查看内存溢出的工具

    前言 在本篇文章开始前,我想想来回答一个问题:我为什么要写这一篇关于面试的文章...或许这份面试题还不足以概括所有Java问题,但有了它,我相信你一定不会”败“的很惨,因为有哦了它,足以应对目前市面上绝大部分的J

  • Java内存区域介绍与Java内存溢出异常分析

    如图,我们将内存分成了5大块区域:方法区,堆,虚拟机栈,本地方法栈以及程序计数器。 这几个区域的功能概括如下: 程序计数器:占用内存很小,作用就是指示下一条将要执行指令的地址,分支,循环,跳转,异常处理...

  • java虚拟机内存区域6,深刻理解Java虚拟机-Java内存区域与内存溢出异常

    Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的"高墙",墙外面的人想进去,墙里面的人却想出来。css概述对于从事C、C++程序开发的开发人员来讲,在内存管理领域,他们既是拥有最高权力的“皇帝”又是从事...

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

    深入理解Java虚拟机 读书笔记(二)自动内存管理一、运行时数据区域1. 程序计数器2. Java虚拟机栈3.... 内存溢出和内存泄漏2. Java堆3. 虚拟机栈和本地方法栈4. 方法区和运行时常量池5. 本机直接内存溢出 一、

  • JVM:内存监控及各区域内存溢出解决

    本文仅关注一些常见的虚拟机内存监视手段,以及JVM运行时数据区各个部分内存溢出的发生和对应的解决方案,总体来说属于概括性总结,涉及相对不是很深入,目的是让自己和其它初学者有一个框架性、概念性的了解,当...

  • java内存管理(堆、栈、方法区)

    java内存管理 简介 首先我们要了解我们为什么要学习java虚拟机的内存管理,不是java的gc垃圾回收机制都帮我们释放了内存了吗?但是在写程序的过程中却也往往因为不懂内存管理而造成了一些不容易察觉到的内存问题,...

  • python 内存溢出_Python之内存泄漏和内存溢出

    一、内存泄漏像Java程序一样,虽然Python本身也有垃圾回收的功能,但是同样也会产生内存泄漏的问题。对于一个用 python 实现的,长期运行的后台服务进程来说,如果内存持续增长,那么很可能是有了“内存泄露”。1、...

  • linux java的启动内存溢出,java - Java的R代码可在Linux上运行,但不能在Windows中运行 - 堆栈内存溢出...

    我正在用Java编写一个数据分析程序,该程序依赖R的arulesViz库来挖掘关联规则。我想要什么?我的目的是将规则存储在Java中的String变量中,以便以后进行处理。它是如何工作的?该代码分别使用String.format和eval ...

  • (一)深入理解Java虚拟机-虚拟机内存区域与内存溢出

    作为Java开发者,一般可能关注最多的就是堆内存(heap)和栈内存(stack),实际可分为以下几个区域: 方法区(Method Area):与Java堆一样,是各个线程共享内存区域,它存储已被虚拟机加载的类信息 、常量、静态...

  • JVM--Java内存区域与内存溢出异常

    概括:程序计数器是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器. 作用:在Java虚拟机的概念模型里,字节码解释器工作是就是通过改变这个计数器的值爱选取下一条需要执行的字节码指令,它是程序...

  • android eclipse 内存溢出,Eclipse项目内存溢出解决方案

    再双击InstalledJREs,在右边选择前面有对勾的JRE,再单击右边的“Edit”按钮,出现一个 Edit JRE 的对话框,在其中的Default VM Arguments: 框中输入 -Xms128m -Xmx512m,这样设置Java拟虚机内存使用最小是128M,...

  • jvm内存分配,jvm内存溢出情况分析

    最近在学习jvm的内存分配机制,于是就网上各种查找资料,看博客等,发现有些博客解释的比较好,我便引来记录学习一下. 以下内容转载自:https://www.cnblogs.com/wangjzh/p/5258254.html ...jvm内存分配 ...

  • 基于FPGA的四相八拍步进电机控制系统设计:集成交付、正反转、加速减速及调速功能

    内容概要:本文详细介绍了基于FPGA的四相八拍步进电机控制系统的开发过程。主要内容包括:1. 使用VHDL和Verilog编写LED显示屏驱动代码,用于显示角度、学号和姓名等信息;2. 实现步进电机的正反转控制,通过状态机管理相序变化;3. 开发加速减速控制模块,确保电机启动和停止时的平稳性;4. 设计调速功能,通过调节脉冲频率实现速度控制。此外,文中还讨论了调试过程中遇到的问题及其解决方案。 适合人群:对FPGA开发和步进电机控制感兴趣的电子工程师、嵌入式系统开发者以及相关专业的学生。 使用场景及目标:适用于需要高精度运动控制的应用场合,如工业自动化、机器人技术和精密仪器等领域。目标是帮助读者掌握FPGA控制步进电机的基本原理和技术细节。 其他说明:文中提供了详细的代码片段和调试经验分享,有助于读者更好地理解和应用所学知识。同时,作者还提到了一些实用技巧,如通过PWM调节实现多级变速,以及如何避免步进电机的共振问题。

  • Android开发:基于SQLite的日历备忘录记事本项目详解与实现

    内容概要:本文详细介绍了基于Android Studio开发的日历备忘录记事本项目,涵盖日历查看、添加备忘录、闹钟提醒和删除备忘录等功能。项目使用SQLite数据库进行数据存储,通过CalendarView、EditText、Button等控件实现用户交互,并利用AlarmManager和PendingIntent实现闹钟提醒功能。此外,项目还包括数据库的设计与管理,如创建DatabaseHelper类来管理数据库操作,确保数据的安全性和完整性。文章还探讨了一些常见的开发技巧和注意事项,如时间戳的使用、手势监听的实现等。 适用人群:适用于初学者和有一定经验的Android开发者,尤其是希望深入了解Android开发基础知识和技术细节的人群。 使用场景及目标:该项目旨在帮助开发者掌握Android开发的基本技能,包括UI设计、数据库操作、闹钟提醒机制等。通过实际项目练习,开发者能够更好地理解和应用这些技术,提升自己的开发能力。 其他说明:文中提到一些进阶任务,如用Room替换SQLite、增加分类标签、实现云端同步等,鼓励开发者进一步扩展和优化项目。同时,项目源码公开,便于学习和参考。

  • Matlab实现基于SVM-Adaboost支持向量机结合Adaboost集成学习时间序列预测的详细项目实例(含完整的程序,GUI设计和代码详解)

    内容概要:本文档详细介绍了一个基于SVM(支持向量机)和Adaboost集成学习的时间序列预测项目。该项目旨在通过结合这两种强大算法,提升时间序列预测的准确性和稳定性。文档涵盖了项目的背景、目标、挑战及其解决方案,重点介绍了模型架构、数据预处理、特征选择、SVM训练、Adaboost集成、预测与误差修正等环节。此外,文档还探讨了模型在金融市场、气象、能源需求、交通流量和医疗健康等多个领域的应用潜力,并提出了未来改进的方向,如引入深度学习、多任务学习、联邦学习等先进技术。 适合人群:具备一定机器学习基础的研究人员和工程师,特别是那些从事时间序列预测工作的专业人士。 使用场景及目标:①用于金融市场、气象、能源需求、交通流量和医疗健康等领域的复杂时间序列数据预测;②通过结合SVM和Adaboost,提升预测模型的准确性和稳定性;③处理噪声数据,降低计算复杂度,提高模型的泛化能力和实时预测能力。 其他说明:文档不仅提供了详细的理论解释,还附有完整的Matlab代码示例和GUI设计指导,帮助读者理解和实践。此外,文档还讨论了模型的部署与应用,包括系统架构设计、实时数据流处理、可视化界面、GPU加速推理等方面的技术细节。

  • #游戏之追逐奶酪123

    #游戏之追逐奶酪123

  • 威纶通触摸屏配方管理系统解析:宏程序、数据结构与UI设计

    内容概要:本文详细介绍了威纶通触摸屏配方管理系统的实现方法及其应用场景。首先,文章讲解了配方管理的基本概念和技术背景,强调了配方管理在工业自动化中的重要性。接着,通过具体的宏程序代码示例,展示了如何实现配方的保存、加载以及安全校验等功能。文中还提到配方数据结构的设计,如使用寄存器地址偏移来确保数据不冲突,并通过CSV文件格式方便地管理和维护配方数据。此外,文章深入探讨了UI设计方面的内容,包括动态图层技术和按钮交互效果的应用,使得用户界面更加友好和直观。最后,作者分享了一些实际项目中的经验和技巧,如文件操作的异常处理和宏指令调试方法。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是对触摸屏配方管理系统感兴趣的读者。 使用场景及目标:适用于需要频繁切换设备参数的生产环境,如食品加工、注塑成型等行业。通过使用威纶通触摸屏配方管理系统,可以提高工作效率,减少人为错误,同时简化设备调试和维护流程。 其他说明:附带的工具包提供了完整的宏指令注释版、图库资源和调试工具,帮助用户更好地理解和应用该系统。

  • 张彩明-图形学简明教程 配书资源

    张彩明-图形学简明教程 PPT课件

Global site tag (gtag.js) - Google Analytics