簡體   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