老项目,要求导出excel带上图片,我以为好简单的加上wSheet.addImage(),就放心摸鱼了,结果上线半年后,导出1000条数据就出现内存溢出,这个坑有点大,不想填,就把-xmx 开的6g,又过了半年,客户又说导出不行啊,实在没办法了,要把这坑给填了,毕竟他们的服务器才8g。 先上maven版本
<dependency>
<groupId>net.sourceforge.jexcelapi</groupId>
<artifactId>jxl</artifactId>
<version>2.6</version>
</dependency>
旧版本 WorkbookSettings,没有临时文件设置,有多少内存吃多少,内存异常正常,只能升级jxl包为2.6.12
<dependency>
<groupId>net.sourceforge.jexcelapi</groupId>
<artifactId>jxl</artifactId>
<version>2.6.12</version>
</dependency>
升级多了临时文件设置,
WorkbookSettings settings = new WorkbookSettings();
settings.setUseTemporaryFileDuringWrite(true);
settings.setTemporaryFileDuringWriteDirectory(new File("/opt/jxl_temp"));
完美解决问题。
原理好简单,不使用临时文件的情况,采用的是MemoryDataOutput实现,一直往内存写数据,使用临时文件,就是写文件的方式,不吃内存。
MemoryDataOutput
/**
* Writes the bytes to the end of the array, growing the array
* as needs dictate
*
* @param d the data to write to the end of the array
*/
public void write(byte[] bytes)
{
while (pos + bytes.length > data.length)
{
// Grow the array
byte[] newdata = new byte[data.length + growSize];
System.arraycopy(data, 0, newdata, 0, pos);
data = newdata;
}
System.arraycopy(bytes, 0, data, pos, bytes.length);
pos += bytes.length;
}
FileDataOutput
public FileDataOutput(File tmpdir) throws IOException
{
temporaryFile = File.createTempFile("jxl",".tmp", tmpdir);
temporaryFile.deleteOnExit();
data = new RandomAccessFile(temporaryFile, "rw");
}
/**
* Writes the bytes to the end of the array, growing the array
* as needs dictate
*
* @param d the data to write to the end of the array
*/
public void write(byte[] bytes) throws IOException
{
data.write(bytes);
}