如何减少此 code/bufferedreader 的内存使用

How to reduce the memory usage of this code/bufferedreader

我正在尝试减少以下代码使用的内存量。我希望它最多使用 5-10MB 的 RAM,但我不确定这是否可行。在启动时,它现在需要大约 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();
            }
        }
    }
}

此代码的主要内存使用问题是在检查字符串是否存在之前将整个响应加载到内存中。

与其将整个流缓冲到一个大字符串中,不如在读取每一行时检查它们,一旦检查过,旧行就可以被垃圾收集。

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 内存使用,但这超出了本答案的范围。