去年夏天,我制作了一个 Java 应用程序,它可以解析一些 PDF 文件并获取它们包含的信息并将其存储在 SQLite 数据库中。
一切都很好,我每周左右都会向数据库添加新文件,没有任何问题。
现在,我正在尝试提高应用程序的速度,我想看看如果我在新数据库中解析过去两年的所有文件,效果会如何。那是我开始收到此错误的时候:OutOfMemoryError:Java 堆空间。我之前没有得到它,因为我每周只解析大约 25 个新文件,但似乎逐个解析 1000 多个文件要求更高。
我部分解决了这个问题:我确保在每次调用数据库后关闭连接,并且错误消失,但代价高昂。现在解析文件的速度慢得难以忍受。至于我的结果集和语句/准备语句,我已经在每次调用后关闭它们。
我想我不明白什么时候应该关闭连接以及什么时候应该继续重复使用同一个连接。我认为,由于自动提交已打开,因此它会在每个事务(选择、更新、插入等)之后提交,并且连接会释放它正在使用的额外内存。我可能是错的,因为当我解析太多文件时,我最终会收到我提到的错误。
一个简单的解决方案是在每次 x 调用后关闭它,但我又不明白为什么,以后可能会遇到相同的错误。谁能解释一下我什么时候应该关闭我的连接(如果有的话,除了我完成时之外)?如果我只应该在完成后执行此操作,那么有人可以解释我应该如何避免此错误吗?
顺便说一句,我没有将其标记为 SQLite,因为当我尝试在在线 MySQL 数据库上运行我的程序时,我遇到了同样的错误。
Edit正如德科和马夫拉夫所指出的,也许问题不在于我的连接。也许是文件的问题,所以我将把我用来调用函数解析文件的代码一一贴出来:
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,playersDatabase);
我认为该方法完成后应该释放内存吗?