Java не собирает мусор в памяти

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

Мой вопрос: есть ли способ освободить эту память? Или это ошибка JVM?

Я создал SSCCE, чтобы продемонстрировать это. Он читает файл размером 1 МБ (2 МБ в Java из-за 16-битной кодировки) и извлекает один символ из каждой строки (~ 4000 строк, поэтому должно быть около 8 КБ).По окончании теста еще используются полные 2 мб!

Начальное использование памяти:

Allocated: 93847.55 kb
Free: 93357.23 kb

Сразу после чтения файла (до ручной сборки мусора):

Allocated: 93847.55 kb
Free: 77613.45 kb (~16mb used)

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

Однако потом я собираю мусор, но не вся память освобождается:

Allocated: 93847.55 kb
Free: 91214.78 kb (~2 mb used! That's the entire file!)

Я знаю, что ручной вызов сборщика мусора не дает никаких гарантий (в некоторых случаях это лениво). Однако это происходило в моем более крупном приложении, где файл съедает почти всю доступную память и приводит к тому, что остальной части программы не хватает памяти, несмотря на необходимость в ней. Этот пример подтверждает мое подозрение, что лишние данные, прочитанные из файла, не освобождаются.

Вот SSCCE для создания теста:

import java.io.*;
import java.util.*;

public class Test {
    public static void main(String[] args) throws Throwable {
        Runtime rt = Runtime.getRuntime();

        double alloc = rt.totalMemory()/1000.0;
        double free = rt.freeMemory()/1000.0;

        System.out.printf("Allocated: %.2f kb\nFree: %.2f kb\n\n",alloc,free);

        Scanner in = new Scanner(new File("my_file.txt"));
        ArrayList<String> al = new ArrayList<String>();

        while(in.hasNextLine()) {
            String s = in.nextLine();
            al.add(s.substring(0,1)); // extracts first 1 character
        }

        alloc = rt.totalMemory()/1000.0;
        free = rt.freeMemory()/1000.0;
        System.out.printf("Allocated: %.2f kb\nFree: %.2f kb\n\n",alloc,free);

        in.close();
        System.gc();

        alloc = rt.totalMemory()/1000.0;
        free = rt.freeMemory()/1000.0;
        System.out.printf("Allocated: %.2f kb\nFree: %.2f kb\n\n",alloc,free);
    }
}
12
задан tskuzzy 8 June 2012 в 15:32
поделиться