繁体   English   中英

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;
    }

这是运行10分钟后的Java堆内存使用情况:

使用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

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;
}

同样,您也不必显式关闭结果集,因为它拥有结果集,所以prepared语句可以这样做:

Statement对象关闭时,其当前ResultSet对象(如果存在)也将关闭。

但是,如果您想变得偏执并且过分杀伤,正如@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()方法引发异常,在任何情况下都不会中断“关闭链”,并且会调用其他资源的close()方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM