2011-03-09 2 views
5

이 질문은 내 previous question에 대한 답변의 결과입니다.이미지가 캐싱되어 힙 공간을 먹고 있습니다.

Eclipse MAT를 사용하여 내 힙을 먹는 것을 조사하도록 요청 받았습니다. 다음은 내 관찰 (상위 소비자가) 있습니다

class sun.awt.SunToolkit         333.7 MB 
com.tennisearth.service.impl.CacheManagerServiceImpl  136 MB 
org.apache.jasper.servlet.JspServlet      91.5 MB 

이미 CacheManageServiceImpl으로 문제를 해결하지만, SunToolkit와 도움을 필요로했다. 이하

Image img = new ImageIcon(imagePath).getImage(); 
int imageWidth = img.getWidth(null); 
int imageHeight = img.getHeight(null); 

Plz은 이미지 오브젝트 만 뒷부분 요구되는 이미지의 폭/높이를 얻기 위해 생성되는 것을 주목 (내부적 SunToolkit.imgCache 사용하는) 이미지 오브젝트를 생성하는 코드 어떤 논리.

SunToolkit 이미지 캐싱을 사용 중지하는 방법이 있습니까? 더 나은 방법은이 캐시를 지울 수있는 방법입니까? 아니면이 정보를 검색 할 수있는 더 나은 방법이 있습니까? 참조 용 BTW

, 내가 (PLZ 힙 크기 인수를 주) 제이 보스 실행하기 위해 아래의 명령을 사용하고 있습니다 :

java -Dprogram.name=run.sh -server -Xms256m -Xmx1024m -XX:PermSize=64m -XX:MaxPermSize=256m -verbose:gc -Xloggc:/data1/logs/jboss/GC.log -XX:+HeapDumpOnOutOfMemoryError -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000 -Dorg.apache.catalina.STRICT_SERVLET_COMPLIANCE=false -Djava.net.preferIPv4Stack=true -Djava.library.path=/usr/local/java/jboss-4.2.2.GA/bin/native -Djava.endorsed.dirs=/usr/local/java/jboss-4.2.2.GA/lib/endorsed -classpath /usr/local/java/jboss-4.2.2.GA/bin/run.jar:/usr/local/java/jdk1.6.0_06/lib/tools.jar org.jboss.Main -c default -b <IP_ADDRESS> -Djboss.messaging.ServerPeerID=1 

수밋

+1

Java에서 이미지 및 이미지 캐싱과 관련하여 * 많은 문제가 있습니다. API 결함 주위의 악명 높은 * flush() * 해결 방법이 마음에 들었습니다. 이미지를 무효화하는 것만으로는 충분하지 않은 경우가 있습니다. 때때로 * flush() *를 호출해야하며 때로는 의미가 없습니다. 서버에 있다면 ImageMagick의 * identify * 명령을 사용하여 폭/높이 정보를 얻을 수 있습니다. 외부 프로세스를 실행하는 데에는 약간의 고통이 따르지만 이미지를로드하는 것만으로 서버의 너비/높이를 얻는 것은 너무 무거울 수 있습니다. – SyntaxT3rr0r

+0

또 다른 옵션 ... 우리는 모든 사진을 일괄 처리하고 사진의 파일 이름에 widht/height 정보를 직접 입력했습니다. * mypic.jpg *는 * mypic640x480.jpg *가됩니다. 그런 다음 파일 이름에서 (w, h)를 추출하면 ... – SyntaxT3rr0r

+0

이 문제에 대한 Google의 의견은 흥미 롭습니다. * OS X 이외의 다른 플랫폼에서도 동일한 문제가 발생 했으므로 " GC가 이미지를 회수하기 전에 플러시를 강제 실행하기 위해 ToolkitImage에 대한 마무리 작업을 구현하여 Sun에서 적절한 수정 작업을 수행해야합니다. 아무도 이것을 Sun에보고 했습니까? * – SyntaxT3rr0r

답변

3

이미지 캐시가 SoftCache라는 클래스에 의해 구현 될 것 같다, 그 문서의 다음 상태 :

Map 인터페이스의 메모리에 민감한 구현입니다.

SoftCache 개체는 java.lang.ref.SoftReference 을 사용하여 메모리 감지 해시 맵을 구현합니다. 쓰레기 컬렉터가 SoftCache 항목의 값 객체가 더 이상 강하게 도달 특정 시점에서 판단하면, 그것은 값 객체가 차지하는 메모리를 해제하기 위해 해당 항목을 제거 할 수 있습니다. 가상 컴퓨터가 OutOfMemoryError을 던지기 전에 모든 SoftCache 개체는 완전히 으로 지워집니다.

다른 곳에서 메모리가 필요할 때 자동으로 지워지므로이 캐시가 사용하는 메모리는 걱정하지 않아도됩니다.

편집 :SyntaxT3rr0r에 의해 코멘트를 읽은 후, 나는 여전히 이미지에 flush를 호출 가치가있을 수 있다고 생각. 이 메소드가 larget 메소드의 일부인 경우 이미지를 null 또는 리팩터링으로 설정하여 더 빨리 범위를 벗어날 수 있습니다.

또 다른 가능성은 ImageIO API를 사용하여 폭과 높이를 검색하는 것입니다. 이는 ImageReader for the image type으로 가능해야합니다.

+1

설명해 주셔서 감사합니다. 다행히 이것에 대해 걱정하지 않아도됩니다 :) – Sumit

+0

편집을 보았습니다. 이미지 객체를 만드는 프로세스의 속도를 높이기 위해 이미지 캐싱을 사용하고 싶습니다. 나는 이미지를 내뿜어도이 캐시를 사용할 수 없다고 생각합니다. 권리? – Sumit

+1

@Sumit, 어떤 캐시가 호출에 의해 플러시되는지 정확히 알지 못합니다. 동일한 이미지 경로의 너비와 높이를 반복적으로 쿼리하는 경우 Map 과 같이 간단한 캐시를 직접 구현하는 것이 좋습니다. imgCache가 gc에 의해 정리되면 이미지를 다시 만들 필요가 없습니다. –

1

하는 것은 가능한 이미지 객체가 오래 범위에 남아 일정 기간? 예를 들어, 오랜 시간 동안 실행되는 코드 블록의 바깥 범위에 포함되어 있으면 제대로 가비지 수집되지 않을 수 있습니다.

가끔 드문 경우이지만 Image 객체 참조를 null로 명시 적으로 설정하는 것이 좋습니다. 위에서 언급 한 경우에도 마찬가지입니다. 더 많은 정보를 원하시면 다음과 같은 질문을 참조하십시오 : Does assigning objects to null in Java impact garbage collection?

관련 문제