Java 为什么这段代码运行得越来越慢?

Java 为什么这段代码运行得越来越慢?,java,hibernate,Java,Hibernate,我有一个名为SrcFile的实体类,其中一列是: @NotNull @Lob private Byte[] data; 此SrcFile与报表实体具有一对一关系 从Report.java: @OneToOne private SrcFile srcFile; 持久化SrcFile实体非常有效 srcFileHomeFacade.clearInstance(); SrcFile srcFile = srcFileHomeFacade.getInstance(); byte[] bArray =

我有一个名为
SrcFile
的实体类,其中一列是:

@NotNull
@Lob
private Byte[] data;
SrcFile
与报表实体具有一对一关系

从Report.java:

@OneToOne
private SrcFile srcFile;
持久化
SrcFile
实体非常有效

srcFileHomeFacade.clearInstance();
SrcFile srcFile = srcFileHomeFacade.getInstance();
byte[] bArray = resource.getBytesForSource();
srcFile.setData(ReportFileResource.toObject(bArray));
System.out.println("````````````````srcFile data length: "+bArray.length);
srcFileHomeFacade.persist();
当我坚持使用
Report
时,问题就出现了

我有:

并且运行得很好,但是在多次运行此代码之后,它变得越来越慢(甚至会引起GC开销错误),经过数小时的调查,我发现这个
报告.setSrcFile(srcFile)
就是问题所在

不知何故,报告不喜欢引用如此多的
srcFile.data

你看到原因了吗

如果我注释
report.setSrcFile
所有的工作都很好(除了报告表中的SRCFILE\u ID将为空,但它只是用于测试)。请注意,数据长度约为100.000

注意:如果我没有保存任何
报告
,而只保存
srcFile
实体,我就没有问题。 更新


“越来越慢地运行”解释:此代码用于将某些pcl转换为PDF,因此
数据
包含pcl的来源,每次都不同。在转换了大约100个PCL之后,这个过程变得越来越慢,对于VM,我发现这个字节[]数组占用了大量MB内存。同样,这肯定不是IO的问题,而是关于报表实体上的setSrcFile的问题,VisualVM也指出了这一点。

我仍然有点不确定,但我怀疑您的问题与您持久化事物和处理实体对象的方式有关:如果您在持久化实体后正确丢弃它们,GC应该经常释放内存,以保持系统平稳运行。特别是如果在每个事务之后使用flush()或commit(),则内存使用量应该不会持续增加太多。然而,在您的例子中,似乎所有的实体都保存在内存中,即使它们不再需要——所以资源没有被释放肯定是有原因的

您是否有可能使用一个for循环来迭代一组src文件,并将所有persist()调用直接包含在其中?如果是这样,您的问题可能与范围有关。您可以尝试将循环的内容提取到新方法,以便在每次迭代后正确释放所有局部变量

您还可以通过设置CascadeType.PERSIST或CascadeType.ALL并对报表使用一个PERSIST()操作来保存这两个对象,从而改善情况。FetchType.LAZY也可能有帮助


在任何情况下:寻找可能的原因,为什么您的程序会将所有实体直接保存在内存中,而不是将它们保存到数据库中,然后忘记它们

我记得Blob的本机JDBC接口可能很棘手,需要手动关闭供应商对象。如果错过了这一步,BLOB就会在JDBC驱动程序上积累(即在JVM内存中),最终JVM就会停止


我想知道您是否需要任何特定于供应商的属性或步骤来在保存后关闭blob。

我会说,因为它是Java:p@ThiefMaster:非常有用;)请澄清:您所说的“多次运行”是什么意思:您是否多次坚持同一实体?程序是否仅在持久化或读取数据时运行较慢?写入数据时是否运行读取操作?您是在同一个报表上设置不同的文件,还是在同一个报表中始终设置同一个文件?你设置了什么类型?你是使用懒惰加载还是急切加载?@weltraumpirat我刚刚更新了这个问题。我没有在实体字段上指定任何级联类型。我只是在这里发布了它们,就像我在源代码中发布的一样……考虑到问题中缺乏细节,这听起来很有可能。谢谢你的详细回答。我使用的是seam,我用@Transactional注释了实现持久化的方法,所以所有事务管理和组件发布都是由seam完成的。。。我会尝试使用CascadeType。坚持。这太棒了。它与CascadeType.PERSIST和FetchType.LAZY一起工作……这是否意味着在持久化报表后,如果报表仍在内存中,则不会分离SRC文件?如果是的话,这一切都是有意义的,因为它非常巨大。。。。
report.setSrcFile(srcFile);
reportHomeFacade.persist();