Java 捕捉内存不足错误的正确位置

Java 捕捉内存不足错误的正确位置,java,python,producer-consumer,Java,Python,Producer Consumer,我遇到了一个本地bot竞争的生产者-消费者设置问题(想想看,但是允许使用更多的语言,并使用管道连接stdin和stdout)。这些项目生产得很好,并且由使用者正确处理,但是,在该设置中,使用者的任务是调用可能占用过多内存的其他软件,从而导致内存不足错误 我有一个Python脚本(即使用者)使用subprocess.call连续调用其他代码段。这些都是由其他人提交以供评估的,但是,有时其中一个提交的片段使用了太多内存,引擎会产生OutOfMemoryError,这会导致整个脚本停止 使用的设置中有

我遇到了一个本地bot竞争的生产者-消费者设置问题(想想看,但是允许使用更多的语言,并使用管道连接stdin和stdout)。这些项目生产得很好,并且由使用者正确处理,但是,在该设置中,使用者的任务是调用可能占用过多内存的其他软件,从而导致内存不足错误

我有一个Python脚本(即使用者)使用
subprocess.call
连续调用其他代码段。这些都是由其他人提交以供评估的,但是,有时其中一个提交的片段使用了太多内存,引擎会产生OutOfMemoryError,这会导致整个脚本停止

使用的设置中有三个层:

  • 消费者(Python)
  • 游戏引擎(Java)
  • 玩家的机器人(语言不同)
消费者使用两个机器人作为参数调用游戏引擎:
子流程调用(['setsid','sudo','-nu','botrunner','/opt/bots/sh/run_bots.sh',bot1,bot2])

在游戏引擎中,一个循环运行,使机器人相互对抗,之后所有数据都保存在数据库中,以便玩家可以查看他们的机器人。这个想法是,如果机器人造成错误,记录错误并将胜利交给对手


但是,在什么地方可以捕捉到这个呢?这应该在“最高”(即消费者)级别上完成,还是在游戏引擎本身中完成?

在Java中捕获任何
异常
错误
的正确位置是您拥有处理它们并执行一些恢复步骤的机制的位置。如果出现
OutOfMemoryError
,您应该在能够正常关闭该错误时捕获该错误,如果可能,可以干净地释放资源并记录失败原因

OutOfMemoryError
由于堆的剩余资源无法满足块内存分配而发生。每当抛出
OutOfMemoryError
时,堆中包含的已分配对象数与分配尝试失败之前的数目完全相同。这应该是您捕获
OutOfMemoryError
并尝试删除对运行时对象的引用以释放清理可能需要的更多内存的实际时间

如果JVM处于可修复状态,您永远无法通过程序确定它,那么甚至可以从错误中恢复并继续。但这通常被认为是一个不好的设计,因为我说过你永远无法通过程序来确定它

如果您看到
java.lang.Error
,它会说

错误是Throwable的一个子类,表示存在严重问题 一个合理的应用程序不应该试图抓住

如果您有意捕获任何错误,请记住NOT覆盖
catch(Throwable t){…}
代码中的任何地方


更多详细信息。

在Java中捕获任何
异常
错误
的正确位置是有机制处理它们并执行一些恢复步骤的位置。如果出现
OutOfMemoryError
,您应该在能够正常关闭该错误时捕获该错误,如果可能,可以干净地释放资源并记录失败原因

OutOfMemoryError
由于堆的剩余资源无法满足块内存分配而发生。每当抛出
OutOfMemoryError
时,堆中包含的已分配对象数与分配尝试失败之前的数目完全相同。这应该是您捕获
OutOfMemoryError
并尝试删除对运行时对象的引用以释放清理可能需要的更多内存的实际时间

如果JVM处于可修复状态,您永远无法通过程序确定它,那么甚至可以从错误中恢复并继续。但这通常被认为是一个不好的设计,因为我说过你永远无法通过程序来确定它

如果您看到
java.lang.Error
,它会说

错误是Throwable的一个子类,表示存在严重问题 一个合理的应用程序不应该试图抓住

如果您有意捕获任何错误,请记住NOT覆盖
catch(Throwable t){…}
代码中的任何地方


更多详细信息。

您可以捕获OutOfMemoryError(OOM)异常并尝试从中恢复,但这可能不是一个好主意。。。特别是如果你的目标是让应用程序“继续”

原因有很多:

As pointed out, there are better ways to manage memory resources than explicitly freeing things; i.e. using SoftReference and WeakReference for objects that could be freed if memory is short.

If you wait until you actually run out of memory before freeing things, your application is likely to spend more time running the garbage collector. Depending on your JVM version and on your GC tuning parameters, the JVM can end up running the GC more and more frequently as it approaches the point at which will throw an OOM. The slowdown (in terms of the application doing useful work) can be significant. You probably want to avoid this.

If the root cause of your problem is a memory leak, then the chances are that catching and recovering from the OOM will not reclaim the leaked memory. You application will keep going for a bit then OOM again, and again, and again at ever reducing intervals.
所以我的建议是不要试图从一个房间继续走下去。。。除非你知道:

where and why the OOM happened,
that there won't have been any "collateral damage", and
that your recovery will release enough memory to continue.
可能至少有一个好时机可以捕捉OutOfMemoryError,当您专门分配一些可能太大的内容时:

public static int[] decode(InputStream in, int len) throws IOException {
  int result[];
  try {
    result = new int[len];
  } catch (OutOfMemoryError e) {
    throw new IOException("Result too long to read into memory: " + len);
  } catch (NegativeArraySizeException e) {
    throw new IOException("Cannot read negative length: " + len);
  }

}

您可以捕获并尝试从OutOfMemoryError(OOM)异常中恢复,但这可能不是一个好主意。。。特别是如果你的目标是让应用程序“继续”

原因有很多:

As pointed out, there are better ways to manage memory resources than explicitly freeing things; i.e. using SoftReference and WeakReference for objects that could be freed if memory is short.

If you wait until you actually run out of memory before freeing things, your application is likely to spend more time running the garbage collector. Depending on your JVM version and on your GC tuning parameters, the JVM can end up running the GC more and more frequently as it approaches the point at which will throw an OOM. The slowdown (in terms of the application doing useful work) can be significant. You probably want to avoid this.

If the root cause of your problem is a memory leak, then the chances are that catching and recovering from the OOM will not reclaim the leaked memory. You application will keep going for a bit then OOM again, and again, and again at ever reducing intervals.
所以我的建议是不要试图从一个房间继续走下去。。。除非你知道:

where and why the OOM happened,
that there won't have been any "collateral damage", and
that your recovery will release enough memory to continue.
可能至少有一个好时机可以捕捉OutOfMemoryError,当您专门分配一些可能太大的内容时:

public static int[] decode(InputStream in, int len) throws IOException {
  int result[];
  try {
    result = new int[len];
  } catch (OutOfMemoryError e) {
    throw new IOException("Result too long to read into memory: " + len);
  } catch (NegativeArraySizeException e) {
    throw new IOException("Cannot read negative length: " + len);
  }

}
又见又见