2016-08-31 26 views
0

我在嘗試減少以下代碼使用的內存量。我希望它最多使用5-10MB的內存,但我不確定這是否可能。在啓動時,它現在大約需要10,1MB,在Thread.sleep之後大約需要40MB。我試過使用BufferedReader的不同實現,但這似乎沒有改變任何東西。我不是java中最偉大的人,我在內存管理方面尤其糟糕,所以我可能錯過了一些非常愚蠢的東西。如果有人能夠給我提供一些關於改進內存管理代碼的指導,那將會非常棒!如何減少此代碼/緩衝讀取器的內存使用量

package tsviewerscanner; 

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.net.MalformedURLException; 
import java.net.URL; 
import java.net.URLConnection; 
import java.nio.charset.StandardCharsets; 
import java.util.stream.Collectors; 

public class TSViewerScanner { 

    static URL url; 

    public static void main(String[] args) { 
     System.out.println("Started"); 
     while (true) { 
      try { 
       Thread.sleep(10000); 
      } catch (InterruptedException ex) { 
       ex.printStackTrace(); 
      } 

      try { 
       url = new URL("https://www.tsviewer.com/ts3viewer.php?ID=1040506"); 
      } catch (MalformedURLException ex) { 
       ex.printStackTrace(); 
      } 

      try { 
       URLConnection conn = url.openConnection(); 
       conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11"); 

       try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) { 
        String WebContentStr = reader.lines().collect(Collectors.joining("\n")); 
        if (WebContentStr.toLowerCase().contains("error code: 2568") && WebContentStr.toLowerCase().contains("insufficient client permissions")) { 
         System.out.println("WebContentStr contains both strings"); 
        } else { 
         System.out.println("Strings not found"); 
        } 
       } 
      } catch (IOException ex) { 
       ex.printStackTrace(); 
      } 
     } 
    } 
} 
+0

爲什麼?有理由嗎? –

+0

將字符串轉換爲小寫而不是兩次將有所幫助,就像讀取和測試URL行一樣,而不是將其全部收集到一個巨型字符串中。 「BufferedReader」與它沒有任何關係。 – EJP

+0

@ScaryWombat部分原因是因爲我想在可用RAM很少的機器上運行代碼的一部分。部分原因是我認爲減少代碼使用的資源數量很有意思,並且使用比必要的資源更多的資源會讓人覺得很浪費。 –

回答

1

該代碼的主要內存利用率問題是整個響應在檢查字符串的存在之前是否加載到內存中。

而不是緩衝整個流成一個大字符串,你可以檢查每一行,因爲他們被讀取,一旦檢查舊線可以被垃圾收集。

try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) { 
    AtomicBoolean hasError = new AtomicBoolean(); 
    AtomicBoolean hasInsufficentPermission = new AtomicBoolean(); 
    reader.lines().map(String::toLowerCase).forEach(line-> { 
     if(line.contains("error code: 2568")) hasError.set(true); 
     if(line.contains("insufficient client permissions")) hasInsufficentPermission.set(true); 
    }); 
    if (hasError.get() && hasInsufficentPermission.get()) { 
     System.out.println("WebContentStr contains both strings"); 
    } else { 
     System.out.println("Strings not found"); 
    } 
} 

不過,我懷疑你所看到的行爲更多的是與你誤解了JVM如何利用內存。
JVM使用的內存量與分配的內存,程序運行的時間以及程序在運行時創建多少垃圾有關。
JVM的內存使用情況通常不代表在任何給定時間堆應用程序需要多少內存。
有很多方法可以調整JVM內存使用情況,但這不在此範圍內。

+0

'錯誤:從lambda表達式引用的局部變量必須是最終的或有效的最終 if(line.contains(「error code:2568」))hasError = true; 錯誤:從lambda表達式引用的局部變量必須是最終的或有效的最終 if(line.contains(「insufficient client permissions」))hasInsufficentPermission = true;' 我猜不應該使用lambda表達式,因爲它是在循環中使用,這使得它不是(有效)最終的。 –

+0

啊我的不好,我已經更新了使用'AtomicBoolean.'的答案,但是您可以使用readline循環。 – Magnus