前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >从main方法分析内存溢出

从main方法分析内存溢出

作者头像
Mshu
发布2020-06-04 15:26:36
7970
发布2020-06-04 15:26:36
举报
文章被收录于专栏:咸鱼不闲咸鱼不闲

内存溢出OutOfMemoryError不常遇到,起码没有姨妈空指针异常(NullPointerException)来的那么频繁。 现在就用最简单的main方法复现堆内存溢出并做分析。

概念先行

JVM内存模型(JMM): 堆,方法区,本地方法栈,虚拟机栈,程序计数器 (后面三个线程共享栈和堆: 栈是运行空间,堆是存储空间,类似于我小米手机的运行内存(RAM)8G和存储空间(ROM)128G。 java中基本类型和堆对象的引用存在栈中。 堆: 堆在JVM中占据了很大的空间,用来存放实例对象,等会儿我们就拿它下手! 堆:我当时害怕急了。 堆内存分为年轻代和老年代,java8之后没有了永久代。(往细了说年轻代还有伊甸园(eden)和两个幸存区(from、to)) 当java对象在年轻代存活一段时间经历过N次回收没有被回收掉后(N还可以自己设置),就会进入老年代,在老年代中又经历回收后积累的没有被回收的对象超负荷后就会抛出内存溢出的异常。

jvm.gif
jvm.gif

图做的有点粗糙,还请见谅!

我把堆内存设置小一点先。 在idea的配置 (VM options)加上启动参数 -Xms10m -Xmx20m。 运行以下代码,不断的生成People对象并放入集合中防止被回收。

代码语言:javascript
复制
public static void main(String[] args) {
    List<People> peoples = new ArrayList<>();
    int i = 0;
    while (true) {
        People abc = new People();
        i++;
        peoples.add(abc);
        System.out.println(abc.toString() + i);
    }
}

结果在生成540217个对象的时候抛出了内存溢出的异常。

代码语言:javascript
复制
......
People{name='null', sex='null'}540216
People{name='null', sex='null'}540217
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:3210)
    at java.util.Arrays.copyOf(Arrays.java:3181)
    at java.util.ArrayList.grow(ArrayList.java:265)
    at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:239)
    at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:231)
    at java.util.ArrayList.add(ArrayList.java:462)
    at com.example.demo.DemoMain.main(DemoMain.java:17)

开启GC日志

添加启动参数,不同的参数打印不同格式的日志。

参数

说明

-XX:-PrintGC

开启GC日志

-XX:-PrintGCDetails

打印详细信息

-XX:+PrintGCDateStamps

打印时间

-Xloggc:./gclogs.log

GC日志的生成路径和日志名称

加上后看到的GC日志如下,太多了,我截取了后半段,可以看到短期内GC之后都是Full GC, 应该是老年代满了,触发Full GC但是还是有大量的对象不能被回收,最后抛出OOM的异常。 年轻代满了会触发GC,也叫Minor GC,老年代满了会触发Full GC,CPU空闲时也会回收垃圾, JVM调优的目的就是减少GC的频率和Full GC的次数。

代码语言:javascript
复制
2020-06-02T22:30:54.038+0800: 4.966: [GC (Allocation Failure)  12088K->7608K(15872K), 0.0046395 secs]
2020-06-02T22:30:54.151+0800: 5.079: [GC (Allocation Failure)  12216K->7800K(15872K), 0.0055183 secs]
2020-06-02T22:30:54.229+0800: 5.158: [GC (Allocation Failure)  12408K->9383K(15872K), 0.0062808 secs]
2020-06-02T22:30:54.347+0800: 5.275: [GC (Allocation Failure)  13991K->9551K(15872K), 0.0045744 secs]
2020-06-02T22:30:54.467+0800: 5.394: [GC (Allocation Failure)  14159K->9751K(15872K), 0.0054287 secs]
2020-06-02T22:30:54.472+0800: 5.400: [Full GC (Ergonomics)  9751K->8508K(19456K), 0.1291069 secs]
2020-06-02T22:30:54.714+0800: 5.642: [GC (Allocation Failure)  13116K->8796K(19456K), 0.0035147 secs]
2020-06-02T22:30:54.826+0800: 5.754: [GC (Allocation Failure)  13404K->8988K(19456K), 0.0054200 secs]
2020-06-02T22:30:54.941+0800: 5.869: [GC (Allocation Failure)  13596K->9084K(19456K), 0.0070004 secs]
2020-06-02T22:30:55.076+0800: 6.005: [GC (Allocation Failure)  13692K->9340K(19456K), 0.0082953 secs]
2020-06-02T22:30:55.206+0800: 6.134: [GC (Allocation Failure)  13948K->9468K(18432K), 0.0099645 secs]
2020-06-02T22:30:55.311+0800: 6.240: [GC (Allocation Failure)  13052K->9604K(18944K), 0.0110139 secs]
2020-06-02T22:30:55.404+0800: 6.332: [GC (Allocation Failure)  13188K->9780K(18944K), 0.0114867 secs]
2020-06-02T22:30:55.508+0800: 6.436: [GC (Allocation Failure)  13364K->9988K(18944K), 0.0095337 secs]
2020-06-02T22:30:55.600+0800: 6.528: [GC (Allocation Failure)  13572K->10052K(18944K), 0.0077667 secs]
2020-06-02T22:30:55.697+0800: 6.625: [GC (Allocation Failure)  13636K->10308K(18944K), 0.0076699 secs]
2020-06-02T22:30:55.789+0800: 6.717: [GC (Allocation Failure)  13892K->10460K(18944K), 0.0044046 secs]
2020-06-02T22:30:55.876+0800: 6.804: [GC (Allocation Failure)  14044K->10580K(17920K), 0.0046781 secs]
2020-06-02T22:30:55.965+0800: 6.892: [GC (Allocation Failure)  14164K->10764K(18432K), 0.0047827 secs]
2020-06-02T22:30:56.057+0800: 6.985: [GC (Allocation Failure)  14348K->10892K(18432K), 0.0050403 secs]
2020-06-02T22:30:56.171+0800: 7.100: [GC (Allocation Failure)  14476K->11036K(18432K), 0.0052502 secs]
2020-06-02T22:30:56.283+0800: 7.211: [GC (Allocation Failure)  15132K->11188K(18944K), 0.0052689 secs]
2020-06-02T22:30:56.340+0800: 7.267: [GC (Allocation Failure)  15284K->13394K(19456K), 0.0086552 secs]
2020-06-02T22:30:56.348+0800: 7.276: [Full GC (Ergonomics)  13394K->11645K(19456K), 0.2421109 secs]
2020-06-02T22:30:56.703+0800: 7.631: [GC (Allocation Failure)  16253K->11965K(19456K), 0.0045707 secs]
2020-06-02T22:30:56.821+0800: 7.749: [GC (Allocation Failure)  16573K->12125K(19456K), 0.0061328 secs]
2020-06-02T22:30:56.943+0800: 7.871: [GC (Allocation Failure)  16733K->12253K(19456K), 0.0067886 secs]
2020-06-02T22:30:57.066+0800: 7.994: [GC (Allocation Failure)  16861K->12509K(19456K), 0.0097933 secs]
2020-06-02T22:30:57.192+0800: 8.121: [GC (Allocation Failure)  17117K->12677K(19456K), 0.0115250 secs]
2020-06-02T22:30:57.312+0800: 8.241: [GC (Allocation Failure)  17285K->12789K(18432K), 0.0135347 secs]
2020-06-02T22:30:57.416+0800: 8.344: [GC (Allocation Failure)  16373K->12957K(18944K), 0.0105043 secs]
2020-06-02T22:30:57.516+0800: 8.445: [GC (Allocation Failure)  16541K->13093K(18944K), 0.0103981 secs]
2020-06-02T22:30:57.620+0800: 8.548: [GC (Allocation Failure)  16677K->13237K(18944K), 0.0098493 secs]
2020-06-02T22:30:57.729+0800: 8.657: [GC (Allocation Failure)  16821K->13421K(18944K), 0.0087252 secs]
2020-06-02T22:30:57.738+0800: 8.666: [Full GC (Ergonomics)  13421K->13218K(18944K), 0.1904231 secs]
2020-06-02T22:30:58.021+0800: 8.949: [Full GC (Ergonomics)  16802K->13300K(18944K), 0.2117216 secs]
2020-06-02T22:30:58.335+0800: 9.264: [Full GC (Ergonomics)  16884K->13435K(18944K), 0.1494933 secs]
2020-06-02T22:30:58.606+0800: 9.533: [Full GC (Ergonomics)  17019K->13569K(18944K), 0.1366324 secs]
2020-06-02T22:30:58.838+0800: 9.766: [Full GC (Ergonomics)  17153K->13703K(18944K), 0.1436044 secs]
2020-06-02T22:30:59.069+0800: 9.998: [Full GC (Ergonomics)  17287K->13837K(18944K), 0.1610447 secs]
2020-06-02T22:30:59.318+0800: 10.246: [Full GC (Ergonomics)  17402K->13971K(18944K), 0.1682002 secs]
2020-06-02T22:30:59.592+0800: 10.520: [Full GC (Ergonomics)  17402K->14099K(18944K), 0.1644734 secs]
2020-06-02T22:30:59.858+0800: 10.787: [Full GC (Ergonomics)  17402K->14223K(18944K), 0.2900750 secs]
2020-06-02T22:31:00.248+0800: 11.176: [Full GC (Ergonomics)  17402K->14342K(18944K), 0.1845255 secs]
2020-06-02T22:31:00.532+0800: 11.461: [Full GC (Ergonomics)  17402K->14457K(18944K), 0.1687967 secs]
2020-06-02T22:31:00.774+0800: 11.702: [Full GC (Ergonomics)  17402K->14567K(18944K), 0.2179055 secs]
2020-06-02T22:31:01.070+0800: 11.998: [Full GC (Ergonomics)  17402K->14674K(18944K), 0.2099567 secs]
2020-06-02T22:31:01.376+0800: 12.304: [Full GC (Ergonomics)  17402K->14776K(18944K), 0.1890367 secs]
2020-06-02T22:31:01.638+0800: 12.567: [Full GC (Ergonomics)  17402K->14874K(18944K), 0.1799833 secs]
2020-06-02T22:31:01.877+0800: 12.805: [Full GC (Ergonomics)  17402K->14969K(18944K), 0.1828141 secs]
2020-06-02T22:31:02.121+0800: 13.050: [Full GC (Ergonomics)  17402K->15060K(18944K), 0.1930089 secs]
2020-06-02T22:31:02.366+0800: 13.295: [Full GC (Ergonomics)  17402K->15148K(18944K), 0.1954160 secs]
2020-06-02T22:31:02.629+0800: 13.557: [Full GC (Ergonomics)  17402K->15232K(18944K), 0.1789831 secs]
2020-06-02T22:31:02.862+0800: 13.791: [Full GC (Ergonomics)  17402K->15313K(18944K), 0.1870638 secs]
2020-06-02T22:31:03.136+0800: 14.065: [Full GC (Ergonomics)  17402K->15392K(18944K), 0.2053623 secs]
2020-06-02T22:31:03.409+0800: 14.337: [Full GC (Ergonomics)  17402K->15467K(18944K), 0.1735414 secs]
2020-06-02T22:31:03.631+0800: 14.559: [Full GC (Ergonomics)  17402K->15539K(18944K), 0.1986520 secs]
2020-06-02T22:31:03.880+0800: 14.809: [Full GC (Ergonomics)  17402K->15609K(18944K), 0.1910945 secs]
2020-06-02T22:31:04.113+0800: 15.041: [Full GC (Ergonomics)  17402K->15676K(18944K), 0.1868629 secs]
2020-06-02T22:31:04.350+0800: 15.278: [Full GC (Ergonomics)  17402K->15741K(18944K), 0.2251443 secs]
2020-06-02T22:31:04.612+0800: 15.541: [Full GC (Ergonomics)  16188K->15757K(18944K), 0.2292204 secs]
2020-06-02T22:31:04.842+0800: 15.770: [Full GC (Allocation Failure)  15757K->15757K(18944K), 0.1922108 secs]

我把GC 日志粘贴到这个分析GC日志的网站上,这个可视化工具可以帮我们更直观的欣赏GC的情况。各种饼状图,柱状图,折线图给你安排的明明白白。

image.png
image.png

选几个看一下,我的内存设置的最大20M,可以看到峰值的时候是16.9M

image.png
image.png

堆空间渐渐被占满

image.png
image.png

GC和Full GC的回收的大小,时间。

image.png
image.png

分析内存快照

想要更详细的分析还得生成内存快照,同样添加启动参数

参数

说明

-XX:+HeapDumpOnOutOfMemoryError

开启内存快照

-XX:HeapDumpPath=./

存储路径

使用jprofiler打开生成的快照文件(xxx.hprof),结果显而易见,People对象的锅,这样你就可以很方便的找出代码中哪里不洽当使用该对象的地方,精准定位,甩锅给同事了。

image.png
image.png

当然仅限于代码需要优化的情况,如果没有需要优化的还出现这种异常,就需要增大堆内存的空间-Xms-Xmx两个参数。 如果还不行就需要结合上面两个工具分析,做出更细化的调整。

JVM调优参数

参数

说明

-Xms4g

堆最小值,和最大值设置一样为宜

-Xmx4g

堆最大值

-Xmn2g

年轻代大小

-Xss128k

每个线程的堆栈大小

-XX:NewRatio=4

年轻代和老年代的比例1:4

-XX:SurvivorRatio=4

年轻代中Survivor区与Eden区与的大小比值1:4

-XX:MaxTenuringThreshold=15

对象在年轻代能经历回收的次数

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概念先行
  • 开启GC日志
  • 分析内存快照
  • JVM调优参数
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档