2009-09-02 4 views
1

메모리에 이미지를로드하려고하는데 다른 이미지가로드되어있어 메모리 문제가있을 수 있습니다. 이러한 이미지에는 가시적인지 아닌지를 나타내는 "가시적 인"필드가 있습니다. 가시성에 관계없이 빠른 로딩 (다시 표시 될 때)을 위해 메모리에 유지합니다."try-error - clean -retry"사례를 처리하는 가장 좋은 방법은 무엇입니까?

그러나 나는 메모리에 많은 것을 가지고 있기 때문에 새로운 이미지를로드하려고하고 메모리 문제가 발생하면 보이지 않는 이미지를 해제하고 다시 시도하십시오. 나는 케이스의이 종류를 처리하는 방법,

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 절 안에서 예외를 잡는 것이 나쁘다고 생각한다.

답변

4

"캐치 (catch)"절의 전체적인 점은 예외의 원인을 처리하는 것입니다. 이 경우 일부 메모리를 해제하여 메모리 부족 현상을 처리하도록 선택한 다음 오류를 전파하기 전에 다시 시도 할 수 있습니다. 완벽하게 합리적인 것 같습니다. catch 절 안에 코드가있는 것을 피하기 위해 구문에 따라 여러 가지로 뒤틀린 방법으로 코드를 다시 작성할 수 있지만 왜 귀찮은 것입니까? 이것은 분명히 당신의 의도를 표현합니다.

그러나 두 번째 경우에서 예외를 다시 발생시키는 (또는 catch하지 않는 것) 한 가지 디자인 변경이있을 수 있으며 전체 메모리를 처리하는 데 더 많은 전역 예외 처리기가 있어야합니다. 이것은 심지어 논쟁의 여지가 있습니다. 다른 OutOfMemory 상황을 실제로 기대하지 않는다면 (거의) 항상 그럴만한 원인이되는 시나리오에 가깝게 처리하십시오.

1

재시도 논리가 throw되는 예외뿐만 아니라 조건에 연결되도록 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); 
} 

이 예는 스택 트레이스를 벗어났습니다 만,이 시점에서 당신이 메모리 부족이기 때문에 그 중요하지 (단지 MessageDialog의 식별자를 포함하거나이 검사가 이루어지고 곳 로그).

+0

답해 주셔서 감사합니다. 나는 점차적으로 메모리를 공개했다면 (한 번에 하나의 숨겨진 이미지를 릴리스 할 수도 있지만) 필자의 예에서는 일단 이것이 공개되면 처음에는 조금 이상하다고 생각하기 때문에 이것을 사용합니다. –

2

하나의 옵션은 2 가지 방법으로 구분하는 것이고, 내부적으로 TryLoadImage를 호출하는 LoadImage를 호출하는 것입니다. OutOfMemoryError의 개별 Threads에 국한되지 않는로

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 .... 
      } 
     } 
} 
+0

좋은 대안 ... 사실 나는 내 대답을 다르게 표현해야했습니다. 나는 코드를 작성하는 다른 방법에 관심이 있었을뿐만 아니라 내 디자인에 "나쁜"글이 적혀 있는지 여부에 대해서도 관심이있었습니다. 간단한 예제를 위해 솔루션을 작성하고 유지하는 것이 가장 쉽다고 생각하기 시작했습니다. –

+0

나는 당신이 그것을하고있는 방식이 좋지 않다고 생각한다. Out of Mana 예외를 완전히 없애기보다는 로그 할 때마다 뭔가를 로그하면 성능을 모니터링 할 수있다. –

3

이, 힘든 일이다. 즉, 현재 Thread에서 프로세스의 메모리를 차지하는 이미지를로드하는 중이지만 Thread은 실제로 OutOfMemoryError을 트리거하는 프로세스를 실행 중일 수 있습니다. 더 많은 글로벌 OOME 관리자에 대한 Adam Wright의 생각은 프로세스에서이 사례를 처리해야하는 경우 고려해야 할 사항입니다.

편집 : 당신은 오세요를 실행하기 전에 청취자가 경고를 할 수 있도록 메모리 경고 시스템 설정에 대한

This article 회담. 이렇게하면 예방 조치를 취하고 쇠약 해지는 OOME에서 시스템을 저장할 수 있습니다. 귀하의 의견을 읽고, 나는 후손을 위해 여기에 링크를 게시하고 있습니다.

+0

흠 그 생각하지 않았다. 하지만 고맙게도 이번 경우에는 EDT가 실행될 때만 제 사례에서 그렇게합니다. 하지만 일반적인 경우에는 메모를해야합니다. –

1

SoftReference을 사용해 보았습니까? 여기서 코드를 변경하지 않아도되지만, 응용 프로그램이 다른 작업을 수행 할 때 상황이 더 확장 될 수 있으며 다른 곳에서 메모리가 부족한 경우 이미지를 버릴 수 있습니다.

-1

당신은

removeHiddenImageReferences(); 

먼저 호출 할 수 있습니다. 그런 다음 하나의 try/catch 만 필요합니다. 당신이 removeHiddenImageReferences()를 안다면 엄청나게 느립니다 (수백만 개의 객체로 작업하는 경우처럼) 최적화 사용은 없습니다. 보통 어쨌든 메모리 부족에 대해서는 너무 많이 할 수 없습니다.

+0

전체 점이 removeHiddenImageReferences()를 호출하지 않습니다. 내가 할 필요가 없다면. 가능한 한 많은 이미지를 메모리에 저장하고 필요한 경우에만 메모리를 해제합니다. –

+0

죄송합니다. 코드를 읽고 질문을 읽지 않고 곧바로 답장을 보냅니다. :) – Shizzmo

관련 문제