Я пытаюсь контролировать действие gc в своем приложении, с помощью-verbosegc флаг. Я вижу, что существуют полные и незначительные наборы, но есть ли способ определить (subscrbing к флагам/независимо от того, что events/vm), который возражает на самом деле собранный?
Спасибо!
Для получения общей информации об объектах в памяти я предлагаю вам заглянуть в jvisualvm (он находится в папке bin вашего JDK). Он содержит много полезной информации о том, что делает виртуальная машина во время работы вашей программы, включая информацию о различных объектах и состоянии памяти.
Если вам нужно что-то более конкретное, вы можете использовать WeakReferences и ReferenceQueues. Этот вариант может быть жизнеспособным, если вас интересуют только объекты небольшого типа. Вы можете создать WeakReference для объектов по мере их создания с помощью общей ReferenceQueue, а затем попросить другой поток периодически проверять очередь (обратите внимание, что в очереди указано только, что объекты достижимы, а не то, что они фактически собраны):
static ReferenceQueue<MyObject> MY_QUEUE = new ReferenceQueue<MyObject>();
static class MyReference extends WeakReference<MyObject>{
public final String name;
public MyReference(MyObject o, ReferenceQueue<MyObject> q){
super(o, q);
name = o.toString();
}
}
static{
Thread t = new Thread(){
public void run(){
while(true){
MyReference r = (MyReference)MY_QUEUE.remove();
System.out.println(r.name+" eligible for collection");
}
}
}
t.setDaemon(true);
t.start();
}
public MyObject(){
//normal init...
new MyReference(this, MY_QUEUE);
}
Как правило, вы не можете определить, какой объект будет возвращен. Однако вы можете найти его подмножество, но вы должны ссылаться на них, используя слабые, мягкие и фантомные ссылки. Как правило, вы создаете объект, а затем ссылаетесь на него, используя одну из этих ссылок. См. эту статью.
Я сам не использовал этот флаг -XX: -TraceClassUnloading
. Он предназначен для отслеживания выгрузки классов.
Метод finalize класса Object вызывается непосредственно перед тем, как GC собирает объект. Переопределите этот метод в своем классе следующим образом:
@Override
protected void finalize() throws Throwable {
System.out.println(this+" collected");
super.finalize();
}
Обратите внимание, что с помощью этого метода вы можете контролировать только свои собственные классы. Так, поскольку String - класс final, вы не можете отслеживать объект String этим методом.
Я не совсем понимаю, зачем вам это знать. Большинство людей хотят знать это, чтобы определить, есть ли у них утечки памяти. (В java это означает, что вы поддерживаете объект в живых, сохраняя ссылку на объект).
Netbeans имеет отличные инструменты для анализа использования памяти любым java-приложением (в том числе и тех, которые не работают из netbeans!). Они могут сказать вам, сколько объектов было собрано и где используется ваша память, а также многие больше полезной статистики.
Я знаю, что это не то, как вы хотели бы решить вашу проблему, но в любом случае это может быть полезно.
Вы можете перехватить это событие на своих собственных объектах, переопределив метод finalize. Это не гарантирует на 100%, что объект будет собран, поскольку он может создавать ссылки на себя, но это начало.
Посмотрите эту статью - это довольно хороший учебник по GC.
Для анализа проблем с памятью вам нужно проверить, какие объекты не GCed, вместо того, чтобы проверять, какие объекты получили GCed.
Чтобы проверить, какие объекты GCed, вы всегда можете использовать любой профилировщик, например Jprofiler и т.д.