我使用的是hsqldb版本2.3.1或2.3.2(两者都有问题)。
我有代码,我在其中对数据库执行了大量插入操作,并且我清理了所有可能的资源 - 但是我注意到调用execute on语句会导致内存永远不会消失 - 尽管如此,我关闭准备好的声明,连接等......
以下是您可以在您的计算机上运行并验证的代码(在java默认堆大小上运行它,OutOfMemory应该在不到5分钟内出现):
Connection c = DriverManager.getConnection("jdbc:hsqldb:mem:a");
PreparedStatement ps = c.prepareStatement("set database sql syntax ora true");
ps.execute();
ps.close();
ps = c.prepareStatement("create table t (x varchar2(1000 char))");
ps.execute();
ps.close();
c.close();
String str = "abcdefghijklmnopqrstuvwxyz";
str = str + str + str + str + str; //just a long string to rapid the outcome
String x = String.format("insert into t values('%s')",str);
for(int i=0;i<1000*1000*1000;i++){
c = DriverManager.getConnection("jdbc:hsqldb:mem:a");
ps = c.prepareStatement(x);
ps.executeUpdate(); //if I remove this line, there is no memory leak
ps.clearParameters();//I really try to clean every possible thing
ps.clearWarnings();//really try
ps.cancel();//cancel it even
ps.close();//close it of course
ps = null;//nullify to hint the GC
c.rollback(); //Rollback so that memory isn't even used inside the hsqldb
c.close();//close the connection even
if(i%100000 == 0){//Every once in a while a report about heap condition
System.gc();//perform gc
System.out.println(Runtime.getRuntime().freeMemory()/1024/1024);//in MB
}
}
如果您运行代码,定期打印将打印可用的可用内存 - 这将逐渐减少直到OutOfMemory。
正如你所看到的,我尝试过关闭,回滚,无效等等 - 似乎没什么用。
使用JvisualVM,大多数内存都是byte []。
如果我是对的并且这是一个错误,我正在寻找一种解决方法。有什么建议?我做错了吗?
谢谢
答案 0 :(得分:3)
请在此处阅读http://hsqldb.org/doc/guide/dbproperties-chapt.html关于关机的信息。
如果未指定,即使您关闭内存数据库中HSQL的最后一个连接,数据库本身也不会被破坏并保留在内存中。您正在添加此数据库中的每个插入新行,并且它会增长。
如果数据库不能保留,那么你永远不能插入,因为在你创建数据库和表t
之后你关闭了连接,然后在重新打开之后,表就应该消失了,不管它。 / p>
如果您是第一次打开它,可以在最后一次连接关闭后强制关闭数据库:
Connection c = DriverManager.getConnection("jdbc:hsqldb:mem:a;shutdown=true");
但是现在你不能再插入了,因为在新getConnection
之后你的桌子不存在。
关闭数据库并释放所有内存的另一种可能性是HSQL的SQL命令SHUTDOWN
:
c.createStatement().execute("SHUTDOWN");
如果您正在处理更大的数据,您的第一个选择应该是在文件系统中使用基于光盘的CACHED表创建HSQL数据库。然后它的内存占用量不会随着内存中的数据而增长。