jxl导出图片内存溢出

51 阅读1分钟

老项目,要求导出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);
}