第一篇:java.lang.OutOfMemoryError: Java heap space

Java 应用程序只允许使用有限的内存量。此限制是在应用程序启动期间指定的。为了让事情变得更复杂,Java 内存被分成两个不同的区域。这些区域称为堆空间和 Permgen(用于永久代):

这些区域的大小是在 Java 虚拟机 (JVM) 启动期间设置的,可以通过指定 JVM 参数 -Xmx 和 -XX:MaxPermSize 进行自定义。如果您没有明确设置大小,将使用特定于平台的默认值。

该 java.lang.OutOfMemoryError:Java堆空间 时,应用程序错误将被触发 尝试添加更多的数据放入堆空间区域,但没有足够的空间供它 。

请注意,可能有足够的物理内存可用,但是只要 JVM 达到堆大小限制,就会抛出 java.lang.OutOfMemoryError: Java heap space 错误。

1,是什么原因造成的?

java.lang.OutOfMemoryError 的 最常见原因很简单:您尝试将 XXL 应用程序放入 S 大小的 Java 堆空间中。也就是说 - 应用程序只需要比正常运行可用的更多的 Java 堆空间。此 OutOfMemoryError 消息的其他原因更为复杂,并且是由编程错误引起的:

  • 使用量/数据量激增 。该应用程序旨在处理一定数量的用户或一定数量的数据。当用户数或数据量突然激增并超过预期阈值时,在峰值之前正常运行的操作停止运行并触发 java.lang.OutOfMemoryError: Java heap space 错误。
  • 内存泄漏 。特定类型的编程错误会导致您的应用程序不断消耗更多内存。每次使用应用程序的泄漏功能时,都会将一些对象留在 Java 堆空间中。随着时间的推移,泄漏的对象会消耗所有可用的 Java 堆空间并触发已经熟悉的 java.lang.OutOfMemoryError: Java heap space 错误。

2,举个例子

第一个例子非常简单——下面的 Java 代码尝试分配一个 2M 整数的数组。当您编译它并使用 12MB 的 Java 堆空间 ( java -Xmx12m OOM ) 启动时,它会失败并显示 java.lang.OutOfMemoryError: Java heap space 消息。使用 13MB Java 堆空间,程序运行得很好。

class OOM {static final int SIZE=2*1024*1024;public static void main(String[] a) {int[] i = new int[SIZE];}
}

内存泄漏示例

第二个也是更现实的例子是内存泄漏。在 Java 中,当开发人员创建和使用新对象( 例如 new Integer(5) )时 ,他们不必自己分配内存——这由 Java 虚拟机 (JVM) 负责。在应用程序的生命周期中,JVM 会定期检查内存中的哪些对象仍在使用,哪些尚未使用。可以丢弃未使用的对象,回收内存并再次使用。这个过程称为 垃圾收集 。JVM 中负责收集的相应模块称为 垃圾收集器 (GC)。

Java 的自动内存管理依赖于 GC 定期查找未使用的对象并删除它们。稍微简化一下,我们可以说 Java 中的 内存泄漏是应用程序不再使用某些对象但 垃圾收集 无法识别它的情况 。结果,这些未使用的对象无限期地保留在 Java 堆空间中。这种堆积最终会触发 java.lang.OutOfMemoryError: Java heap space 错误。

构造一个满足内存泄漏定义的 Java 程序相当容易:

class KeylessEntry {static class Key {Integer id;Key(Integer id) {this.id = id;}@Overridepublic int hashCode() {return id.hashCode();}}public static void main(String[] args) {Map m = new HashMap();while (true)for (int i = 0; i < 10000; i++)if (!m.containsKey(new Key(i)))m.put(new Key(i), "Number:" + i);}
}

当您执行上面的代码时,您可能希望它永远运行而不会出现任何问题,假设朴素的缓存解决方案仅将底层 Map 扩展到 10,000 个元素,因为除此之外,所有键都已经存在于 HashMap 中。然而,实际上这些元素将继续添加,因为 Key 类在其 hashCode() 旁边不包含适当的 equals() 实现。

结果,随着时间的推移,随着不断使用泄漏代码,“缓存”结果最终会消耗大量 Java 堆空间。当泄漏的内存填满堆区域中的所有可用内存并且 垃圾收集 无法清除它时,会抛出 java.lang.OutOfMemoryError:Java 堆空间 。

解决方案很简单——添加类似于下面的 equals() 方法的实现,你会很高兴。但在你找到原因之前,你肯定会失去一些宝贵的脑细胞。

@Override
public boolean equals(Object o) {boolean response = false;if (o instanceof Key) {response = (((Key)o).id).equals(this.id);}return response;
}

3,解决办法是什么?

在某些情况下,分配给 JVM 的堆数量不足以满足在该 JVM 上运行的应用程序的需求。在这种情况下,你应该只分配更多的堆——请参阅本章末尾以了解如何实现这一点。

然而,在许多情况下,提供更多的 Java 堆空间并不能解决问题。例如,如果您的应用程序包含内存泄漏,添加更多堆只会推迟 java.lang.OutOfMemoryError: Java heap space 错误。此外,增加 Java 堆空间量也往往会增加 GC 暂停 的长度,影响应用程序的 吞吐量或延迟 。

如果您希望解决 Java 堆空间的潜在问题而不是掩盖症状,您需要弄清楚代码的哪一部分负责分配最多的内存。换句话说,您需要回答以下问题:

  1. 哪些对象占据堆的大部分
  2. 在源代码中分配这些对象的位置

此时,请确保在您的日历中清除几天(或 – 请参阅项目符号列表下方的自动方式)。以下是一个粗略的流程大纲,可以帮助您回答上述问题:

  • 获得安全许可,以便从 JVM 执行堆转储。“转储”基本上是您可以分析的堆内容的快照。因此,这些快照可能包含机密信息,例如密码、信用卡号等,因此出于安全原因,甚至可能无法获取此类转储。
  • 在适当的时候获取转储。准备好进行一些转储,因为在错误的时间进行时,堆转储包含大量噪音,实际上可能毫无用处。另一方面,每次堆转储都会完全“冻结”JVM,因此不要使用太多堆转储,否则您的最终用户会开始面临性能问题。
  • 找到一台可以加载转储的机器。当您的 JVM-to-troubleshoot 使用例如 8GB 的​​堆时,您需要一台超过 8GB 的​​机器来分析堆内容。启动转储分析软件(我们推荐 Eclipse MAT ,但也有同样好的替代品)。
  • 检测到最大堆消耗者的 GC 根的路径。我们已经覆盖在一个单独的后这一活动 在这里 。对于初学者来说尤其困难,但练习会让您了解结构和导航机制。
  • 接下来,您需要弄清楚在源代码中的何处分配了具有潜在危险的大量对象。如果您非常了解应用程序的源代码,则可以通过几次搜索来完成此操作。

或者,我们建议 Plumbr,这是唯一具有自动根本原因检测功能的 Java 监控解决方案 。在其他性能问题中,它捕获所有 java.lang.OutOfMemoryError 并自动为您提供有关最需要内存的数据结构的信息。

Plumbr 负责在幕后收集必要的数据——这包括有关堆使用情况的相关数据(只有对象布局图,没有实际数据),以及一些您甚至在堆转储中都找不到的数据。它还会为您进行必要的数据处理——在 JVM 遇到 java.lang.OutOfMemoryError 时立即进行 。这是来自 Plumbr 的 java.lang.OutOfMemoryError 事件警报示例:

无需任何额外的工具或分析,您就可以看到:

  • 哪些对象消耗的内存最多(271 个 com.example.map.impl.PartitionContainer 实例消耗了 248MB 总堆中的 173MB)
  • 这些对象的分配位置(大部分分配在 MetricManagerImpl 类中,第 304 行)
  • 当前引用这些对象的是什么(直到 GC 根的完整引用链)

有了这些信息,您就可以放大潜在的根本原因,并确保将数据结构修剪到适合您的内存池的级别。

但是,当您从内存分析或阅读 Plumbr 报告得出的结论是内存使用是合法的并且源代码中没有任何更改时,您需要让您的 JVM 有更多的 Java 堆空间才能正常运行。在这种情况下,更改您的 JVM 启动配置并添加(或增加值,如果存在)以下内容:

-Xmx1024m

上述配置将为应用程序提供 1024MB 的 Java 堆空间。您可以对 GB 使用 g 或 G,对 MB 使用 m 或 M,对 KB 使用 k 或 K。例如,以下所有内容都相当于说最大的 Java 堆空间为 1GB:

java -Xmx1073741824 com.mycompany.MyClassjava -Xmx1048576k com.mycompany.MyClassjava -Xmx1024m com.mycompany.MyClassjava -Xmx1g com.mycompany.MyClass

OOM系列之一:java.lang.OutOfMemoryError: Java堆空间问题详解相关推荐

  1. java内存溢出模拟_模拟实战排查堆内存溢出(java.lang.OutOfMemoryError: Java heap space)问题...

    前言: 模拟实战中排查堆内存溢出(java.lang.OutOfMemoryError: Java heap space)的问题. 堆内存溢出的原因:一般都是创建了大量的对象,这些对象一直被引用着,无 ...

  2. java.lang.OutOfMemoryError: Java heap space错误及...

    为什么80%的码农都做不了架构师?>>>    以下是从网上找到的关于堆空间溢出的错误解决办法: java.lang.OutOfMemoryError: Java heap spac ...

  3. java.lang.OutOfMemoryError: Java heap space的解决办法

    如果在启动过程中出现内存溢出问题,抛出类似如下异常信息: java.lang.OutOfMemoryError: Java heap space 可以尝试办法: A.修改Tomcat/bin/cata ...

  4. (转)java.lang.OutOfMemoryError: Java heap space错误及处理办法(收集整理、转)

    java.lang.OutOfMemoryError: Java heap space =================================================== 使用Ja ...

  5. Exception in thread main java.lang.OutOfMemoryError: Java heap space

    在做大批量数据测试的时候,服务端初始化出现问题 测试规模,没个站2万点量测数据,整个数据超过20万,初始化过程中对量测数据初始化,按站分别初始化,但是初始化到总数据量10万的时候就会报内存溢出错误. ...

  6. eclipse中报错:java.lang.OutOfMemoryError: Java heap space

    问题: 在eclipse中执行java程序.去重100多万的数据,报例如以下错误: java.lang.OutOfMemoryError: Java heap space 异常原因: 在JVM中假设9 ...

  7. java.lang.OutOfMemoryError: Java heap space错误及处理办法(收集整理、转)

    下面是从网上找到的关于堆空间溢出的错误解决的方法: java.lang.OutOfMemoryError: Java heap space ============================== ...

  8. java.lang.OutOfMemoryError: Java heap space 错误及解决办法

    java.lang.OutOfMemoryError: Java heap space =================================================== 使用Ja ...

  9. java.lang.OutOfMemoryError: Java heap space 解决方法

    这个问题的根源是jvm虚拟机的默认Heap大小是64M,可以通过设置其最大和最小值来实现.设置的方法主要是几个. 1.可以在windows 更改系统环境变量 加上JAVA_OPTS=-Xms64m - ...

最新文章

  1. 安卓关于fragment切换后继续运行的问题!
  2. C语言博客作业--嵌套循环
  3. 阳泉2021高考成绩查询时间段,阳泉高考时间,2021年阳泉高考具体时间科目安排
  4. hdu 4991(树状数组优化dp)
  5. git 如何取消add操作
  6. hybris backoffice和产品主数据相关的一些sample data
  7. 奥鹏20年12月作业考核(C语言专科),《C语言(专科)》20年12月作业考核【答案100分】...
  8. 选出你最喜欢的Linux操作系统吧
  9. 安装服务器系统大概多久,安装服务器系统
  10. 机器学习实战(六)AdaBoost元算法
  11. Linux学习总结(四)-两种模式修复系统,单用户,救援模式
  12. PHP设计模式——桥接模式
  13. Pytorch—时序数据的加载与简单处理
  14. 三种刷写LEDE等软路由固件的方法
  15. 工具 - 屏幕录像专家7.5注册机
  16. 分享几个实用的破解软件
  17. IOS捷径早安,创建自动化可实现自动化叫醒
  18. 跟我学AngularJs:Directive指令用法解读(上)
  19. Android开发自定义水印图片
  20. 基于java民航售票管理系统源码(java毕业设计)

热门文章

  1. 简单又有效的基本折线图制作方法
  2. 黑马程序员---Java 容器集合
  3. 在字节跳动工作是一种怎样的体验?
  4. matlab神经网络newff函数的用法
  5. python编程入门书-最适合Python初学者的6本书籍推荐「必须收藏」
  6. 基于vue编写的2048小游戏
  7. MATLAB中不用循环生成圆盘(圆形)/圆环掩膜矩阵
  8. 小程序发送模板消息form_id的获取
  9. php 获取目录分隔符,php目录分隔符DIRECTORY_SEPARATOR
  10. MySQL 架构与 SQL 执行流程