2016-08-31 2 views
0

아래 코드에서 사용하는 메모리 양을 줄이려고합니다. 5 ~ 10MB의 RAM을 사용하고 싶습니다.하지만 가능한지 확실하지 않습니다. 시동시 약 10MB 정도가 걸리며, 이후 약 40MB 정도 인 Thread.sleep이 뒤 따른다. 내가 BufferedReader의 다른 구현을 사용하여 시도했지만 그게 아무것도 변경하지 않는 것. 나는 자바에서 가장 위대하지 못하며 특히 메모리 관리에 나쁘다. 그래서 나는 정말 바보 같은 것들을 놓쳤을 것이다. 누군가 메모리 관리와 관련하여 코드 개선에 대한 지침을 줄 수 있다면 정말 좋을 것입니다!이 코드/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

문자열을 두 번이 아니라 소문자로 변환하면 URL 행을 하나의 거대한 문자열로 모두 수집하는 대신 줄로 읽거나 테스트하는 것처럼 도움이됩니다. 'BufferedReader'는 아무 것도하지 않습니다. – EJP

+0

@ SkaryWombat 아주 작은 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

'오류 : 람다 식에서 참조 된 지역 변수는 final 또는 실질적으로 최종이어야합니다. if (line.contains ("error code : 2568")) hasError = true; 오류 : 람다 식에서 참조 된 지역 변수가 최종적이거나 효과적이어야합니다. if (line.contains ("insufficient client permissions")) hasInsufficentPermission = true; 람다 식은 사용해서는 안됩니다. 루프에서 사용되기 때문에 최종적으로 (사실상) 최종 생성되지 않습니다. –

+0

아, 제 대답은'AtomicBoolean.'을 사용하는 대답을 업데이트했습니다.하지만 대신 readline 루프를 사용할 수 있습니다. – Magnus