Java GC - есть ли способ определить, какие объекты собраны - PullRequest
7 голосов
/ 13 апреля 2010

Я пытаюсь отслеживать активность gc в своем приложении, используя флаг -verbosegc. Я могу видеть, что есть полные и второстепенные коллекции, но есть ли способ определить (подчинение событиям / флаги vm / что угодно), какие объекты фактически собраны?

Спасибо!

Ответы [ 7 ]

5 голосов
/ 13 апреля 2010

Для получения общей информации об объектах в памяти, я бы посоветовал вам заглянуть в 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);
}
3 голосов
/ 13 апреля 2010

Я не использовал этот флаг сам -XX:-TraceClassUnloading. Отслеживать выгрузку классов.

2 голосов
/ 13 апреля 2010

Метод finalize класса Object вызывается непосредственно перед тем, как GC собирает объект. Переопределите метод в вашем классе следующим образом:

@Override
protected void finalize() throws Throwable {
    System.out.println(this+" collected");
    super.finalize();
}

Обратите внимание, что вы можете контролировать только свои собственные классы с помощью этого метода. Итак, поскольку String является последним классом, вы не можете отслеживать объект String таким образом.

0 голосов
/ 13 апреля 2010

Как правило, вы не можете определить, какой объект восстанавливается. Однако вы можете найти его подмножество, но вам нужно сослаться на них, используя ссылки Weak, Soft и Phantom. Как правило, вы создаете объект, а затем ссылаетесь на него, используя одну из этих ссылок. См. эту статью.

0 голосов
/ 13 апреля 2010

Для анализа проблем с памятью вам нужно проверить, какие объекты не GCed, вместо проверки, какие объекты получили GCed.

Чтобы проверить, какие объекты GCed, вы всегда можете использовать любой профилировщик, например, Jprofiler и т. Д.

0 голосов
/ 13 апреля 2010

Я не совсем уверен, зачем тебе это знать. Большинство людей хотят знать это, чтобы определить, есть ли у них утечки памяти. (В Java это означает, что вы поддерживаете объект, сохраняя ссылку на объект).

Netbeans имеет отличные инструменты для просмотра использования памяти любым java-приложением (в том числе не запущенным из netbeans!). Они могут сказать вам, сколько объектов было собрано и куда идет использование вашей памяти и еще много полезной статистики.

0 голосов
/ 13 апреля 2010

Я знаю, что это не то, как вы хотели бы решить вашу проблему, но в любом случае это может быть полезно.

Вы можете захватить событие на ваших собственных объектах, переопределив метод finalize. Это не на 100% гарантирует, что объект будет собирать мусор, поскольку он может создавать ссылки на себя, но это только начало.

Взгляните на эту статью Это довольно хороший учебник по ГК.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...