"main"线程中的异常java.lang.OutOfMemoryError,如何找到并解决?

4

我正在尝试编写一个填字游戏生成器,使用给定的字典txt文件和给定的模式txt文件。基本思路是使用DFS算法。问题在于当字典文件非常大(约50000个单词)时会出现问题,然后我收到以下错误信息:

Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded

我知道我的程序中有一部分浪费了内存,但我不知道它在哪里、如何找到它以及如何修复它。


“如何查找”这个相关问题已经在以下链接中得到解答:https://dev59.com/LnE85IYBdhLWcg3wUBsZ - meriton
5个回答

3

它是否真的会浪费内存?如果你正在加载一个庞大的字典,那么你可能只需要增加JVM内存设置(JVM有一个最大内存分配-取决于您的平台,并可配置)。

例如:

$ java -Xmx512m ....

将JVM的最大内存分配增加到512m。

如果您认为存在内存泄漏(由于引用未被释放而导致垃圾回收未启动),那么像YourKit这样的分析工具可能会有所帮助。注意,这不是免费的,但试用版可能会帮助您解决问题。


嘿,我已经尝试增加JVM内存了... 您还有其他建议吗? - or.nomore
你尝试过对其进行性能分析吗? - Brian Agnew
抱歉我的无知,什么是性能分析? - or.nomore
3
使用某种工具(例如YourKit)运行程序,并获取统计数据/指标,以确定瓶颈所在的位置(例如内存使用量)。 - Brian Agnew

2
为解决这个问题(在基于Linux的操作系统中),请按照以下步骤进行:
1) 通过配置“domain.xml”(位于/glassfish/domain/domain1/config)来增加内存(这样可以减少此问题的频繁出现)。搜索以下内容: -XX:MaxPermSize=
将其设置为更高的值,例如198m或256m。
2) 杀死Glassfish进程以释放其运行的端口(在我的情况下是8686)。在Linux操作系统中打开终端并输入:
sudo netstat -npl | grep 8686
这将显示类似以下内容的结果:
tcp6 0 0 :::8686 :::* LISTEN 3452/java
然后使用kill -9 3452命令杀死该进程(在本例中为3452)。
现在尝试启动Glassfish,它应该可以正常启动。

0
有时候,我看到人们在循环中初始化变量,比如:
While(condition){

    String s="tttt";

}

这应该被避免,因为它浪费了大量的内存。


它不一定会浪费内存(而且您的示例肯定不会,因为字符串字面量是池化的)。它甚至可以帮助垃圾回收年轻对象比收集旧对象更便宜。 - gustafc
非常感谢,这是我之前不知道的东西。这真的让我的一天变得更美好了。 - Shashank T

0

这是一个棘手的问题。我曾经遇到过一两次,增加堆大小并没有帮助。使用VM设置来解决它 - 你甚至可能需要减小堆大小(这对我曾经有效过)。你也可以尝试测试不同的垃圾收集器,我曾成功地使用G1收集器

关于如何避免此错误的一般建议也很难(或者当我研究此事以解决自己的问题时,似乎是这样的)。高婴儿期死亡率可能是不错的,因为年轻对象比老对象更便宜收集。


0

大型字典...嗯...是否有将其直接存储在JVM内存中的绝对要求?

像我这样懒惰的人会将其存储在数据库中(甚至可能是内存中的数据库?例如Hypersonic),将搜索列表的责任转移到数据库,而我的程序则专注于创建有趣的对称黑白方块组合 :)

只是一个想法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接