本帖最後由 Lin-JN 於 2024-5-4 14:54 編輯
我发贴纯属无聊,我说的不一定正确,只是把自己的一些经验分享出来,因为我眼睛视力最近下降厉害,个别地方也可能会写漏或者写错。
我是从15年前那个天堂模拟器大分享时代走过来并一路跟前辈们学习交流才有了今天所谓的“技术”的,非常感谢那个时代的各路大神们。
我个人对自己发的任何教学贴都不会负任何责任,仅仅只是抱着一种“希望尽量少的新手不要被人骗”的想法无聊水几贴并指望有抱着和我一样想法的大神们出来交流一下。
仅此而已……
最近有台湾朋友发给我帮忙修改的一些版本,发现有一些会在源码中写入 System.gc()
(当然了,我偷偷给他全部删掉了,而且我不告诉他!),觉得比较好奇,因为之前学习时找的一些资料都是极力劝阻这种行为的,于是再去查了一点资料。
在翻阅了一些前辈大佬对不同版本Jave中GC相关的源码解析后,得到的结论是,我们应当从最大限度上来减少gc,让gc变得更少,才能够更稳定,因为在FullGC的时候,整个系统是处于一种 World Stop 状态中的,严重的可能会引起整个项目崩溃。
于是,我稍稍研究了一下要从哪些方面来做到这些事情。
正常来说,我们要减少gc次数,肯定就需要了解gc的过程,以及gc频率,再谈如何避免FullGC过多。
这里就牵涉到一个启动参数
- -XX:+HeapDumpOnOutOfMemoryError -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:./Loginfo/gc_recode.log
複製代碼
具体的作用,有兴趣的可以查一下,目的是为了把gc的情况记录下来,然后通过记录来查看如何更合理的设定年轻代内存数值或者查看是否有内存溢出等等。
有兴趣的同学可以再去认真查看一下关于GC的整套原理及流程。
- 2024-05-03T04:09:25.046+0800: 56.445: [GC (Allocation Failure) 56.445: [ParNew: 691574K->330558K(819200K), 0.0767209 secs] 691574K->369887K(3784704K) icms_dc=0 , 0.0768291 secs] [Times: user=0.17 sys=0.02, real=0.08 secs]
複製代碼
- 691574 - 330558 = 361016
- 691574 - 369887 = 361287
複製代碼
后面的差值比前面的大,正常来说,这里年轻代的设定是比较合理的。
如果结果反过来,我们就可以相对适量提升一点年轻代大小(官方推荐是整个堆大小的3/8),当然了,年轻代的修改对系统影响是比较大的,提升年轻代大小在不同程度上会消耗更多系统资源,可能需要多次调整才能找到适合自己版本的数值。
然后建议初始堆大小和最大堆大小都设置成一样的,可以尽量避免每次gc后系统重新分配内存,这也是我新想到的一种可能性,毕竟之前我自己对初始堆和最大堆的设定大小从来都没有太过在意。
然后呢,如果你的源码中包含了 System.gc()或者RunTime.runTime().gc()方法的,也建议全部注销,或者在启动参数中加上禁止显式GC的参数