JVM 堆不断增加。为什么?
JVM heap keeps Increasing. why?
executor = Executors.newScheduledThreadPool(1);
Runnable helloRunnable = new Runnable() {
public void run() {
controller2.GetAIntFromDatabase(columblName);
}
};
executor.scheduleAtFixedRate(helloRunnable, 0, 10, TimeUnit.MILLISECONDS);
这部分程序产生堆内存递增错误。
controller2.GetAIntFromDatabase(columblName);
使用此函数,我从数据库中读取了一个 int 值。
@Override
public int GetAIntFromDatabase(String columblName) {
int stare = 0;
try{
String query = "SELECT * FROM stari ORDER BY id DESC LIMIT 1";
PreparedStatement preparedStatement = this.connnection.prepareStatement(query);
ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next()){
stare = resultSet.getInt(columblName);
preparedStatement.close();
resultSet.close();
return stare;
}
preparedStatement.close();
resultSet.close();
}catch (SQLException ex) {
System.out.println("GetUtilajStare Error: " + ex);
return 0;
}
return 0;
}
这是 Java 10 分钟后 运行 的堆内存使用情况:
为什么我的堆内存一直在增加?
如果打开preparedStatement
和resultSet
后抛出异常,则永远不会关闭。因此,您应该使用将始终执行的 finally
块。
public int GetAIntFromDatabase(String columblName) {
int stare = 0;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
String query = "SELECT * FROM stari ORDER BY id DESC LIMIT 1";
preparedStatement = this.connnection.prepareStatement(query);
resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
stare = resultSet.getInt(columblName);
return stare;
}
} catch (SQLException ex) {
System.out.println("GetUtilajStare Error: " + ex);
return 0;
} finally {
if (preparedStatement != null)
preparedStatement.close();
if (resultSet != null)
resultSet.close();
}
return 0;
}
您应该使用 Java 7+ 关闭资源的方式,try-with-resources。
The try-with-resources statement is a try
statement that declares one or more resources. A resource is an object that must be closed after the program is finished with it. The try-with-resources statement ensures that each resource is closed at the end of the statement. Any object that implements AutoCloseable
, which includes all objects which implement Closeable
, can be used as a resource.
public int GetAIntFromDatabase(String columblName) {
final String query = "SELECT * FROM stari ORDER BY id DESC LIMIT 1";
try (final PreparedStatement preparedStatement = this.connnection.prepareStatement(query)) {
final ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
return resultSet.getInt(columblName);
}
return 0;
} catch (SQLException ex) {
// Do something better than System.out.println(...)
return 0;
}
return 0;
}
此外,您不必显式关闭结果集,准备好的语句会按原样执行 owns the result set:
When a Statement
object is closed, its current ResultSet
object, if one exists, is also closed.
但是,如果您想变得偏执并矫枉过正,正如@MarkRotteveel 在他的评论中建议的那样,您可以将 ResultSet
也添加为 AutoCloseable
资源,然后代码将看起来像这样:
public int GetAIntFromDatabase(String columblName) {
final String query = "SELECT * FROM stari ORDER BY id DESC LIMIT 1";
try (final PreparedStatement preparedStatement = this.connnection.prepareStatement(query);
final ResultSet resultSet = preparedStatement.executeQuery()
) {
...
}
我从未做过,也从不需要它,文档明确指出不需要,但有些人在某些极端情况下遇到过问题。
在第二种情况下,特别明显的是 try-with-resources 为您节省了多少 - 您不需要将变量分配给 null
,您不必检查它们是否有被打开,即使其中一个close()
方法抛出异常,"closing chain"并没有被破坏,无论如何都会调用其他资源的close()
方法。
executor = Executors.newScheduledThreadPool(1);
Runnable helloRunnable = new Runnable() {
public void run() {
controller2.GetAIntFromDatabase(columblName);
}
};
executor.scheduleAtFixedRate(helloRunnable, 0, 10, TimeUnit.MILLISECONDS);
这部分程序产生堆内存递增错误。
controller2.GetAIntFromDatabase(columblName);
使用此函数,我从数据库中读取了一个 int 值。
@Override
public int GetAIntFromDatabase(String columblName) {
int stare = 0;
try{
String query = "SELECT * FROM stari ORDER BY id DESC LIMIT 1";
PreparedStatement preparedStatement = this.connnection.prepareStatement(query);
ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next()){
stare = resultSet.getInt(columblName);
preparedStatement.close();
resultSet.close();
return stare;
}
preparedStatement.close();
resultSet.close();
}catch (SQLException ex) {
System.out.println("GetUtilajStare Error: " + ex);
return 0;
}
return 0;
}
这是 Java 10 分钟后 运行 的堆内存使用情况:
为什么我的堆内存一直在增加?
如果打开preparedStatement
和resultSet
后抛出异常,则永远不会关闭。因此,您应该使用将始终执行的 finally
块。
public int GetAIntFromDatabase(String columblName) {
int stare = 0;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
String query = "SELECT * FROM stari ORDER BY id DESC LIMIT 1";
preparedStatement = this.connnection.prepareStatement(query);
resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
stare = resultSet.getInt(columblName);
return stare;
}
} catch (SQLException ex) {
System.out.println("GetUtilajStare Error: " + ex);
return 0;
} finally {
if (preparedStatement != null)
preparedStatement.close();
if (resultSet != null)
resultSet.close();
}
return 0;
}
您应该使用 Java 7+ 关闭资源的方式,try-with-resources。
The try-with-resources statement is a
try
statement that declares one or more resources. A resource is an object that must be closed after the program is finished with it. The try-with-resources statement ensures that each resource is closed at the end of the statement. Any object that implementsAutoCloseable
, which includes all objects which implementCloseable
, can be used as a resource.
public int GetAIntFromDatabase(String columblName) {
final String query = "SELECT * FROM stari ORDER BY id DESC LIMIT 1";
try (final PreparedStatement preparedStatement = this.connnection.prepareStatement(query)) {
final ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
return resultSet.getInt(columblName);
}
return 0;
} catch (SQLException ex) {
// Do something better than System.out.println(...)
return 0;
}
return 0;
}
此外,您不必显式关闭结果集,准备好的语句会按原样执行 owns the result set:
When a
Statement
object is closed, its currentResultSet
object, if one exists, is also closed.
但是,如果您想变得偏执并矫枉过正,正如@MarkRotteveel 在他的评论中建议的那样,您可以将 ResultSet
也添加为 AutoCloseable
资源,然后代码将看起来像这样:
public int GetAIntFromDatabase(String columblName) {
final String query = "SELECT * FROM stari ORDER BY id DESC LIMIT 1";
try (final PreparedStatement preparedStatement = this.connnection.prepareStatement(query);
final ResultSet resultSet = preparedStatement.executeQuery()
) {
...
}
我从未做过,也从不需要它,文档明确指出不需要,但有些人在某些极端情况下遇到过问题。
在第二种情况下,特别明显的是 try-with-resources 为您节省了多少 - 您不需要将变量分配给 null
,您不必检查它们是否有被打开,即使其中一个close()
方法抛出异常,"closing chain"并没有被破坏,无论如何都会调用其他资源的close()
方法。