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 分钟后 运行 的堆内存使用情况:

为什么我的堆内存一直在增加?

如果打开preparedStatementresultSet后抛出异常,则永远不会关闭。因此,您应该使用将始终执行的 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()方法。