请问 Java 怎么防止内存溢出?

2020-09-15 10:54:06 +08:00
 youla

请问遇到这种情况怎么防止内存溢出?

Test t=new Test();
t.start();
//没有找到关闭以及释放资源的方法

4275 次点击
所在节点    Java
26 条回复
ic2y
2020-09-15 18:46:07 +08:00
@youla 在启动脚本里,加上 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/heap/java.dump 然后运行一把程序,让他内存溢出崩溃。 然后用 MAT 软件分析 /path/heap/java.dump 文件,看看是谁导致了溢出,修正之,再往复循环测试。 直到不崩溃。
neoblackcap
2020-09-15 21:08:25 +08:00
@youla 你说不用规避的手段,那就是你去修掉内存泄漏的 bug 。否则所有方法都是规避手段。
whp1473
2020-09-16 16:57:12 +08:00
首先你确定是这个类造成的么?
第一、Test t=new Test(); t.start();创建后方法出栈就会判定为可回收了,gc 会自动垃圾回收。如果不确定,用 JVM VisualVM 分析 dump 日志,找到堆中最多的类,分析为什么该类被一直持有
第二、Test t=new Test(); t.start();如果是一个线程,一直运行,那说明里面有 while 死循环,并一直持有对象的地址和一直 new 对象导致,也可能是阻塞导致对象不被释放,比如 Http 不设置超时时间等。如果是古老的包,可以考虑继承、代理模式、AOP 等方式替换接口实现,来修复该 BUG 。
第三、如果都没有问题,Test 就是每个用户请求就要有一个,那建议加大 JVM 堆内存,同时使用更好的机器,以及对机器限流和用 ng 做复杂均衡,将请求均匀分布在更多的机器上
youla
2020-09-17 09:38:21 +08:00
@whp1473 你好,我也不太熟悉 Java,这个类里面可能封装了 io 包里面的一些类没有及时 close,想请教下这种情况会回收吗?
whp1473
2020-09-17 10:42:13 +08:00
@youla JVM 会自动关闭并回收,但是一般都应手动关闭,否则会一直占用无用资源。更多的情况应该是阻塞导致的。还有如果有 static 要注意,比如这种 private List<对象> list = new ArrayList<>(); list 中放入 IO,那永远不会被释放。
youla
2020-09-17 15:55:28 +08:00
@whp1473 好的,多谢指教。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/707095

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX