可以在Java 8 VM中重现该问题。 正如@Tilman在他的回答中已经提到的,这是Java 8使用与以前的Java版本不同的颜色管理系统引入的一个问题。
通过使用新的色彩管理系统分析VM行为,可以清楚地发现问题实际上并不是内存泄漏问题(可能是由于过多的内存使用造成的)。 相反,实例化对象的速度快于垃圾回收可以收集和释放未使用的对象的速度!
通过更改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();
}
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启动选项中,则他至少可以防止过多的内存使用。