为什么会产生 java.lang.OutOfMemoryError: Java heap space 错误以及如何解决?

JAVA herman 6425浏览
公告:“业余草”微信公众号提供免费CSDN下载服务(只下Java资源),关注业余草微信公众号,添加作者微信:xttblog,发送下载链接帮助你免费下载!
本博客日IP超过1800,PV 2600 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog,之前的微信号好友位已满,备注:返现
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序
视频教程免费领

关于 java.lang.OutOfMemoryError: Java heap space 错误,遇到的程序员可能不是很多,但是当你真的遇到的时候,你就会发现我的这篇文章对你的帮助非常的大!

引发 java.lang.OutOfMemoryError: Java heap space 错误的主要原因就是在创建新的对象时, 堆内存中的空间不足以存放新创建的对象时发生!

所以说,当有人问你:在 Java 中创建一个对象(new 一个正常的类)会不会发生异常?你应该这样回答:当堆内存中的空间不足时,可能会发生 java.lang.OutOfMemoryError: Java heap space 错误!

知道了 java.lang.OutOfMemoryError: Java heap space 错误的发生时机。我们来看看 Java 中为什么有这个异常或错误产生!

一般来说每个 Java 程序都只能使用一定量的内存,这种限制是由 JVM 的启动参数决定的。而更复杂的情况在于, Java 程序的内存主要分为两部分: 堆内存(Heap space)和 永久代(Permanent Generation,简称 Permgen):

堆内存和永久代

这两个区域的最大内存大小,由 JVM 启动参数 -Xmx 和 -XX:MaxPermSize 指定。如果没有明确指定,则根据平台类型(OS版本+ JVM版本)和物理内存的大小来确定。

就算机器上还存在空闲的物理内存,但只要堆内存使用量达到最大内存限制(注意,在 JVM 中如果 98% 的时间是用于 GC 且可用的 Heap size 不足 2% 的时候将抛出此异常信息),就会抛出 java.lang.OutOfMemoryError: Java heap space 错误。

产生 java.lang.OutOfMemoryError: Java heap space 错误的原因,通俗的讲就是一个人只能吃一碗米饭,吃完一碗后,你又给他乘了一碗,他说吃不下去了,吃饱了!

明白了这个原因,我们来看怎么解决它!

因为你现在饭做多了,所以让别人再吃一碗,别人也吃不下。所以,解决办法就有两种,一种就是你下次少做点饭,就只在做饭的时候就进行控制;还有一种就是一次别吃完,让它饿一下了再吃!

反映到 Java 应用程序上就是,你在程序启动的时候,把堆内存设置大一点,当然是不能超过物理内存大小的。还有一种办法就是,一些超大的,超预期的对象或数据分批来处理。例如,我定义了一个长度为 10 的数组,你就不能放置 20 个元素。你可以先放 10 个,等这 10 个用完后,再放 10 个。

另外就是,你的程序本身就有内存泄露的情况。

比如,代码中的某些错误,导致系统占用的内存越来越多。如果某个方法/某段代码存在内存泄漏的,每执行一次,就会(有更多的垃圾对象)占用更多的内存。随着运行时间的推移,泄漏的对象耗光了堆中的所有内存,那么在新创建对象等情况下就会爆发 java.lang.OutOfMemoryError: Java heap space 错误。

在启动的时候,把堆内存设置大一点的操作很简单,比如下面的配置:

JAVA_OPTS="-server -Xms800m -Xmx800m -XX:PermSize=64M -XX:MaxNewSize=256m -XX:MaxPermSize=128m -Djava.awt.headless=true "

或者也可以在 Tomcat 的 TOMCAT_HOME/bin/catalina.bat 中添加下面这句话:

set JAVA_OPTS= -Xmx1024M -Xms512M -XX:MaxPermSize=256m

除此之外,也可以在 Idea 或 Eclipse 的 Optional Java VM arguments中添加:

-Xmx1024M -Xms512M -XX:MaxPermSize=256m

如果是 SpringBoot 项目,直接执行 jar 文件,可以这样做:

java -jar -Xms258m -Xmx258m -XX:PermSize=512M -XX:MaxPermSize=512m xttblog.jar --spring.profiles.active=prod --server.port=80

上面这些设置虽然简单,但就是怕有些时候,问题的根本原因是你的程序存在内存泄露的情况。

这个时候,你扩大堆内存,只能延缓  java.lang.OutOfMemoryError: Java heap space 错误的触发时间。

所以,产生  java.lang.OutOfMemoryError: Java heap space 错误的时候,我建议你按照下面的步骤检查一边你的应用程序!

  • 获得在生产服务器上执行堆转储(heap dump)的权限。“转储”(Dump)是堆内存的快照,稍后可以用于内存分析。这些快照中可能含有机密信息,例如密码等。所以有时候,由于企业的安全限制,要获得生产环境的堆转储并非易事。

  • 在适当的时间执行堆转储。一般来说,内存分析需要比对多个堆转储文件,假如获取的时机不对,那就可能是一个“废”的快照。另外,每次执行堆转储,都会对JVM进行“冻结”,所以生产环境中,也不能执行太多的Dump操作,否则系统缓慢或者卡死,你的麻烦就大了。

  • 然后用另一台机器来加载Dump文件。一般来说,如果出问题的JVM内存是8GB,那么分析 Heap Dump 的机器内存需要大于 8GB。打开转储分析软件(推荐Eclipse MAT,当然你也可以使用其他工具)。

  • 检测快照中占用内存最大的 GC roots(具体怎么做,我后面会抽时间写文章来做教程)。这对新手或没分析过的程序员来说可能有点困难,但这也会加深你对堆内存结构以及 navigation 机制的理解。

  • 最后就可以找出可能会分配大量对象的代码。如果对整个系统非常熟悉,那么找到的可能就会更快。

说了这么多,其实最重要的还是要加强自己的编码能力和良好的编码习惯!更多关于 JVM 的学习内容,我后面会一篇一篇的写,希望能够帮助到大家,并能得到大家的支持!

参考资料

业余草公众号

最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加QQ1群:135430763(2000人群已满),QQ2群:454796847(已满),QQ3群:187424846(已满)。QQ群进群密码:xttblog,想加微信群的朋友,之前的微信号好友已满,请加博主新的微信号:xttblog,备注:“xttblog”,添加博主微信拉你进群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作可添加助理微信进行沟通!

本文原文出处:业余草: » 为什么会产生 java.lang.OutOfMemoryError: Java heap space 错误以及如何解决?