Java - утечка памяти файлового сервера

У меня есть сервер, настроенный таким образом, что, когда пользователи открывают мое приложение, он проверяет наличие обновлений с файлового сервера и при необходимости загружает их.

Однако я заметил, что со временем, когда люди подключаются и скачивают, использование памяти сервером постепенно увеличивается и увеличивается и уменьшается только в том случае, если я перезапускаю программу Java, которая открывает сокеты для размещения файлов.

Основная часть программы приведена ниже:

@Override
public void run() {
    try {
        int archiveCount = in.readByte();
        while(archiveCount-- > 0) {
            int nameLength = in.readInt();
            byte[] name = new byte[nameLength];
            in.read(name);
            int size = in.readInt();
            clientLengths.put(new String(name).toLowerCase().trim(), size);
        }
        if (!clientLengths.isEmpty()) {
            int count = 0;
            for(String fileName : lengths.keySet()) {
                if (!clientLengths.containsKey(fileName) || 
                        (long)clientLengths.get(fileName) != (long)lengths.get(fileName)) {
                    missing.add(fileName);
                    count += lengths.get(fileName);
                }
            }
            if (count == 0) {
                out.writeByte(0);
            } else {
                out.writeByte(1);
                byte[] archive = readFile(archiveZip);
                out.writeInt(count);
                readFully(new ByteArrayInputStream(archive), out, archive.length);
            }
        } else { //hit if cache doesnt exist
            out.writeByte(2);
            byte[] cache = readFile(cacheZip);
            out.writeInt(cache.length);
            readFully(new ByteArrayInputStream(cache), out, cache.length);
        }
        destroy();
    } catch(Exception e) {
        e.printStackTrace();
    }
}

private void destroy() throws IOException {
    System.out.println("Finished cache handling from: " + socket.getInetAddress());
    missing.clear();
    clientLengths.clear();
    socket.close();
}

А переменные определены следующим образом:

private final Socket socket;
private final DataInputStream in;
private final DataOutputStream out;
private final List<String> missing = new ArrayList<>();
private final HashMap<String, Integer> clientLengths = new HashMap<>();
private final static HashMap<String, Integer> lengths = new HashMap<>();
private final static File dir = new File("./Data/Archive");
private final static File archiveZip = new File("./Data/Archive.zip");
private final static File cacheZip = new File("./Data/Cache.zip");

Основной цикл в отдельном классе, который в первую очередь открывает сокет, выглядит следующим образом:

@Override
public void run() {
    while(true) {
        try {
            Socket socket = cacheSocket.accept();
            System.out.println("Accepted cache socket from: " + socket.getInetAddress());
            Thread acceptor = new Thread(new CacheHandler(socket));
            acceptor.start();
            Main.debug();
            System.gc();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Кто-нибудь знает, почему использование памяти продолжает расти и расти? Любые советы будут оценены. Спасибо!

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
65
1

Ответы 1

Таким образом, все операции закрытия / уничтожения должны выполняться в предложении finally. Этот обязательно будет выполнен.

Или лучше использовать try-with-resources.

Mark Rotteveel 02.06.2018 19:27

Другие вопросы по теме