2011-09-08 104 views
7

可能重复:
Catching java.lang.OutOfMemoryError捕获OutOfMemoryError是一个坏主意吗?

OutOfMemoryError是:当Java虚拟机无法分配一个对象,因为 它是内存不足,并没有更多的

时抛出内存可以通过 垃圾回收器

的Java说:

一个错误是Throwable的子类,表示严重的问题 合理的应用程序不应该试图捕获。大多数这样的 错误都是异常情况。

这感觉就像讯:

如果你是溺水,是合理的:你不应该试图游泳向上 保持你的头露出水面。死亡通常是由 异常情况造成的。

让我们想象一个运行服务的场景。出于某种原因,同一服务器上的另一个应用程序正在占用大量内存,导致服务中出现意外的OOM。试图减少这种服务的内存消耗以保持对用户可用,这是一个坏主意吗?

还是在JVM级别发生了一些更基础的事情,导致OOM抛出后无法实现此类解决方案?

+0

@aix我可以通过将一些数据结构的引用设置为无效,即使我没有正确保存它们,但在戏剧性情况下仍然可以正常保存时,可以减少一些引用。 – JVerstry

+0

@dogbane你的参考文献不回答我的问题,这个问题不是重复的。 – JVerstry

+0

一个更好的比喻是:你开着一辆着火的汽车。不要试图继续并到达目的地。拉到坚硬的肩膀上。 – Jim

回答

0

这里的问题在于,通过OOM是一种在正常情况下不应该发生的错误。通过捕捉它并试图释放记忆,你可能会在其他地方模糊某种泄漏或意外行为。

如果你确实得到了OOM,可能是因为你没有配置JVM来使用更多的内存。

+0

同意,但我可以在释放内存并自己调用gc后记录该问题。这不是不可能的。 – JVerstry

+1

如果你可以修复它,并且你知道错误发生的原因并且它是合法的,那么一定要这样做。但大多数情况下,当你得到一个OOM时,你不会知道,并且恢复起来会非常困难,因为一旦你的虚拟机内存不足,你会发现自己能做的事情非常有限。 –

3

当你引用时,Java虚拟机无法分配一个对象,因为 它的内存不足,可以提供没有更多的内存由 垃圾收集

扔了,

在那一刻,你被拧紧了。这个描述意味着Java/JVM无法获得足够的资源来运行,如果这是真的,那么执行更多的Java代码来解决问题本身就是有问题的。

一个很好的比喻是你的汽车用完了,你想通过踩油门来解决这个问题。

更好的解决办法是做容量规划,并确保

1)你的服务器有足够的内存来完成他们的工作
2)您的服务器上运行的服务规范中执行并且不消耗超过一定量的资源。

+0

“JVM不再正常运行”或者没有资源正常运行? – JVerstry

+0

真的是第二个,编辑我的答案。 – hvgotcodes

+0

这就是我的想法,因此,(至少)试图挽救一天并不是完全不可能的或不合理的。 – JVerstry

-1

这是一个坏主意。主要是因为OutOfMemoryErrorError而不是Exception - An Error“表示合理应用程序不应尝试捕获的严重问题。”

相反,你的分析可能出现的情况,并基于该PDF

+1

好的,但是如果你能修好飞机以避免飞机坠毁怎么办?有没有理由不这样做?这是我的问题... – JVerstry

+0

男人,这是一个比喻!因此,大多数时间都不受人为控制,因此发生飞机坠毁事故。为此,我们制定了应急程序,以便可以挽救一些灵魂。同样,如果应用程序非常关键并且应该有一个恢复过程 - 如果合理,应该有适当的预警。如果你正要赶上'OutOfMemoryError',你会在哪里捕捉到?并且大部分时间当你抓住它的时候,你无能为力。就像一架飞机在大西洋中部坠毁一样;即使你有降落伞,幸存的机会也是0 –

-1

这是没用的提供的信息应用修复程序。因为在错误被捕捉的那一刻,你可能缺乏堆内存,所以任何新的对象创建都可能会抛出一个新的OOME。在捕获量中有这么小的回旋余地意味着你唯一可以采取的行动就是退出。

试验这个片段,告诉我你的输出是什么:

 import java.util.LinkedList; 
     import java.util.List; 

     public class OOMErrorTest { 


     public static void main(String[] args) { 
      List<Long> ll = new LinkedList<Long>(); 

      try { 
       long l = 0; 
       while(true){ 
        ll.add(new Long(l++)); 
       } 
      } catch(OutOfMemoryError oome){   
       System.out.println("Error catched!!"); 
       System.out.println("size:" +ll.size()); 
      } 
      System.out.println("Test finished"); 
     } 

     } 

但严格来说,是的,这些都是开捕。

+0

你的意思是精确地瓦解? – JVerstry

+0

我的意思是炸毁。 –

+1

你可能想检查http://stackoverflow.com/questions/2679330/catching-java-lang-outofmemoryerror然后 – JVerstry

-1

你不能从OOM中恢复。

但有一个理由尝试去捕捉任何东西 - 这就是当我们在一个我不再工作的项目中完全做到这一点时,这个“可抛弃的”派告诉我的 - 其中一个原因是:尝试记录发生的事情。因为如果你不知道发生了什么,很难弄清楚如何让软件恢复正常运行。

还有一个很大的“但是”原因:它通常不会工作。

错误通常无法从运行代码中修复,这就是为什么会有这种差异。

相关问题