简体   繁体   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);

this part of the program generates the increasing heap memory error. 程序的这一部分会产生越来越多的堆内存错误。

 controller2.GetAIntFromDatabase(columblName); 

with this function I read an int value from my database. 通过此功能,我从数据库中读取了一个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;
    }

That's the Java heap memory usage after 10 minutes of running: 这是运行10分钟后的Java堆内存使用情况:

使用Java堆内存10分钟

Why does my heap memory keep increasing? 为什么我的堆内存不断增加?

If an exception is thrown after opening the preparedStatement and the resultSet , they will never be closed. 如果一个异常被打开后抛出preparedStatementresultSet ,他们将永远不会被关闭。 Therefore you should use the finally block which will always be executed. 因此,您应该使用将始终执行的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;
}

You should use a Java 7+ way of closing the resources, try-with-resources . 您应该使用Java 7+的方式关闭资源try-with-resources

The try-with-resources statement is a try statement that declares one or more resources. try-with-resources语句是一个try语句,用于声明一个或多个资源。 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. try-with-resources语句可确保在语句末尾关闭每个资源。 Any object that implements AutoCloseable , which includes all objects which implement Closeable , can be used as a resource. 任何实现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;
}

Also you do not have to explicitly close the result set, the prepared statement does it as it owns the result set : 同样,您也不必显式关闭结果集,因为它拥有结果集,所以prepared语句可以这样做:

When a Statement object is closed, its current ResultSet object, if one exists, is also closed. Statement对象关闭时,其当前ResultSet对象(如果存在)也将关闭。

However, if you want to be paranoid and overkill it, as @MarkRotteveel suggests in his comment, you may add as an AutoCloseable resource also the ResultSet , and the code would then look like this: 但是,如果您想变得偏执并且过分杀伤,正如@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()
    ) {
    ...
}

I have never done it and never needed it and the documentation explicitly states that it's not necessary, but some people have experienced problems in certain edge cases. 我从来没有做过它,也从来不需要它,文档中明确指出这是没有必要的,但是有些人在某些极端情况下遇到了问题。

In this second case it's especially visible how much the try-with-resources saves you from - you do not need to assign the variables to null , you do not have to check if any of them have been opened, and even if one of the close() methods throws an exception, the "closing chain" is not broken and the close() methods of the other resources are called in any case. 在第二种情况下,特别明显的是try-with-resources为您节省了多少费用-您无需将变量分配为null ,不必检查是否已打开任何变量,即使其中一个已打开, close()方法引发异常,在任何情况下都不会中断“关闭链”,并且会调用其他资源的close()方法。

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

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