Время выполнения - почему freeMemory () не показывает, что память используется правильно? - PullRequest
4 голосов
/ 06 августа 2010

Ниже приведен фрагмент кода для проверки памяти

public class TestFreeMemory {

    public static void main(String ... args){

        Runtime rt = Runtime.getRuntime();
        System.out.println("Free Memory (Before GC): " + rt.freeMemory());

        rt.gc();
        System.out.println("Free Memory (After GC1): " + rt.freeMemory());

        rt.gc(); // Second time to ensure results are consistent 
                 // MAY BE has collected all non-reachable objects
        System.out.println("Free Memory (After GC2): " + rt.freeMemory());

        String s = new String("abcd");
        Integer i = new Integer(12345);
        System.out.println("Free Memory (After String Creation): " + rt.freeMemory());
        // Why is freeMemory not reflecting the memory consumed by two objects
    }

}

и вывод

Free Memory (Before GC): 1859672
Free Memory (After GC1): 1911768
Free Memory (After GC2): 1911768
Free Memory (After String Creation): 1911768

Почему freeMemory не отражает память, занятую двумя объектами?


Чтобы быть более понятным, вопрос в том, что вызов getMemory () не показывает ожидаемый результат, даже если два объекта созданы и не связаны с GC.Два вызова GC выполняются только для того, чтобы убедиться, что номера вызовов getMemory () правильные ... и, кстати, нет вызова GC после создания объектов ... так что, пожалуйста, обратите внимание, что я не пытаюсь получить GC после создания объектов..

Ответы [ 4 ]

3 голосов
/ 06 августа 2010

Управление памятью в JSM HotSpot:

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

Управление памятью в HotSpot JVM (формат PDF).

Это поведение может очень зависеть от конкретной реализации сборки мусора. Например:

Parallel Mark Compact

  • Стоп-мир
  • Куча, разделенная на куски фиксированного размера (> 2 КБ сейчас, вероятно, увеличится или будет с учетом эргономики)
  • Чанк - это единица суммирования данных в реальном времени
  • Параллельная отметка
  • Запись адресов данных в реальном времени во внешнее растровое изображение
  • Найти на чанк живого размера данных
  • Найдите плотные куски, то есть те, которые (почти) полны живых объектов

Я сделал этот пример (с использованием неправильной конкатенации строк, чтобы использовать больше памяти):

public class TestFreeMemory {

 static void allocateSomeMemory(){
  long[][] array = new long[400][400];
 }

    public static void main(String ... args){

        Runtime rt = Runtime.getRuntime();

        allocateSomeMemory(); // once we leave, our array is not reachable anymore 
        System.out.println("Free Memory (Before GC): " + rt.freeMemory());     
        rt.gc();
        System.out.println("Free Memory (After GC): " + rt.freeMemory());

        String a = new String("A");
        for(int i = 0; i < 100; i++){
         a+="B";
        }

        System.out.println("Free Memory (After String Creation): " + rt.freeMemory());
        // Less free memory expected.
    }

}

выход

Свободная память (до GC): 3751800

Свободная память (после GC): 5036104

Свободная память (после создания строки): 5012048


Если я использую относительно небольшое количество итераций в цикле (скажем, 10), дополнительное пространство не отображается в freeMemory(), и я получу что-то вроде этого:

Свободная память (до GC): 3751800

Свободная память (после GC): 5036040

Свободная память (после создания строки): 5036040

1 голос
/ 06 августа 2010

Это хороший вопрос, так как вы ожидаете, что увеличение использования памяти будет отражено, это кажется логичным тестом. Вы можете предположить, что это происходит потому, что система управления кучей и сборки мусора несколько сложнее, чем простая граница Free vs Allocated. Распределение, вероятно, выполняется в блоках, намного превышающих одно строковое + одно целое число, поэтому свободная память может быть подсчитана путем суммирования свободных кусков.

0 голосов
/ 06 августа 2010

Попробуйте выделить больше памяти, и вы увидите увеличение. Я предполагаю, что Java предварительно выделяет по крайней мере достаточно байтов (как умно!) Для хранения ваших строк ИЛИ они уже были в пуле строк.

0 голосов
/ 06 августа 2010

GC не освобождает память при вызове, но когда требуется больше памяти.

...