Java по-прежнему использует системную память после освобождения объектов и сборки мусора

Я использую JVM 1.5.0 (Mac OS X по умолчанию) и слежу за своей Java-программой в Activity Monitor. Имею следующее:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Date;

public class MemoryTest {

public static void memoryUsage() {
 System.out.println(
     Runtime.getRuntime().totalMemory() - 
     Runtime.getRuntime().freeMemory()
 );
}

public static void main( String[] args ) throws IOException {

    /* create a list */
    ArrayList<Date> list = new ArrayList<Date>();

    /* fill it with lots of data */
    for ( int i = 0; i < 5000000; i++ ) {
        list.add( new Date() );
    } // systems shows ~164 MB of physical being used

    /* clear it */
    memoryUsage();      //  about 154 MB
    list.clear();
    list = null;
    System.gc();
    memoryUsage();      //  about 151 KB, garbage collector worked

    // system still shows 164 MB of physical being used.
    System.out.println("Press enter to end...");
    BufferedReader br = new BufferedReader( 
            new InputStreamReader( System.in )
            );
    br.readLine();
}

}

Так почему же физическая память не освобождается, хотя сборщик мусора работает нормально?

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

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

Ответы 4

Ответ принят как подходящий

Многие JVM никогда не возвращают память операционной системе. Будет ли это так или нет, зависит от реализации. Для тех, кто этого не делает, ограничения памяти, указанные при запуске, обычно с помощью флага -Xmx, являются основным средством резервирования памяти для других приложений.

Мне сложно найти документацию по этому вопросу, но Документация по сборщику мусора для Sun Java 5 решает эту проблему, предполагая, что при правильных условиях куча будет сжиматься, если используется правильный сборщик - по умолчанию, если более 70% кучи свободно , он сожмется, и только 40% останется свободным. Параметры командной строки для управления ими - -XX:MinHeapFreeRatio и -XX:MaxHeapFreeRatio.

У меня есть пояснение. В конкретном тестовом примере, приведенном выше, вызов System.gc освободит некоторую память, даже если список комментариев не ясен и равен нулю. Здесь список активен, поэтому какая память зависает

UVM 06.04.2012 13:11

Возможно, ОС показывает память, которая в настоящее время выделена программе - даже если выделено 150 ~ МБ, это не означает, что 150 ~ МБ используются.

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

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

Для JVM есть несколько параметров командной строки, которые помогают настроить размер кучи, используемой Java. Все знают (или должны знать) о -Xms и -Xmx, которые устанавливают минимальный и максимальный размер кучи.

Но есть также -XX: MinHeapFreeRatio и -XX: MaxHeapFreeRatio, которые являются соответствующими пределами, между которыми JVM управляет свободным пространством. Это достигается за счет сжатия используемой кучи, что может снизить потребление памяти программой.

Вы можете найти более подробную информацию здесь:

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