Вообще говоря, «полная сборка мусора» не определена. GC обнаруживает недоступные объекты и восстанавливает их. Так получилось, что большинство реализаций GC работают на основе «цикла», и после завершения полного цикла можно определить правильное представление о «освобожденном пространстве». Таким образом, если вы можете запустить полный цикл, и этот цикл вообще не нашел восстанавливаемого пространства, а приложение в противном случае «простаивает» (например, не обновляет указатели), то вы можете сказать, что вы временно достигли «полностью собранного» пункта .
Таким образом, вы можете захотеть сделать что-то подобное:
Runtime r = Runtime.getRuntime();
r.gc();
long f = r.freeMemory();
long m = r.maxMemory();
long t = r.totalMemory();
for (;;) {
r.gc();
long f2 = r.freeMemory();
long m2 = r.maxMemory();
long t2 = r.totalMemory();
if (f == f2 && m == m2 && t == t2)
break;
f = f2;
m = m2;
t = t2;
}
System.out.println("Full GC achieved.");
Этот код опирается на некоторые предположения, главным из которых является то, что Runtime.gc()
- это больше, чем «подсказка», и действительно вызывает некоторую активность GC. JVM от Sun может быть запущена с флагом «-XX: -DisableExplicitGC», который преобразует Runtime.gc()
в бездействие, эффективно предотвращая выполнение кода, приведенного выше.
Также есть несколько предостережений:
JVM может иметь некоторую фоновую непрерывную активность, например, Timer
темы. Некоторые из этих действий могут быть «скрытыми», то есть не кодом, написанным разработчиком приложения. Также подумайте о потоке диспетчера событий AWT / Swing.
Выполнение GC может вызвать дополнительную асинхронную активность через финализуемые объекты или мягкие / слабые / фантомные ссылки. Такая активность обязательно является асинхронной и может выполняться неограниченное количество времени. Runtime.gc()
не будет ждать, пока это закончится. Это на самом деле вопрос определения: вы считаете, что сборщик мусора "завершен", если финализаторы и справочные очереди еще не обработаны?
Ничто не заставляет код, приведенный выше, завершаться ...
Для «более полного» GC вы можете использовать интерфейс JVMTI (тот, который используется отладчиками), который позволяет запускать GC, но также , чтобы приостановить целевые потоки JVM, что делает его намного легче определить и достичь состояния "полного GC".