2016-08-31 11 views
0

以下のコードで使用するメモリ量を減らそうとしています。 5〜10MBのRAMを使用したいと思っていますが、可能かどうかは分かりません。起動時には、現在約10,1MB、その後約40MBのThread.sleepが必要です。私はBufferedReaderの異なる実装を試してみましたが、それは何も変更されていないようです。私はJavaで最高ではないし、私は特にメモリ管理が悪いので、おそらく本当にばかなものを逃してしまっただろう。誰かが私にメモリ管理に関するコードを改善するための指示を与えることができたらすばらしいでしょう!このコード/ buffereredreaderのメモリ使用量を減らす方法

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

文字列を2回ではなく1回小文字に変換すると、URL行を1つの巨大な文字列にまとめずに行単位で読み込んでテストするのに役立ちます。 'BufferedReader'はそれと関係がありません。 – EJP

+0

@ScaryWombatこのコードの一部を、ごくわずかのRAMしか使用できないマシンで実行したいと思っているためです。部分的には、コードが使用するリソースの量を減らすことは面白いと思っています。また、必要以上に多くのリソースを使用するのは無駄です。 –

答えて

1

このコードでの主メモリの利用の問題は、応答全体がメモリにロードされてから文字列が存在するかどうかを確認することです。

ストリーム全体を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

'エラー:ラムダ式から参照されるローカル変数はfinalまたは実質的に最終的なものでなければなりません。 if(line.contains(" error code:2568 "))hasError = true; エラー:ラムダ式から参照されるローカル変数は最終的に有効でなければなりません。 if(line.contains( "不十分なクライアント権限"))hasInsufficentPermission = true; ' ラムダ式は使用しないでください。ループで使用されるため、最終的には(実質的に)最終的にはなりません。 –

+0

ああ、私はAtomicBooleanを使う答えを更新しました。しかし、代わりにreadlineループを使うことができます。 – Magnus

関連する問題