Java Runnable Out of Memory

时间:2018-02-01 20:29:20

标签: java garbage-collection runnable

不好的做法......

我们实现了一个Java线程Runnable,并在其run()中有while(true)做了一些事情。 while内的第一件事就是try/catch/finally说,如果发现任何事情,请先睡觉,然后“退出”(这会持续一段时间)。

如果在更高级别的线程外有OutOfMemory问题,线程是否会完全死掉?如果是这样,try/catch/finally将不会catch,因为OOM的执行超出了该范围?

线程是否会被垃圾收集(它不合理地死亡)。

TLDR:如果Runnable得到OutOfMemory它会死掉并且只是停在其轨道上,或者是在执行范围内抛出该异常?

run(){
  while(true){
    try {
      stuff
    } catch{  //blah
    } finally{sleep}
  }
}

4 个答案:

答案 0 :(得分:2)

Error而不是Exception发现整个JVM时 - >在大多数情况下,所有线程都会死亡。
如果你的后台线程没有使用共享的resurces,那么它可能会受到冲击,但正如所说的非常罕见。 啊,如果它是一个deamon threas它会死于instat。
try catch final是什么意思? 你不能真正发现错误,它就像一颗子弹:

  

错误是可以捕获的,你可以尝试捕获,但如果它被抛出你就死了。

答案 1 :(得分:2)

分配失败时抛出OutOfMemoryError。因此,它被传递到进行分配尝试的线程的调用链。只有try … catch块封装了这个调用链,resp。分配本身可能会抓住它。

对JVM的整体操作和其他线程没有直接影响。当然,如果抛出OutOfMemoryError的原因是JVM内存不足,那么这种特殊情况本身可能同时影响整个JVM操作或其他线程。例如,当时尝试分配的所有线程可能会因错误而失败。

this answer所示,如果内存太低而无法构造单个错误实例,则多个线程可能会遇到相同的OutOfMemoryError实例。但这并不意味着抛出的错误可能会转移到不同的线程。线程中的失败分配与该线程中捕获的错误之间仍存在因果关系。或者,如果异步操作失败,并发框架可能会将错误实例移交给启动线程。

JVM在OutOfMemoryError上自动退出的唯一原因是间接的;如果所有非守护进程线程都退出以响应OutOfMemoryError,例如当没有捕获它时,JVM将退出,因为当没有非守护程序线程处于活动状态时,这是标准行为。

有些情况下,当JVM内存不低时,应用程序可以从单个失败的分配中恢复,例如,如果失败的分配非常大(表达式new long[Integer.MAX_VALUE-8]需要~16GiB),如果它遇到一般限制(HotSpot不支持new long[Integer.MAX_VALUE],即使有足够的内存),或者需要特殊的内存而不是普通堆空间(旧JVM中的本机缓冲区,图形内存或PermGen空间)。

答案 2 :(得分:1)

再次做作业时间?

OutOfMemoryError是错误,不是例外。您可以捕获Error - 所有,它们来自ThrowableException也是如此 - 但这不是一个好主意。

您的线程不会死,您的整个JVM都会死。因为从OutOfMemoryError恢复真的没有优雅的方式。

答案 3 :(得分:1)

当您在while循环中捕获OutOfMemoryError时,您分配的所有内容(假设它们仅在您的循环中引用)直到点内存错误,将有资格进行垃圾回收。(这也是没有的情况)错误)

如果一个线程由于OutOfMemoryError而死亡,它的堆栈将被销毁,并且仅从该堆栈引用的所有对象也将有资格进行垃圾收集。

如果你的非守护程序线程处于活动状态,即使主线程由于OutOfMemoryError而死亡,jvm也不会死亡。

OutOfMemoryError可能有不同的原因,这里列出https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/memleaks002.html

通常建议您在抓住OutOfMemoryError时清理并退出。