我有一个名为SrcFile
的实体类,其中一个列是:
@NotNull
@Lob
private Byte[] data;
此SrcFile
与报表实体具有OneToOne关系。
来自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
时会出现问题。
我做:
report.setSrcFile(srcFile);
reportHomeFacade.persist();
并且工作得很好但是在多次运行此代码之后会变得越来越慢(即使它会引发GC开销错误)并且经过数小时的调查后我发现这个report.setSrcFile(srcFile)
是问题所在
不知何故报道不喜欢引用srcFile.data
...
你看到原因吗?
如果我评论report.setSrcFile
一切都很好(除了报告表中的SRCFILE_ID为空,但它只是用于测试)。请注意,数据长度约为100.000。
注意:如果我没有保留任何report
但只保留srcFile
个实体,我就没有问题。
的更新:
“运行速度越来越慢”解释:调用此代码将一些pcl转换为pdfs,因此data
包含pcl的来源,每次都不同。转换大约100个pcls后,进程变得越来越慢,使用VM我发现这个byte []数组占用了大量的MB内存。同样,它绝对不是关于IO的问题,但关于报告实体上的这个setSrcFile,VisualVM也表明了这一点。
答案 0 :(得分:2)
我仍然有点不确定,但我怀疑你的问题与你持久化和处理实体对象的方式有关:如果你的实体在持久存在后正确地丢弃它们,GC应该经常释放内存以保持你的系统运行顺畅。特别是如果你在每次事务后使用flush()或commit(),你的内存使用量应该不会累积太多。但是,在您的情况下,似乎所有实体即使在不再需要之后也会保留在内存中 - 因此必须有一些原因可以解释为什么资源不会被释放。
你是否有机会使用单个for循环迭代一组srcFiles并直接在其中调用所有persist()?如果是这样,您的问题可能与范围有关。您可以尝试将循环的内容提取到一个新方法,以便在每次迭代后正确释放所有局部变量。
您也可以通过设置CascadeType.PERSIST或CascadeType.ALL并在报表上使用单个persist()操作来保存两个对象,从而改进。 FetchType.LAZY也可能会有所帮助。
在任何情况下:查找程序将所有实体直接保留在内存中的可能原因,而不是将它们保存到数据库中,然后忘记它们。
答案 1 :(得分:0)
我记得BLOB的原生JDBC接口可能很棘手,需要手动关闭()供应商对象。如果错过了这一步,则BLOB会在JDBC驱动程序上积累(即在JVM内存中),最终JVM也会在OOM中累积。
我想知道您是否需要任何供应商特定的属性或步骤来保存后关闭BLOB。