Я использую 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 никогда не возвращают память операционной системе. Будет ли это так или нет, зависит от реализации. Для тех, кто этого не делает, ограничения памяти, указанные при запуске, обычно с помощью флага -Xmx, являются основным средством резервирования памяти для других приложений.
Мне сложно найти документацию по этому вопросу, но Документация по сборщику мусора для Sun Java 5 решает эту проблему, предполагая, что при правильных условиях куча будет сжиматься, если используется правильный сборщик - по умолчанию, если более 70% кучи свободно , он сожмется, и только 40% останется свободным. Параметры командной строки для управления ими - -XX:MinHeapFreeRatio и -XX:MaxHeapFreeRatio.
У меня есть пояснение. В конкретном тестовом примере, приведенном выше, вызов System.gc освободит некоторую память, даже если список комментариев не ясен и равен нулю. Здесь список активен, поэтому какая память зависает
Возможно, ОС показывает память, которая в настоящее время выделена программе - даже если выделено 150 ~ МБ, это не означает, что 150 ~ МБ используются.
Вам необходимо использовать профилировщик, специфичный для JVM, чтобы отслеживать фактическое пространство кучи, используемое программой, а не память, выделенную для JVM.
JVM не только неохотно освобождает выделенную память из кучи, но и имеет тенденцию пожирать по разным причинам, включая своевременную компиляцию.
Для JVM есть несколько параметров командной строки, которые помогают настроить размер кучи, используемой Java. Все знают (или должны знать) о -Xms и -Xmx, которые устанавливают минимальный и максимальный размер кучи.
Но есть также -XX: MinHeapFreeRatio и -XX: MaxHeapFreeRatio, которые являются соответствующими пределами, между которыми JVM управляет свободным пространством. Это достигается за счет сжатия используемой кучи, что может снизить потребление памяти программой.
Вы можете найти более подробную информацию здесь:
Эта операционная система имеет систему виртуальной памяти. JVM не удерживает физическую память. Я думаю, вы действительно имеете в виду, почему JVM не ограничивает диапазон виртуальных адресов, который она использует.