OutOfMemoryError系列(1): Java heap space - CSDN博客

文章推薦指數: 80 %
投票人數:10人

本文通过实例来分析java.lang.OutOfMemoryError: Java heap space 问题产生的原因, 以及相关的解决方案. OutOfMemoryError系列(1):Javaheapspace 铁锚 于 2017-07-2919:31:14 发布 83082 收藏 92 分类专栏: JavaGC GC性能优化 文章标签: java outofmemoryerror heap 实例 解决方案 JavaGC 同时被2个专栏收录 22篇文章 18订阅 订阅专栏 GC性能优化 23篇文章 606订阅 订阅专栏 这是本系列的第一篇文章,相关文章列表: OutOfMemoryError系列(1):JavaheapspaceOutOfMemoryError系列(2):GCoverheadlimitexceededOutOfMemoryError系列(3):PermgenspaceOutOfMemoryError系列(4):Metaspace 每个Java程序都只能使用一定量的内存,这种限制是由JVM的启动参数决定的。

而更复杂的情况在于,Java程序的内存分为两部分:堆内存(Heapspace)和永久代(PermanentGeneration,简称Permgen): 这两个区域的最大内存大小,由JVM启动参数-Xmx和-XX:MaxPermSize指定.如果没有明确指定,则根据平台类型(OS版本+JVM版本)和物理内存的大小来确定。

假如在创建新的对象时,堆内存中的空间不足以存放新创建的对象,就会引发java.lang.OutOfMemoryError:Javaheapspace错误。

不管机器上还没有空闲的物理内存,只要堆内存使用量达到最大内存限制,就会抛出java.lang.OutOfMemoryError:Javaheapspace错误。

原因分析 产生java.lang.OutOfMemoryError:Javaheapspace错误的原因,很多时候,就类似于将XXL号的对象,往S号的Javaheapspace里面塞。

其实清楚了原因,就很容易解决对不对?只要增加堆内存的大小,程序就能正常运行.另外还有一些比较复杂的情况,主要是由代码问题导致的: 超出预期的访问量/数据量。

应用系统设计时,一般是有“容量”定义的,部署这么多机器,用来处理一定量的数据/业务。

如果访问量突然飙升,超过预期的阈值,类似于时间坐标系中针尖形状的图谱,那么在峰值所在的时间段,程序很可能就会卡死、并触发java.lang.OutOfMemoryError:Javaheapspace错误。

内存泄露(Memoryleak).这也是一种经常出现的情形。

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

具体示例 一个非常简单的示例 以下代码非常简单,程序试图分配容量为2M的int数组.如果指定启动参数-Xmx12m,那么就会发生java.lang.OutOfMemoryError:Javaheapspace错误。

而只要将参数稍微修改一下,变成-Xmx13m,错误就不再发生。

publicclassOOM{ staticfinalintSIZE=2*1024*1024; publicstaticvoidmain(String[]a){ int[]i=newint[SIZE]; } } 内存泄漏示例 这个示例更真实一些。

在Java中,创建一个新对象时,例如Integernum=newInteger(5);,并不需要手动分配内存。

因为JVM自动封装并处理了内存分配.在程序执行过程中,JVM会在必要时检查内存中还有哪些对象仍在使用,而不再使用的那些对象则会被丢弃,并将其占用的内存回收和重用。

这个过程称为垃圾收集.JVM中负责垃圾回收的模块叫做垃圾收集器(GC)。

Java的自动内存管理依赖GC,GC会一遍又一遍地扫描内存区域,将不使用的对象删除.简单来说,Java中的内存泄漏,就是那些逻辑上不再使用的对象,却没有被垃圾收集程序给干掉.从而导致垃圾对象继续占用堆内存中,逐渐堆积,最后造成java.lang.OutOfMemoryError:Javaheapspace错误。

很容易写个BUG程序,来模拟内存泄漏: importjava.util.*; publicclassKeylessEntry{ staticclassKey{ Integerid; Key(Integerid){ this.id=id; } @Override publicinthashCode(){ returnid.hashCode(); } } publicstaticvoidmain(String[]args){ Mapm=newHashMap(); while(true){ for(inti=0;i<10000;i++){ if(!m.containsKey(newKey(i))){ m.put(newKey(i),"Number:"+i); } } System.out.println("m.size()="+m.size()); } } } 粗略一看,可能觉得没什么问题,因为这最多缓存10000个元素嘛!但仔细审查就会发现,Key这个类只重写了hashCode()方法,却没有重写equals()方法,于是就会一直往HashMap中添加更多的Key。

请参考:Java中hashCode与equals方法的约定及重写原则 随着时间推移,“cached”的对象会越来越多.当泄漏的对象占满了所有的堆内存,GC又清理不了,就会抛出java.lang.OutOfMemoryError:Javaheapspace错误。

解决办法很简单,在Key类中恰当地实现equals()方法即可: @Override publicbooleanequals(Objecto){ booleanresponse=false; if(oinstanceofKey){ response=(((Key)o).id).equals(this.id); } returnresponse; } 说实话,在寻找真正的内存泄漏原因时,你可能会死掉很多很多的脑细胞。

一个SpringMVC中的场景 译者曾经碰到过这样一种场景: 为了轻易地兼容从Struts2迁移到SpringMVC的代码,在Controller中直接获取request. 所以在ControllerBase类中通过ThreadLocal缓存了当前线程所持有的request对象: publicabstractclassControllerBase{ privatestaticThreadLocalrequestThreadLocal=newThreadLocal(); publicstaticHttpServletRequestgetRequest(){ returnrequestThreadLocal.get(); } publicstaticvoidsetRequest(HttpServletRequestrequest){ if(null==request){ requestThreadLocal.remove(); return; } requestThreadLocal.set(request); } } 然后在SpringMVC的拦截器(Interceptor)实现类中,在preHandle方法里,将request对象保存到ThreadLocal中: /** *登录拦截器 */ publicclassLoginCheckInterceptorimplementsHandlerInterceptor{ privateListexcludeList=newArrayList(); publicvoidsetExcludeList(ListexcludeList){ this.excludeList=excludeList; } privatebooleanvalidURI(HttpServletRequestrequest){ //如果在排除列表中 Stringuri=request.getRequestURI(); Iteratoriterator=excludeList.iterator(); while(iterator.hasNext()){ StringexURI=iterator.next(); if(null!=exURI&&uri.contains(exURI)){ returntrue; } } //可以进行登录和权限之类的判断 LoginUseruser=ControllerBase.getLoginUser(request); if(null!=user){ returntrue; } //未登录,不允许 returnfalse; } privatevoidinitRequestThreadLocal(HttpServletRequestrequest){ ControllerBase.setRequest(request); request.setAttribute("basePath",ControllerBase.basePathLessSlash(request)); } privatevoidremoveRequestThreadLocal(){ ControllerBase.setRequest(null); } @Override publicbooleanpreHandle(HttpServletRequestrequest, HttpServletResponseresponse,Objecthandler)throwsException{ initRequestThreadLocal(request); //如果不允许操作,则返回false即可 if(false==validURI(request)){ //此处抛出异常,允许进行异常统一处理 thrownewNeedLoginException(); } returntrue; } @Override publicvoidpostHandle(HttpServletRequestrequest, HttpServletResponseresponse,Objecthandler,ModelAndViewmodelAndView) throwsException{ removeRequestThreadLocal(); } @Override publicvoidafterCompletion(HttpServletRequestrequest, HttpServletResponseresponse,Objecthandler,Exceptionex) throwsException{ removeRequestThreadLocal(); } } 在postHandle和afterCompletion方法中,清理ThreadLocal中的request对象。

但在实际使用过程中,业务开发人员将一个很大的对象(如占用内存200MB左右的List)设置为request的Attributes,传递到JSP中。

JSP代码中可能发生了异常,则SpringMVC的postHandle和afterCompletion方法不会被执行。

Tomcat中的线程调度,可能会一直调度不到那个抛出了异常的线程,于是ThreadLocal一直hold住request。

随着运行时间的推移,把可用内存占满,一直在执行FullGC,系统直接卡死。

后续的修正:通过Filter,在finally语句块中清理ThreadLocal。

@WebFilter(value="/*",asyncSupported=true) publicclassClearRequestCacheFilterimplementsFilter{ @Override publicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsIOException, ServletException{ clearControllerBaseThreadLocal(); try{ chain.doFilter(request,response); }finally{ clearControllerBaseThreadLocal(); } } privatevoidclearControllerBaseThreadLocal(){ ControllerBase.setRequest(null); } @Override publicvoidinit(FilterConfigfilterConfig)throwsServletException{} @Override publicvoiddestroy(){} } 教训是:可以使用ThreadLocal,但必须有受控制的释放措施、一般就是try-finally的代码形式。

说明:SpringMVC的Controller中,其实可以通过@Autowired注入request,实际注入的是一个HttpServletRequestWrapper对象,执行时也是通过ThreadLocal机制调用当前的request。

常规方式:直接在controller方法中接收request参数即可。

解决方案 如果设置的最大内存不满足程序的正常运行,只需要增大堆内存即可,配置参数可以参考下文。

但很多情况下,增加堆内存空间并不能解决问题。

比如存在内存泄漏,增加堆内存只会推迟java.lang.OutOfMemoryError:Javaheapspace错误的触发时间。

当然,增大堆内存,可能会增加GCpauses的时间,从而影响程序的吞吐量或延迟。

要从根本上解决问题,则需要排查分配内存的代码.简单来说,需要解决这些问题: 哪类对象占用了最多内存?这些对象是在哪部分代码中分配的。

要搞清这一点,可能需要好几天时间。

下面是大致的流程: 获得在生产服务器上执行堆转储(heapdump)的权限。

“转储”(Dump)是堆内存的快照,稍后可以用于内存分析.这些快照中可能含有机密信息,例如密码、信用卡账号等,所以有时候,由于企业的安全限制,要获得生产环境的堆转储并不容易。

在适当的时间执行堆转储。

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

用另一台机器来加载Dump文件。

一般来说,如果出问题的JVM内存是8GB,那么分析HeapDump的机器内存需要大于8GB.打开转储分析软件(我们推荐EclipseMAT,当然你也可以使用其他工具)。

检测快照中占用内存最大的GCroots。

详情请参考:SolvingOutOfMemoryError(part6)–Dumpisnotawaste。

这对新手来说可能有点困难,但这也会加深你对堆内存结构以及navigation机制的理解。

接下来,找出可能会分配大量对象的代码.如果对整个系统非常熟悉,可能很快就能定位了。

打个广告,我们推荐Plumbr,theonlyJavamonitoringsolutionwithautomaticrootcausedetection。

Plumbr能捕获所有的java.lang.OutOfMemoryError,并找出其他的性能问题,例如最消耗内存的数据结构等等。

Plumbr在后台负责收集数据——包括堆内存使用情况(只统计对象分布图,不涉及实际数据),以及在堆转储中不容易发现的各种问题。

如果发生java.lang.OutOfMemoryError,还能在不停机的情况下,做必要的数据处理.下面是Plumbr对一个java.lang.OutOfMemoryError的提醒: 强大吧,不需要其他工具和分析,就能直接看到: 哪类对象占用了最多的内存(此处是271个com.example.map.impl.PartitionContainer实例,消耗了173MB内存,而堆内存只有248MB)这些对象在何处创建(大部分是在MetricManagerImpl类中,第304行处)当前是谁在引用这些对象(从GCroot开始的完整引用链) 得知这些信息,就可以定位到问题的根源,例如是当地精简数据结构/模型,只占用必要的内存即可。

当然,根据内存分析的结果,以及Plumbr生成的报告,如果发现对象占用的内存很合理,也不需要修改源代码的话,那就增大堆内存吧。

在这种情况下,修改JVM启动参数,(按比例)增加下面的值: -Xmx1024m 这里配置Java堆内存最大为1024MB。

可以使用g/G表示GB,m/M代表MB,k/K表示KB. 下面的这些形式都是等价的,设置Java堆的最大空间为1GB: #等价形式:最大1GB内存 java-Xmx1073741824com.mycompany.MyClass java-Xmx1048576kcom.mycompany.MyClass java-Xmx1024mcom.mycompany.MyClass java-Xmx1gcom.mycompany.MyClass 原文链接:https://plumbr.eu/outofmemoryerror/java-heap-space 翻译日期:2017年7月29日 翻译人员:铁锚:http://blog.csdn.net/renfufei 铁锚 关注 关注 35 点赞 踩 16 评论 92 收藏 扫一扫,分享内容 点击复制链接 专栏目录 java.lang.OutOfMemoryError:Javaheapspace解决方法 4星·用户满意度95% 10-18 java.lang.OutOfMemoryError:Javaheapspace解决方法 java.lang.OutOfMemoryError错误整理及解决办法 09-01 主要介绍了java.lang.OutOfMemoryError错误整理及解决办法的相关资料,需要的朋友可以参考下 评论 16 您还未登录,请先 登录 后发表或查看评论 Java中OutOfMemoryError(内存溢出)的三种情况及解决办法 最新发布 m0_67390963的博客 05-28 620 Java中OutOfMemoryError(内存溢出)的三种情况及解决办法 相信有一定java开发经验的人或多或少都会遇到OutOfMemoryError的问题,这个问题曾困扰了我很长时间,随着解决各类问题经验的积累以及对问题根源的探索,终于有了一个比较深入的认识。

在解决java内存溢出问题之前,需要对jvm(java虚拟机)的内存管理有一定的认识。

jvm管理的内存大致包括三种不同类型的内存区域:PermanentGenerationspace(永久保存区域)、Heapspace(堆区域)、Java java.lang.OutOfMemoryError及解决方法 az44yao的专栏 04-22 5008 主要有3种比较常见的OutOfMemoryError: Java.lang.OutOfMemoryError:Javaheapspace java.lang.OutOfMemoryError:PermGenspace java.lang.OutOfMemoryError:GCoverheadlimitexceeded 1.java.lang.OutOfMemoryErr... java.lang.OutOfMemoryError:Javaheapspace解决方法 awhip9的博客 06-30 3万+ //首先检查程序有没有限入死循环 这个问题主要还是由这个问题 Java.lang.OutOfMemoryError: Java heap space引起的。

第一次出现这样的的问题以后,引发了其他的问题。

在网上一查可能是JAVA的堆栈设置太小的原因。

跟据网上的答案大致有这两种解决方法: 1、设置环境变量 解决方法:手动设置Heapsize 修改TOMCAT_HOME/bin/ca 记一次解决OutOfMemoryError:Javaheapspace详细过程与解决思路(jvisualvm解决问题案例详细分析) lyflyyvip的博客 09-02 7万+ 喧哗的夜满地银光。

望向窗外,星的眨眼频率格外的高,低眼看泛着油光的键盘,心中的寂寞。





滴滴,靠着每天【ctrl+alt+w】几千+的惯性,打开最【嘿嘿嘿】的聊天软件,心中不免惆怅,已过午时三刻,还tm不下班。

惆惆啥?油光的脸瞬间露出一缕微笑,惺忪的眼也充满了血丝。

那么:问题来了,一点自己写的代码的信息没有,怎么找 错误信息是我朋友发给我的截图,我并没有他的代... Idea运行项目报错:java.lang.OutOfMemoryError:Javaheapspace解决方法 热门推荐 一只小码渣的博客 10-16 17万+ 问题描述 使用idea运行代码量比较多的项目时,会报错:java.lang.OutOfMemoryError:Javaheapspace 问题处理 这个显而易见时堆内存溢出,首先想到的时tomcat的内存分配太小了,调整Idea的内存分配: Help–>EditCustomVMOptions–> 将配置改为以下内容: -server -Xms512m#JVM启动时分配的内存 -Xmx1024m#JVM运行时内存 -XX:ReservedCodeCacheSize=300m -X OutOfMemoryError常见类型及解决方案 weixin_42325823的博客 06-30 623 -Xms:javaHeap初始大小,默认是物理内存的1/64。

-Xmx:javaHeap最大值,不可超过物理内存。

-Xmn:younggeneration的heap大小,一般设置为Xmx的3、4分之一。

增大年轻代后,将会减小年老代大小,可以根据监控合理设置。

-Xss:每个线程的Stack大小,而最佳值应该是128K,默认值好像是512k。

-XX:PermSize:设定内存的永久保存区初始大小,缺省值为64M。

-XX:MaxPermSize:设定内存的永久保存区最大大小,缺省值为64M。

OutOfMemoryError(内存溢出)解决办法 weixin_30668887的博客 12-18 198 第一种OutOfMemoryError:PermGenspace 发生这种问题的原意是程序中使用了大量的jar或class,使java虚拟机装载类的空间不够,与PermanentGenerationspace有关。

解决这类问题有以下两种办法: 增加java虚拟机中的XX:PermSize和XX:MaxPermSize参数的大小,其中XX:PermSize是初始永久保存区域大小,XX... 出现OutOfMemoryError时,通用解决思路 weixin_39374471的博客 03-24 796 说一下,当我们的项目出现OutOfMemoryError时,一些简单的解决思路: **1.**当java堆出现OutOfMemoryError时可Linux中用jmap-dump:命令查看对象大小,当然一般都是用工具,比如常用的JProfiler查看分析Dump文件,查看都有哪些对象,那些对象占用空间较多,确定到底是内存泄漏(不在用到的对象还在堆里存活),一般引起泄漏的对象包括:St... tomcat出现OutOfMemoryError的解决方法 05-14 tomcat出现OutOfMemoryError的解决方法 常见的OutOfMemoryError原因及解决方案 wan3964366的博客 08-05 9423 常见的OutOfMemoryError原因及解决方案 常见的OutOfMemoryError原因及解决方案 当JVM内存严重不足时,就会抛出java.lang.OutOfMemoryError错误。

本文总结了常见的OOM原因及其解决方法。

如有遗漏或错误,欢迎补充指正。

1、Javaheapspace 当堆内存(HeapSpace)没有足够空间存放新创建的对象时,就会抛出java.lang.OutOfMemoryError:Javaheapspace错误(根据实际生产经验,可以对程序 java.lang.OutOfMemoryError:Javaheapspace 男人要霸气的博客 09-14 3254 先研究java为什么会报java.lang.OutOfMemoryError:Javaheapspace错误呢?是由谁抛出的呢? Java.lang.OutOfMemoryError:javaheapspace:说明java虚拟机内存不够。

示例: publicstaticvoidmain(String[]args){ Stringstr="H... javapermspace_java.lang.OutOfMemoryError:PermGenspace及其解决方法 weixin_33837516的博客 02-22 96 PermGenspace的全称是PermanentGenerationspace,是指内存的永久保存区域OutOfMemoryError:PermGenspace从表面上看就是内存益出,解决方法也一定是加大内存。

说说为什么会内存益出:这一部分用于存放Class和Meta的信息,Class在被Load的时候被放入PermGenspace区域,它和和存放Instance的Heap区域不同,... 为什么会产生java.lang.OutOfMemoryError:Javaheapspace错误以及如何解决? chajinglong的专栏 09-23 3608 关于java.lang.OutOfMemoryError:Javaheapspace错误,遇到的程序员可能不是很多,但是当你真的遇到的时候,你就会发现我的这篇文章对你的帮助非常的大! 引发java.lang.OutOfMemoryError:Javaheapspace错误的主要原因就是在创建新的对象时,堆内存中的空间不足以存放新创建的对象时发生! 所以说,当有人问你:在Java中创建一个对象(new一个正常的类)会不会发生异常?你应该这样回答:当堆内存中的空间不足时,可能会发生 “相关推荐”对你有帮助么? 非常没帮助 没帮助 一般 有帮助 非常有帮助 提交 ©️2022CSDN 皮肤主题:编程工作室 设计师:CSDN官方博客 返回首页 铁锚 CSDN认证博客专家 CSDN认证企业博客 码龄12年 暂无认证 119 原创 9530 周排名 394 总排名 641万+ 访问 等级 2万+ 积分 3322 粉丝 2060 获赞 877 评论 2594 收藏 私信 关注 热门文章 IntelliJIDEA设置代码提示或自动补全的快捷键 320920 Windows下安装并设置Redis 317046 创建GitHub技术博客全攻略 252091 JavaLambda表达式入门 228429 在JS数组指定位置插入元素 222618 分类专栏 GC性能优化 23篇 HTML5_前端 51篇 面试笔试 8篇 Java基础 51篇 JS笔记 30篇 想法 7篇 Android 5篇 算法 4篇 MariaDB 21篇 图说Java 10篇 操作系统 15篇 Chrome浏览器开发调试系列 4篇 AngularJS 5篇 Spring 11篇 Polymer 8篇 Redis 7篇 GitHub 8篇 JavaGC 22篇 Java周边 17篇 JavaEE基础系列 7篇 WebRTC基础实践 10篇 最新评论 WebRTC基础实践-4.获取摄像头的视频流 weixin_45049417: 大佬,我现在实现了音频通话,要做个免提功能该怎么操作。

OOM终结者参数调优 菜菜的大数据开发之路: 程序有问题时不要担心。

如果所有东西都没问题,你就失业了。

(软件工程的Mosher定律) G1垃圾收集器入门 铁锚: GC性能调优,官方文档链接: [code=java] https://docs.oracle.com/javase/10/gctuning/ [/code] SpringMVC中JSP页面不显示EL表达式的原因 披甲征战南北: 哥你真牛逼解决了 7.GC调优(实战篇)-GC参考手册 qq_32178709: 流弊 您愿意向朋友推荐“博客详情页”吗? 强烈不推荐 不推荐 一般般 推荐 强烈推荐 提交 最新文章 业务指标采集影响系统性能问题排查 不需要再手工指定JVM启动参数-XX:+UseCompressedOops 一些好用的alias命令 2022年2篇 2021年5篇 2020年11篇 2019年5篇 2018年19篇 2017年34篇 2016年27篇 2015年28篇 2014年91篇 2013年82篇 2012年2篇 目录 目录 分类专栏 GC性能优化 23篇 HTML5_前端 51篇 面试笔试 8篇 Java基础 51篇 JS笔记 30篇 想法 7篇 Android 5篇 算法 4篇 MariaDB 21篇 图说Java 10篇 操作系统 15篇 Chrome浏览器开发调试系列 4篇 AngularJS 5篇 Spring 11篇 Polymer 8篇 Redis 7篇 GitHub 8篇 JavaGC 22篇 Java周边 17篇 JavaEE基础系列 7篇 WebRTC基础实践 10篇 目录 评论 16 被折叠的  条评论 为什么被折叠? 到【灌水乐园】发言 查看更多评论 实付元 使用余额支付 点击重新获取 扫码支付 钱包余额 0 抵扣说明: 1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。

2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值



請為這篇文章評分?