我用Spring开发了一个应用程序。我有一个bean来创建一个线程,但在执行该线程期间,在运行时,JVM会抛出OutOfMemoryError - Java Heap Space。
我要问的是以下解决方案是否适合解决问题:
一旦抛出线程死亡并释放先前由线程占用的内存,然后我通过另一个线程(我称之为RestartThread),我意识到线程已死(没有捕获错误),然后:
1)调用垃圾收集器,有效地释放死线程的内存;
2)回调函数run()死亡的Thread,即重新启动前一个实例(包括死亡Thread使用的私有变量,即使在生成'OutOfMemoryError'后仍保留在内存中)死亡的Thread。
你怎么看待这件事,它可能会产生问题?是一个正确的解决方案,重新启动死亡线程的先前istance?
提前谢谢,
--Alucard
答案 0 :(得分:2)
尽一切可能阻止OutOfMemoryError
。当JVM没有任何其他选择时,它会抛出它,即已经删除了GC可以删除的所有对象。发生这种情况时,即使正常终止,JVM通常也没有资源。它应该被杀死并重新开始。
大多数机会即使你试图捕获OutOfMemoryError
并取消链接某些资源,这也是行不通的,至少不会有效。
答案 1 :(得分:2)
从OutOfMemoryError
恢复,尤其是在多线程环境中,非常困难,甚至经常是不可能的。您可能应该找出内存不足的原因(比如泄漏引用或者您的应用程序只需要比您给出的内存更多的内存)并尝试修复它,而不是试图从中恢复。
即使您可以让线程抛出错误并重新启动它,重新启动的线程可能会在开始时再次死亡。在更糟糕的情况下,根本原因可能在程序的其他部分。这意味着应用程序中的其他线程会开始抛出相同的错误,因为他们试图分配新对象,导致错误级联到整个应用程序,最后整个事情会崩溃。
记忆不是你唯一的问题。如果由OOME终止的线程处于处理过程中并触及某些共享对象的状态(其他线程也使用),那么您的应用程序状态几乎可以是任何东西(即不一致)。此外,如果另一个线程正在等待某个监视器(mutex),终止的线程正在等待(或等待/通知等),则另一个线程可能会死锁。在大多数情况下,编写恢复逻辑并检查恢复是否成功将非常困难,因为在确定应用程序已真正恢复之前,需要检查的变量和事项太多。
答案 2 :(得分:1)
您可以尝试通过生成堆转储来了解为什么会出现OOM错误 见这里:
虽然这里的答案是针对JBoss Application Server的,但它应该适用于任何java进程。
稍后你可以分析这个转储,也许你会发现生成了很多相同类型的对象。
希望这有帮助