Java, Apache-poi, memory-leak-mit-excel-Dateien
Ich Lesen müssen, (15000) excel-Dateien für meine Diplomarbeit. Ich bin mit apache poi, um zu öffnen und später zu analysieren, Sie aber nach rund 5000 Dateien, ich bekomme die folgende exception und stacktrace:
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
at org.apache.xmlbeans.impl.store.Cur$CurLoadContext.attr(Cur.java:3044)
at org.apache.xmlbeans.impl.store.Cur$CurLoadContext.attr(Cur.java:3065)
at org.apache.xmlbeans.impl.store.Locale$SaxHandler.startElement(Locale.java:3263)
at org.apache.xmlbeans.impl.piccolo.xml.Piccolo.reportStartTag(Piccolo.java:1082)
at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.parseAttributesNS(PiccoloLexer.java:1822)
at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.parseOpenTagNS(PiccoloLexer.java:1521)
at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.parseTagNS(PiccoloLexer.java:1362)
at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.yylex(PiccoloLexer.java:4682)
at org.apache.xmlbeans.impl.piccolo.xml.Piccolo.yylex(Piccolo.java:1290)
at org.apache.xmlbeans.impl.piccolo.xml.Piccolo.yyparse(Piccolo.java:1400)
at org.apache.xmlbeans.impl.piccolo.xml.Piccolo.parse(Piccolo.java:714)
at org.apache.xmlbeans.impl.store.Locale$SaxLoader.load(Locale.java:3479)
at org.apache.xmlbeans.impl.store.Locale.parseToXmlObject(Locale.java:1277)
at org.apache.xmlbeans.impl.store.Locale.parseToXmlObject(Locale.java:1264)
at org.apache.xmlbeans.impl.schema.SchemaTypeLoaderBase.parse(SchemaTypeLoaderBase.java:345)
at org.apache.poi.POIXMLTypeLoader.parse(POIXMLTypeLoader.java:92)
at org.openxmlformats.schemas.spreadsheetml.x2006.main.WorksheetDocument$Factory.parse(Unknown Source)
at org.apache.poi.xssf.usermodel.XSSFSheet.read(XSSFSheet.java:173)
at org.apache.poi.xssf.usermodel.XSSFSheet.onDocumentRead(XSSFSheet.java:165)
at org.apache.poi.xssf.usermodel.XSSFWorkbook.parseSheet(XSSFWorkbook.java:417)
at org.apache.poi.xssf.usermodel.XSSFWorkbook.onDocumentRead(XSSFWorkbook.java:382)
at org.apache.poi.POIXMLDocument.load(POIXMLDocument.java:178)
at org.apache.poi.xssf.usermodel.XSSFWorkbook.<init>(XSSFWorkbook.java:249)
at org.apache.poi.xssf.usermodel.XSSFWorkbook.<init>(XSSFWorkbook.java:302)
at de.spreadsheet_realtions.analysis.WorkbookAnalysis.analyze(WorkbookAnalysis.java:18)
Code (im moment nur die Datei öffnen und schließen Sie die Datei):
public static void main(String[] args) {
start();
}
public void start(){
File[] files = getAllFiles(Config.folder);
ZipSecureFile.setMinInflateRatio(0.00);
for(File f: files){
analyze(f);
}
}
public void analyze(File file){
Workbook workbook = null;
try {
workbook = new XSSFWorkbook(file); //line 18
} catch (Exception e1) {e1.printStackTrace(); return;}
// later would be here the code to analyze the workbook
try {
workbook.close();
} catch (Exception e) {e.printStackTrace();}
}
Versuchte ich auch, mit OPCPackage.open(Datei) und habe das gleiche Ergebnis.
Was mache ich falsch oder was kann ich tun, um dieses problem zu lösen? Vielen Dank für jede Hilfe.
BEARBEITEN:
Das gleiche für den folgenden code.
try (XSSFWorkbook workbook = new XSSFWorkbook(file)){
} catch (Exception e1) {e1.printStackTrace(); return;}
- Es könnte sein, eine sehr große Datei, die Ursachen einer OOM basierend auf den Speicher Einstellungen, die Sie definieren, für die Sie java-Prozess. Können Sie versuchen zu laufen, nur mit der einen Datei, wo die OOM passiert, und sehen, ob dies allein schon löst das OOM?
- Ja, es ist eine große Datei (42mb) und whiteout diese Datei, es funktioniert 🙂 danke.
Du musst angemeldet sein, um einen Kommentar abzugeben.
In der Regel, POI hat die ganze Arbeitsmappe im Arbeitsspeicher. Also, eine große Arbeitsmappe erfordert einen anderen Ansatz.
Während schreiben, kann man SXSSF und die meisten Aufrufe sind die gleichen, außer, dass nur eine bestimmte Anzahl von Zeilen im Speicher.
In Ihrem Fall, Sie sind Lesen. Für diese können Sie verwenden, Ihren "event driven" - API. Die grundlegende Idee hier ist, dass Sie nicht bekommen, die Arbeitsmappe als ein riesiges Objekt. Stattdessen bekommt man es Stück für Stück, wie es gelesen wird, und Sie können sparen Sie so viel wie Sie möchten in Ihre eigenen Daten-Struktur. Oder Sie können einfach verarbeiten, wie Sie es Lesen und nicht speichern, sehr viel.
Da dies eine untere-level-API (angetrieben durch die Struktur der gelesenen Daten), gibt es einen Ansatz für XLS und einen anderen Ansatz für XLSX. Blick auf die POI "How To" - Seite, und suchen Sie den Abschnitt mit dem Titel "XSSF und SAX (Event, API)".
Dieses Beispiel zeigt, wie Sie erkennen den Wert jeder Zelle, wie es gelesen wird.
(Sie müssen die xercesImpl.jar auf Ihrem library-Pfad).
Im Falle einer Ausnahme in der ersten try-block, kehren Sie, so dass Sie würde nicht schließen Sie die Arbeitsmappe.
Setzen, die in der Nähe in einem
finally
block.Oder, besser, mit try-mit-Ressourcen.