我对PDFBox 2.0.1有一个问题,因为它无法呈现PDF。如果PDFBox在几个文件上失败,我真的不在乎,但问题是整个线程挂起并且几分钟内都没有返回,内存不断积累,看起来似乎并未结束
问题似乎与gridimg.setOnClickListener(this);
llm = new LinearLayoutManager(ProductListActivity.this);
rv = (RecyclerView)findViewById(R.id.recycler_viewproduts);
rv.setLayoutManager(llm);
有关,这就是我所说的:
gridimg.setOnClickListener(this);
llm = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
rv = (RecyclerView)findViewById(R.id.recycler_viewproduts);
rv.setLayoutManager(llm);
代码卡在该特定行上并消耗CPU和内存。在netbeans中,每当我暂停执行时,我都会看到这个堆栈跟踪。虽然我不确定发生了什么,因为我看到PDFBox工作但似乎已经遇到某种无限循环。
有问题的PDF可以从以下网址下载:https://drive.google.com/file/d/0B5zMlyl8rHwsY3Y1WjFVZlllajA/view?usp=sharing
有人可以帮忙吗?
答案 0 :(得分:3)
您使用的是java 8还是Java 9?正如here所解释的那样,使用以下选项启动java:
-Dsun.java2d.cmm=sun.java2d.cmm.kcms.KcmsServiceProvider
这与JDK8 / 9改变了他们的色彩管理系统有关。
文件渲染速度仍然很慢(20-30秒),因为它非常复杂。
(顺便说一下渲染没有挂起。它只花了很长时间,即几分钟)
自PDFBox 2.0.9以来的新功能:您提到了您正在创建缩略图。您现在可以使用PDFRender.setSubsamplingAllowed(true)
启用子采样,这将减少用于图像的内存。
答案 1 :(得分:0)
该问题可以在Java 8 VM中重现。正如@Tilman在他的回答中已经提到的那样,这是Java 8使用与以前的Java版本不同的颜色管理系统引入的问题。
使用新的颜色管理系统分析虚拟机行为,很明显该问题实际上并不是内存泄漏问题(由于内存使用过多而推测);相反,对象的实例化速度比垃圾收集可以收集和释放未使用的对象更快!
通过更改PDFStreamEngine.processStreamOperators(PDContentStream)
中页面内容解析的主循环,可以允许抓取垃圾回收:
int i = 1; // new
while (token != null)
{
if (token instanceof COSObject)
{
arguments.add(((COSObject) token).getObject());
}
else if (token instanceof Operator)
{
processOperator((Operator) token, arguments);
arguments = new ArrayList<COSBase>();
}
else
{
arguments.add((COSBase) token);
}
token = parser.parseNextToken();
if (i++ % 1000 == 0) // new
Runtime.getRuntime().gc(); // new
}
(1000
是我凭空选择的任意值。)
这仍然很慢但最终会创建位图而不会占用过多的内存。
因此,它看起来像旧的颜色管理系统实例化的方式更少的临时对象和/或明确允许垃圾收集介入。
PS: 上方的更改不会加快速度。它只是阻止了过多的内存使用观察到的OP以及在我的测试设置中导致了OutOfMemory情况。
如果OP完全控制部署环境,他确实应该使用@Tilman在他的回答中显示的选项。但是,如果OP没有,例如如果他最终部署到Web服务器上,他不管理,如果管理员不想添加到JVM启动选项,他至少可以防止过多的内存使用。