解决OOM问题的一个初步思路

首先第一个问题,假设发生OOM了,必然说明系统中某个区域的对象太多了,塞满了那个区域,而且一定是无法回收掉那些对象,最终才会导致内存溢出的。

既然是这个思路,要解决OOM的话,首先就得知道到底是什么对象太多了最终导致OOM的?

所以你想知道什么对象太多导致OOM的,就必须得有一份JVM发生OOM时的dump内存快照

只要有了那个dump内存快照,你就可以用之前介绍过的MAT之类的工具瞬间分析得到什么对象太多了。

那么现在一个关键问题来了,到底怎么做才可以在JVM内存溢出的时候自动dump出来一份内存快照呢?

在OOM的时候自动dump内存快照

看到这里,大家必须得对一个事情有个概念,大家可以思考一下,假设JVM发生OOM了,你觉得JVM是完全来不及处理然后突然进程就没了吗?也就是JVM是看起来非常突然的自己无法控制的就挂掉了吗?

其实不是的,只要之前对JVM OOM的各种情况原理有一定的了解,就会知道JVM本身在发生OOM之前都会尽可能的去进行GC腾出来一些内存空间

如果GC后还是没有空间,放不下对象, 才会触发内存溢出的。

所以JVM自己对OOM情况的发生是完全有把控权的,他知道什么时候会触发OOM,也是他自己感觉不行的时候才会去触发的

所以OOM的发生并不是大家想的那样,突然之间内存太多了,JVM自己都没反应过来就直接崩溃了,并非如此。

因此JVM如果知道要发生OOM了,此时完全可以让他做点事情

我们可以让他在OOM时dump一份内存快照,事后我们只要分析这个内存快照,一下就可以知道是哪些可恶的对象占用了所有的内存,并且还无法释放。

此时你就需要在JVM的启动参数中加入如下的一些参数:

-XX:+HeapDumpOnOutOfMemoryError

-XX:HeapDumpPath=/usr/local/app/oom

第一个参数意思是在OOM的时候自动dump内存快照出来,第二个参数是说把内存快照放到哪儿去

只要你加入了这两个参数,在JVM OOM崩溃的时候,无论你是立马主动收到一个报警,还是被动让客服通知了你,立马就可以去找OOM时候的内存快照了。

迄今为止我们可以得出的一份JVM参数模板

在学习完这篇文章之后,我们最常用的一些JVM参数已经全部学习完了,而且可以总结一份JVM参数模板出来供大家进行参考,大家未来对自己的系统只要根据自己的情况去调整就可以了:

-Xms4096M -Xmx4096M -Xmn3072M -Xss1M -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M

-XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFaction=92

-XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=0

-XX:+CMSParallelInitialMarkEnabled -XX:+CMSScavengeBeforeRemark

-XX:+DisableExplicitGC -XX:+PrintGCDetails -Xloggc:gc.log

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/local/app/oom

这份JVM参数模板基本上涵盖了所有你需要的一些参数

首先是各个内存区域的大小分配,这个是需要你精心调优的

其次是两种垃圾回收器的指定,接着是一些常规性的CMS垃圾回收的参数,可以帮助优化偶尔发生的Full GC性能。

最重要的就是平时要打印出来GC日志,GC日志可以配合你用jstat工具分析GC频率和性能的时候用,jstat可以分析出来GC的频率,但是对每次具体的GC情况,可以结合GC日志来看。

还有就是在OOM的时候需要自动dump内存快照,这样即使突然发生OOM,你只要得知了这个事,立马就可以去分析内存快照了。

同时结合GC日志,让大家更加清晰的理解每次发生内存溢出时候的具体过程和原理,以及解决内存溢出的排查过程。

java 内存溢出时打印_如何在JVM内存溢出的时候自动dump内存快照相关推荐

  1. java 线程中创建线程_如何在Java 8中创建线程安全的ConcurrentHashSet?

    java 线程中创建线程 在JDK 8之前,还没有办法在Java中创建大型的线程安全的ConcurrentHashSet. java.util.concurrent包甚至没有一个名为Concurren ...

  2. java类添加单元测试代码_如何在java中单元测试时跳过一段代码

    如果问题确实是: 如何在Java 然后我给出的答案同意单元测试时,我跳过一段代码.依赖注入,嘲讽框架绝对是真正的单元测试的正确途径. 但是,如果问题是: 使用JUnit(或其他单元测试框架) 然后我想 ...

  3. Java枚举的打印_如何在java中打印所有枚举值?

    首先,我会重构您的枚举在构造函数参数中传递字符串表示形式.该代码位于底部. 现在,打印你只是使用的东西像所有枚举值: // Note: enum name changed to comply with ...

  4. java中print换行符_如何在java中打印带换行符的字符串

    我需要使用 java打印一个字符串,所以我喜欢以下解决方案经过google搜索了很多.我做了一些更改来打印字符串而不显示打印对话框.我的问题是虽然这个方法正确地打印了字符串,但它不会像我定义的那样破坏 ...

  5. stack java 打印_如何在java中打印完整的stacktrace

    问题很简单,我想读一个异常,我捕获的完整stacktrace

  6. java 合并两个列表_如何在Java中合并两个列表?

    java 合并两个列表 Merging two lists in Java is often a useful operation. These lists can be ArrayLists or ...

  7. visual studio内存溢出检测工具_详解JVM内存管理与垃圾回收机制2 何为垃圾

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 随着编程语言的发展,GC的功能不断增强,性能也不断提高,作为语言背 ...

  8. java数组删除数组元素_如何在Java中删除数组元素

    java数组删除数组元素 When we create an array in Java, we specify its data type and size. This is used by JVM ...

  9. 在java读字符串入文件_如何在java中将文件读入字符串?

    我已经将文件读入String. 该文件包含各种名称,每行一个名称. 现在的问题是我想在String数组中使用这些名称. 为此我写了以下代码: String [] names = fileString. ...

最新文章

  1. Linux系统的大小端模式
  2. react的导出是怎么实现的_22 个让 React 开发更高效更有趣的工具
  3. UA MATH524 复变函数14 Laurent级数
  4. 图形处理(五)基于旋转不变量的网格变形-Siggraph 2007
  5. 天津大学计算机考研真题,天津大学计算机科学与技术考研真题
  6. jQuery EasyUI Datagrid组件的完整的基础DOM结构
  7. ubuntu 配置静态IP及DNS
  8. a 中调用js的几种方法
  9. Python异步非阻塞IO多路复用Select/Poll/Epoll使用
  10. C语言课后习题(19)
  11. @Scheduled不执行的原因
  12. LeetCode_88、合并两个数组(python)
  13. python 摄像头采集_Python+OpenCV采集本地摄像头的视频
  14. 【HTML+CSS】静态网页设计期末大作业——我的家乡无锡印象
  15. xp启用计算机共享打印机,xp系统怎么共享打印机|win7怎么连接xp共享打印机
  16. 一篇关于蜿蜒型河流的介绍
  17. 什么是集合竞价和连续竞价
  18. 生物信息学(4)——多序列比对之CLUSTAL算法详解及C++实现
  19. ARM基础(1):Cortex-M3的核心寄存器和特殊寄存器
  20. 电力电子技术第二章总结

热门文章

  1. docker构建hadoop镜像、docker-compose启动hdfs
  2. MathML: 描述数学表达式
  3. 关闭中国电信的绿色上网服务
  4. python用turtle画月亮_使用Python的turtle画小猪乔治和哆啦 A 梦
  5. David想对asc码进行位运算
  6. plotly画图(包含x轴设置marker类型设置)
  7. Configuration 'compile' is obsolete and has been replaced with 'implementati解决方案
  8. 各大语言之父,你认识几个?Python之父,头发最茂盛?
  9. LeetCode题解 - 动态规划-股票买卖
  10. Android-少不了的 AAR 文件常识,最好知道的注意事项