【发布时间】:2012-04-16 13:16:36
【问题描述】:
当我在分析器中运行以下代码时,我会得到一个 char[] 和 byte[] ,直到程序由于 java 堆内存不足异常而崩溃。有人能告诉我为什么吗?也许我在做一些根本错误的事情。
package testleak;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import javax.swing.Timer;
public class TestLeak
{
static String DB_USERNAME = "userName";
static String DB_SUBSCRIPTION_EXPIRATION = "subscriptionExpiration";
static String DB_REMOTE_ACCESS_ENABLED = "remoteAccessEnabled";
static String DB_LOCAL_USERNAME = "root";
static String DB_LOCAL_PASS = "root";
public static void main(String[] args)
{
Timer timer = new Timer(2000, new ActionListener()
{
@Override
public void actionPerformed(ActionEvent evt)
{
TestLeak tester = new TestLeak();
try
{
tester.go();
}
catch (NumberFormatException n)
{
}
tester = null;
}
});
timer.start();
while (true)
{
//keep the program from ending...
}
}
private void go() throws NumberFormatException
{
ResultSet results = null;
Connection conn = null;
Properties connectionProps = new Properties();
try
{
connectionProps.put("user", "root");
connectionProps.put("password", "root");
conn = DriverManager.getConnection("jdbc:mysql://localhost:8889/myDataBase",
connectionProps);
connectionProps = null;
try
{
String rawQuery = new String("SELECT " + TestLeak.DB_USERNAME + ", "
+ TestLeak.DB_REMOTE_ACCESS_ENABLED
+ ", " + TestLeak.DB_SUBSCRIPTION_EXPIRATION + " FROM myTable");
Statement statement = conn.createStatement();
try
{
statement.executeQuery(rawQuery);
results = statement.getResultSet();
rawQuery = null;
try
{
while (results.next())
{
String auth = new String(results.getString(TestLeak.DB_REMOTE_ACCESS_ENABLED));
if (auth.equals("1"))
{
Long subExpires = Long.valueOf(results.getString(TestLeak.DB_SUBSCRIPTION_EXPIRATION));
if (subExpires > System.currentTimeMillis())
{
System.out.println(results.getString(TestLeak.DB_USERNAME));
System.out.println();
}
subExpires = null;
}
auth = null;
}
}
finally
{
results.close();
}
}
finally
{
statement.close();
}
}
finally
{
conn.close();
}
}
catch (SQLException e)
{
System.out.println(e.getMessage());
}
}
}
我想我正在释放所有东西,但一定有什么东西阻止了所有对象被释放。为什么 go() 方法结束时所有对象都没有资格进行垃圾回收?每次我在分析器中调用垃圾收集时,我都会得到另一代幸存者。 谢谢。
【问题讨论】:
-
所以...把它放在调试器中,找出问题所在。
-
SQLException 捕获块位于清理 JDBC 资源的 finally 块之外。你得到任何 SQLExceptions 吗?附带说明一下,有一些方法可以清理 JDBC 资源,而不必像这样嵌套 try/catch/finally 块。这将使代码更易于阅读。
-
确保那些
.close确实被调用了。此外,我认为那些“关闭”语句需要在他们自己的 try-catch 中,否则第一次失败会导致其余的不执行?我相信在您的情况下,您应该在您的catch下方有一个finally,并在那里处理(您的ResultSet、Statement和Connection)的清理。 -
while(true) 确实是个坏主意,因为它使您的线程保持运行。您应该在同步块中调用 wait()
-
运行它时我没有遇到任何异常。会不会是while(true)??有人可以给我一个基本示例,说明如何通过调用 wait() 来运行它吗?
标签: java mysql loops jdbc memory-leaks