Java 什么';“这是最好的处理方法”;try-error-clean-retry“;案例

Java 什么';“这是最好的处理方法”;try-error-clean-retry“;案例,java,memory,memory-management,Java,Memory,Memory Management,我正在尝试在内存中加载图像,但可能有内存问题,因为我加载了一些其他图像。这些图像有一个“可见”字段,指示它们是否可见。无论可见性如何,我都会将它们保存在内存中,以便快速加载(当它们再次可见时) 但是,由于我的内存中有很多图像,我想尝试加载一个新图像,如果遇到内存问题,请释放不可见的图像,然后重试。现在,到目前为止,我正在使用这段相当难看的代码(我确信,出于某种原因,这段代码是错误的): try { image = GraphicsUtilities.loadImage(filePath)

我正在尝试在内存中加载图像,但可能有内存问题,因为我加载了一些其他图像。这些图像有一个“可见”字段,指示它们是否可见。无论可见性如何,我都会将它们保存在内存中,以便快速加载(当它们再次可见时)

但是,由于我的内存中有很多图像,我想尝试加载一个新图像,如果遇到内存问题,请释放不可见的图像,然后重试。现在,到目前为止,我正在使用这段相当难看的代码(我确信,出于某种原因,这段代码是错误的):

try {
    image = GraphicsUtilities.loadImage(filePath);
} catch (OutOfMemoryError e) {
    removeHiddenImageReferences();
    try {
        image = GraphicsUtilities.loadImage(filePath);
    } catch (OutOfMemoryError ee) {
        ee.printStackTrace();
        JOptionPane.showMessageDialog(parent,
            "There is not enought memory to load this image",
            "Not enough memory", JOptionPane.WARNING_MESSAGE);
    }
}

我的问题是,我应该如何处理这种情况?我觉得在catch子句中捕获一个异常并重新捕获一个异常是不好的。

我不认为这是一种特别糟糕的风格——“catch”子句的全部要点是处理异常的原因。在这种情况下,您可以通过释放一些内存,然后在传播错误之前允许再次重试来处理内存不足的问题。似乎完全合理-您可以用任何数量的语法扭曲方式重写它,以避免catch子句中包含代码,但为什么要麻烦呢?这清楚地表达了你的意图


然而,一个可能有意义的设计更改是在第二种情况下重新抛出异常(或者,只是不捕获它),并使用一个更全局的异常处理程序来处理完整的内存。即使这也是有争议的——如果你真的不希望出现任何其他OutOfMemory情况,那么将其处理为接近(几乎)总是导致其发生的场景是合理的。

我不认为这是一种特别糟糕的风格——“catch”子句的全部要点是处理异常的原因。在这种情况下,您可以通过释放一些内存,然后在传播错误之前允许再次重试来处理内存不足的问题。似乎完全合理-您可以用任何数量的语法扭曲方式重写它,以避免catch子句中包含代码,但为什么要麻烦呢?这清楚地表达了你的意图


然而,一个可能有意义的设计更改是在第二种情况下重新抛出异常(或者,只是不捕获它),并使用一个更全局的异常处理程序来处理完整的内存。甚至这也是有争议的——如果您真的不希望出现任何其他OutOfMemory情况,那么将其处理为接近(几乎)总是导致其发生的场景是合理的。

引入while循环,以便重试逻辑与条件相关联,而不仅仅是抛出的异常

int tryCount = 2;
while (tryCount > 0) {
  try {
    image = GraphicsUtilities.loadImage(filePath);
  } catch (OutOfMemoryError e) {
    removeHiddenImageReferences();
    tryCount--;
  }
}
if(tryCount <= 0) {
        JOptionPane.showMessageDialog(parent,
            "There is not enought memory to load this image",
            "Not enough memory", JOptionPane.WARNING_MESSAGE);
}
int tryCount=2;
而(tryCount>0){
试一试{
image=GraphicsUtilities.loadImage(文件路径);
}捕获(OutOfMemory错误){
removeHiddenImageReferences();
tryCount--;
}
}

if(tryCount引入while循环,使重试逻辑与条件相关联,而不仅仅是抛出的异常

int tryCount = 2;
while (tryCount > 0) {
  try {
    image = GraphicsUtilities.loadImage(filePath);
  } catch (OutOfMemoryError e) {
    removeHiddenImageReferences();
    tryCount--;
  }
}
if(tryCount <= 0) {
        JOptionPane.showMessageDialog(parent,
            "There is not enought memory to load this image",
            "Not enough memory", JOptionPane.WARNING_MESSAGE);
}
int tryCount=2;
而(tryCount>0){
试一试{
image=GraphicsUtilities.loadImage(文件路径);
}捕获(OutOfMemory错误){
removeHiddenImageReferences();
tryCount--;
}
}

如果(tryCount一个选项是将其分解为两个方法,则调用LoadImage,它在内部调用TryLoadImage

public void TryLoadImage(string filePath){
     bool b = false;

     try{
          image = GraphicsUtilities.loadImage(filePath);
          bool b = true;
     }
     catch(OutOfMemoryError){
          // Log notfication of file the was too big perhaps? so in the future you could
          // optimize this?  
     }
}

public void LoadImage(string filePath, bool clearReferences){

      if(!TryLoadImage(string filePath))    
      {
            removeHiddenImageReferences();
            if(!TryLoadImage(string filePath)){
                   // Log error
                   JOptionPane.showMessageDialog ....
            }
      }
}

一种选择是将其分解为两个方法,您调用LoadImage,它在内部调用TryLoadImage

public void TryLoadImage(string filePath){
     bool b = false;

     try{
          image = GraphicsUtilities.loadImage(filePath);
          bool b = true;
     }
     catch(OutOfMemoryError){
          // Log notfication of file the was too big perhaps? so in the future you could
          // optimize this?  
     }
}

public void LoadImage(string filePath, bool clearReferences){

      if(!TryLoadImage(string filePath))    
      {
            removeHiddenImageReferences();
            if(!TryLoadImage(string filePath)){
                   // Log error
                   JOptionPane.showMessageDialog ....
            }
      }
}

这是一个困难的问题,因为
OutOfMemoryError
不是特定于单个
线程的。这意味着,尽管在当前
线程中加载的映像占用了进程的大部分内存,但另一个
线程可能正在运行实际触发
OutOfMemoryError的进程

讨论设置内存警告系统,以便在触发OOME之前向侦听器发出警报。这允许您采取预防措施,并将您的系统从衰弱的OOME中拯救出来。阅读了您的评论后,我将在此处为后代发布链接。

这是一个困难的问题,因为
OutOfMemoryError
不是spe这意味着,尽管在当前的
线程中加载的映像占用了进程的大部分内存,但另一个
线程可能正在运行实际触发
OutOfMemoryError
的进程。Adam Wright关于更全局的OOME管理器的想法是som如果您需要在处理过程中处理这个问题,请考虑。 编辑:

讨论设置内存警告系统,以便在触发OOME之前提醒侦听器。这允许您采取预防措施,并将您的系统从衰弱的OOME中拯救出来。阅读了您的评论后,我将此链接发布在这里供子孙后代使用。

您是否考虑过使用?尽管它不一定会改变您的想法我们这里的代码,如果您的应用程序正在做其他事情,它将使情况更具可伸缩性,如果它在其他地方内存不足,您愿意丢弃这些映像。

您考虑过使用吗?虽然它不一定会更改您的代码,但如果您的应用程序正在做其他事情,它将使情况更具可伸缩性如果其他地方的内存不足,你会愿意丢弃这些图像。

你可以打电话给她

removeHiddenImageReferences();
首先。然后只需要一次try/catch。除非您知道removeHiddenImageReferences()的速度非常慢(就像处理数百万个对象一样),否则优化是没有用的。通常情况下,对于内存耗尽,您不能做太多。

您可以调用

removeHiddenImageReferences();

首先。然后你只需要一次try/catch。优化没有用,除非你知道removeHiddenImageReferences()的速度非常慢(就像你正在处理数百万个对象)。通常情况下,你无论如何也不能对内存不足做太多。

谢谢你的回答。我会告诉我们的