java.lang.OutOfMemoryErrorの発生から原因特定まで

java.lang.OutOfMemoryErrorの発生

現在1日に100人くらいの人が利用しているのだけれど、1日〜2日程度動かすと以下のエラーを吐き出して応答が返ってこなくなる問題が発生

Jul 23, 2011 9:40:51 AM com.sun.jersey.spi.container.ContainerResponse mapMappableContainerException
SEVERE: The exception contained within MappableContainerException could not be mapped to a response, re-throwing to the HTTP container
java.lang.OutOfMemoryError: Java heap space
	at com.sun.org.apache.xerces.internal.util.XMLStringBuffer.append(XMLStringBuffer.java:205)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.refresh(XMLDocumentScannerImpl.java:1522)
	at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.invokeListeners(XMLEntityScanner.java:2070)
	at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.skipSpaces(XMLEntityScanner.java:1515)
	at com.sun.org.apache.xerces.internal.impl.XMLDTDScannerImpl.skipSeparator(XMLDTDScannerImpl.java:2056)
	at com.sun.org.apache.xerces.internal.impl.XMLDTDScannerImpl.scanDecls(XMLDTDScannerImpl.java:2032)
	at com.sun.org.apache.xerces.internal.impl.XMLDTDScannerImpl.scanDTDExternalSubset(XMLDTDScannerImpl.java:320)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$DTDDriver.dispatch(XMLDocumentScannerImpl.java:1203)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$DTDDriver.next(XMLDocumentScannerImpl.java:1090)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:1003)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648)
	at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:140)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:511)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:808)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
	at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119)
	at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
	at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
	at org.dom4j.io.SAXReader.read(SAXReader.java:465)
	at org.hibernate.util.xml.MappingReader.readMappingDocument(MappingReader.java:75)
	at org.hibernate.cfg.Configuration.add(Configuration.java:513)
	at org.hibernate.cfg.Configuration.add(Configuration.java:509)
	at org.hibernate.cfg.Configuration.add(Configuration.java:689)
	at org.hibernate.cfg.Configuration.addResource(Configuration.java:774)
	at org.hibernate.cfg.Configuration.parseMappingElement(Configuration.java:2317)
	at org.hibernate.cfg.Configuration.parseSessionFactory(Configuration.java:2283)
	at org.hibernate.cfg.Configuration.doConfigure(Configuration.java:2263)
	at org.hibernate.cfg.Configuration.doConfigure(Configuration.java:2216)
	at org.hibernate.cfg.Configuration.configure(Configuration.java:2131)
	at org.hibernate.cfg.Configuration.configure(Configuration.java:2110)

原因の調査

ヒープ領域の問題のようなので、Eclipse Memory Analyzerを使用して原因を調べる

jpsコマンドでプロセスIDを確認
# jps
4089 Jps
12131 jar
jmapコマンドでヒープをダンプ
# jmap -dump:format=b,file=(出力ファイル名) (プロセスID)
Memory Analyzer for Eclipse IDEを取得

以下のサイトから入手。
Eclipse Memory Analyzer Open Source Project
既にダンプを取得しているのでEclipseのプラグインではなくRPC版を使用する。
任意の場所に展開したら「MemoryAnalyzer.exe」を起動

ファイルを開く

「File」->「Open Heap Dump...」から先程のファイルを選択

dominator treeを開く

「Open Dominator Tree for entire heap.」というボタンがあるので押す。
「Retained Heap」列でソートしてサイズの大きなクラスを展開していく。

f:id:yustam:20110725222819p:image

こんな感じ。
念のため一日置いて再度取得した結果。

f:id:yustam:20110725232010p:image

どうやらHibernateのSessionFactoryObjectFactoryクラスが原因みたい。