【发布时间】:2012-03-05 04:56:30
【问题描述】:
去年夏天,我制作了一个 Java 应用程序,它可以解析一些 PDF 文件并获取其中包含的信息以将它们存储在 SQLite 数据库中。
一切都很好,我每周左右都在向数据库中添加新文件,没有任何问题。
现在,我正在尝试提高我的应用程序的速度,我想看看如果我在一个新数据库中解析过去两年的所有文件,它会如何运行。那时我开始收到此错误:OutOfMemoryError: Java Heap Space。我之前没搞明白,因为我每周只解析大约 25 个新文件,但似乎一个接一个地解析 1000 多个文件要求更高。
我部分解决了这个问题:我确保在每次调用数据库后关闭我的连接并且错误消失了,但代价是巨大的。解析文件现在慢得令人难以忍受。至于我的 ResultSets 和 Statements / PreparedStatements,我已经在每次通话后关闭它们。
我想我不明白什么时候应该关闭我的连接,什么时候应该继续重复使用同一个连接。我认为由于自动提交已打开,它会在每个事务(选择、更新、插入等)之后提交,并且连接会释放它正在使用的额外内存。我可能错了,因为当我解析太多文件时,我最终得到了我提到的错误。
一个简单的解决方案是在每次调用 x 后关闭它,但我又不明白为什么,以后可能会遇到同样的错误。谁能解释我什么时候应该关闭我的连接(如果有的话,除非我完成了)?如果我只应该在完成后才这样做,那么有人可以解释我应该如何避免这个错误吗?
顺便说一句,我没有将其标记为 SQLite,因为当我尝试在我的在线 MySQL 数据库上运行我的程序时遇到了同样的错误。
编辑 正如 Deco 和 Mavrav 所指出的,问题可能不是我的 Connection。可能是文件的问题,所以我把我用来调用函数解析文件的代码一一贴出来:
public static void visitAllDirsAndFiles(File dir){
if (dir.isDirectory()){
String[] children = dir.list();
for (int i = 0; i < children.length; i++){
visitAllDirsAndFiles(new File(dir, children[i]));
}
}
else{
try{
// System.out.println("File: " + dir);
BowlingFilesReader.readFile(dir, playersDatabase);
}
catch (Exception exc){
System.out.println("Other exception in file: " + dir);
}
}
}
因此,如果我使用目录调用该方法,它会使用我刚刚创建的 File 对象再次递归调用该函数。然后我的方法检测到它是一个文件并调用 BowlingFilesReader.readFile(dir, playerDatabase);
我认为方法完成后应该释放内存?
【问题讨论】:
-
连接可能不是错误的确切原因。 PDF 文件的平均大小是多少?您是否一次将所有 1000 个文件加载到内存中?尝试一一加载。
-
确保每次将 PDF 文件的引用存储在新数据库中时都会发布它。您可能一次将 1000 个文件全部加载到内存中,这会导致您的 OOME。您是否也使用分析器检查过它?
-
@mavrav 有关我如何加载文件的详细信息,请参阅已编辑的问题。平均可能是 300kb(从 175kb 到大约 1.2mb)
-
@Deco 有关我如何加载文件的详细信息,请参阅已编辑的问题。至于探查器,我不知道如何使用它,我尝试查看它,当我尝试一段时间后,我最终看到了数字和所有内容,但我不知道它们如何指示问题可能出在哪里。 ..
-
在
BowlingFilesReader.readFile();中,您是否使用.close()方法关闭BufferedReader(或您正在使用的任何东西)?File对象不应该是问题,因为这只是文件的路径而不是文件本身。如果有的话,那就是您用来读取未正确关闭的文件的文件
标签: java database connection database-connection