我遇到了一个问题,我似乎无法解决,我需要你的帮助。
我正在生成一个PDF列表,我写入硬盘驱动器,一切都可以正常处理少量文件,但是当我开始生成更多文件时(通过for循环),创建停止了其他PDF文件没有创建。
我将Play Framework与PDF module一起使用,依赖于ITextRenderer生成PDF。
我通过添加输出以查看它停止的位置来解决问题(好吧,我相信它在这里),问题出在我打电话给.createPDF(os);
时。
起初,我只能创建16个文件,然后它会停止,但我创建了一个Singleton,它在Class实例中创建渲染器并重用同一个实例(为了避免添加字体和设置每次)我去了61个文件创建,但没有更多。
我虽然关于内存泄漏阻止了这个过程,但无法查看在哪里或如何正确找到它。
这是我的代码部分:
列出模型; //我从db查询中获得了一个MyModel列表,这个MyModel包含一个文件路径
List<InputStream> files = new ArrayList<InputStream>();
for (MyModel model : models) {
if (!model.getFile().exists()) {
model.generatePdf();
}
files.add(new FileInputStream(model.getFile()));
}
// generatePDF:
public void generatePdf() {
byte[] bytes = PDF.toBytes(views.html.invoices.pdf.invoice.render(this, due));
FileOutputStream output;
try {
File file = getFile();
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
if (file.exists()) {
file.delete();
}
output = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(output);
bos.write(bytes);
bos.flush();
bos.close();
output.flush();
output.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
如您所见,我尽力避免内存泄漏,但这还不够。
为了找到问题,我将PDF.toBytes以及该类中的所有后续调用替换为我的类中的复制/粘贴版本,并添加了输出。这就是我发现线程挂起createPDF
,行
更新1: 我有两个(缩进的)PlayFramework应用程序运行这些参数:
-Xms1024m -Xmx1024m -XX:PermSize=512m -XX:MaxPermSize=512m
我试图停止一个实例并重新执行PDF生成,但它并没有影响生成的文件数量,它停在相同数量的文件中。 我还尝试更新分配的记忆:
-Xms1536m -Xmx1536m -XX:PermSize=1024m -XX:MaxPermSize=1024m
完全没有变化。
有关信息,服务器具有 16 Gb RAM 。
cat /proc/cpuinfo :
model name : Intel(R) Core(TM) i5-2400 CPU @ 3.10GHz
cpu MHz : 3101.000
cpu cores : 4
cache size : 6144 KB
希望它有所帮助。
答案 0 :(得分:0)
嗯,我真的很惊讶这个bug与内存,内存泄漏或可用内存完全无关。
我很惊讶。
它与通过网址加载的图像相关,在同一服务器(本地)中加载了很长时间。删除该图像解决了问题。
我将制作一个base64编码的图像,它应该解决问题。
我仍然无法相信!
答案 1 :(得分:0)
该模块由JörgViola开发,我认为假设这方面的一切都很好是安全的。从IText库中,我也相信可以安全地假设一切都是安全的。
正如您所猜测的,瓶颈来自您的代码。有趣的是,不是某些内存没有得到妥善管理,而是来自网络请求,每次都会使PDF渲染变得越来越慢,直到它最终失败。
很高兴你终于让它发挥作用了。