Куча JVM продолжает увеличиваться. Зачем?
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 минут работы:
Почему моя куча памяти продолжает увеличиваться?
2 ответа
Вы должны использовать Java 7+ способ закрытия ресурсов, попробуйте с ресурсами.
Оператор try-with-resources является
try
заявление, которое объявляет один или несколько ресурсов. Ресурс - это объект, который должен быть закрыт после завершения программы. Оператор try-with-resources обеспечивает закрытие каждого ресурса в конце оператора. Любой объект, который реализуетAutoCloseable
, который включает в себя все объекты, которые реализуютCloseable
, может быть использован в качестве ресурса.
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;
}
Также вам не нужно явно закрывать результирующий набор, подготовленный оператор делает это так, как он владеет результирующим набором:
Когда
Statement
объект закрыт, его токResultSet
Объект, если таковой существует, также закрыт.
Однако, если вы хотите быть параноиком и переборщить, как @MarkRotteveel предлагает в своем комментарии, вы можете добавить в качестве AutoCloseable
ресурс также ResultSet
и код будет выглядеть так:
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()
) {
...
}
Я никогда не делал этого и никогда не нуждался в этом, и в документации прямо говорится, что в этом нет необходимости, но у некоторых людей возникали проблемы в определенных крайних случаях.
Во втором случае особенно заметно, насколько спасает вас попытка с ресурсами - вам не нужно присваивать переменные null
, вам не нужно проверять, были ли открыты какие-либо из них, и даже если один из close()
методы выдает исключение, "замкнутая цепочка" не разрывается и close()
методы других ресурсов вызываются в любом случае.
Если исключение выдается после открытия 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;
}