我正在尝试使用apache POI 3.10将Excel文件(xlsx)加载到工作簿对象中。
我收到一个java.lang.OutofMemoryError。
我在JVM上使用带有-Xmx2g参数的Java 8。
当我运行程序时,所有4个内核(64位系统)和我的RAM(4gb)都已用完。
Excel工作表具有43列和166,961行,等于7,179,323个像元。
我正在使用Apache POIs WorkBookFactory.create(new File),因为它比使用InputFileStream占用更少的内存。
是否有人对如何优化内存使用或创建工作簿的其他方式有任何想法?
下面是我的测试Reader类,不要判断,它很粗糙,并且包含调试语句:
import java.io.File;
import java.io.IOException;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
public class Reader {
private Workbook wb;
public Reader(File excel) {
System.out.println("CONSTRUCTOR");
wb = null;
try {
wb = WorkbookFactory.create(excel);
} catch (IOException e) {
System.out.println("IO Exception");
System.out.println(e.getMessage());
} catch (InvalidFormatException e) {
System.out.println("Invalid Format");
System.out.println(e.getMessage());
}
}
public boolean exists() { return (wb != null); }
public void print() {}
public static void main(String[] args) {
System.out.println("START PRG");
//File f = new File("oldfilename.xls");
File f = new File("filename.xlsx");
System.out.println("PATH:" + f.getAbsoluteFile());
if (!f.exists()) {
System.out.println("File does not exist.");
System.exit(0);
}
System.out.println("FILE");
Reader r = new Reader(f);
System.out.println("Reader");
r.print();
System.out.println("PRG DONE");
}
}
最佳答案
显然,加载24mb文件不应该引起OOM ...
乍一看,虽然Xmx设置为2G,但实际上系统中没有多少可用内存。换句话说,操作系统和其他进程可能已经占用了4G物理内存中的2G以上!首先检查可用的物理内存。如果可用情况低于预期,请尝试关闭其他一些正在运行的应用程序/进程。
如果不是这种情况,并且确实有足够的内存,那么不进行概要分析就很难确定真正的原因。使用配置文件工具检查与内存相关的JVM状态。您可以简单地使用jconsole(JDK随附)。 @请参见this on how to activate JMX
连接后,检查与内存相关的读数,尤其是在内存空间下方:
老一代
年轻一代
烫发
监视这些空间,看看它在哪里挣扎。我认为这是一个独立的应用程序。如果将其部署在服务器(作为Web或服务)上,则可以考虑使用“ -XX:NewRatio”选项来有效地分配堆空间。 @see调整相关详细信息here。