Java: Как на самом деле заставить GC использовать ForceGargabeCollection JVMTI? - PullRequest
23 голосов
/ 01 февраля 2010

Мне не нужны обычные ответы «вы можете намекнуть на сборщик мусора в Java, используя ответы System.gc () », это совсем не то, о чем этот вопрос.

Мои вопросы не субъективны и основаны на реальности: GC может быть принудительным в Java для факта. Многие программы, которые мы используем ежедневно, делают это: IntelliJ IDEA, NetBeans, VisualVM.

Они все могут заставить GC произойти.

Как это сделать?

Я так понимаю, все они используют JVMTI, а точнее ForceGarbageCollection (обратите внимание на "Force"), но как я могу попробовать это для себя?

http://java.sun.com/javase/6/docs/platform/jvmti/jvmti.html#ForceGarbageCollection

Также обратите внимание, что этот вопрос не о «почему», я бы хотел это сделать: «почему» может быть «любопытством» или «мы пишем программу, похожую на VisualVM» и т. Д.

Вопрос на самом деле "как заставить GC использовать ForceGarbageCollection JVMTI"?

Нужно ли запускать JVM с какими-либо особыми параметрами?

Требуется ли какой-либо JNI? Если да, то какой именно код?

Работает ли это только на виртуальных машинах Sun?

Любой законченный и компилируемый пример будет очень кстати.

Ответы [ 4 ]

10 голосов
/ 30 марта 2010

NetBeans, по крайней мере, использует System.gc (): http://hg.netbeans.org/main/annotate/9779f138a9c9/openide.actions/src/org/openide/actions/GarbageCollectAction.java (это для маленькой кнопки, которая показывает текущую кучу и позволяет запустить GC). Если вы перейдете по этой ссылке, вы увидите, что они явно запускают финализаторы. Если у вас есть несколько гигабайт свободного места на диске и вы хотите исследовать код самостоятельно, он доступен через Mercurial: hg clone http://hg.netbeans.org/main/

Насколько я могу судить, догма "System.gc () - это просто подсказка" берет свое начало в педантичной интерпретации спецификации JLS и JVM, которая допускает реализации Java, которые не имеют кучи, собираемой мусором. Это и неполное чтение JavaDoc :

Вызов метода gc предполагает, что виртуальная машина Java затрачивает усилия на утилизацию неиспользуемых предметов в чтобы сделать память они в настоящее время занимают доступны для быстрого повторное использование. Когда контроль возвращается из вызов метода, виртуальная машина Java сделал все возможное, чтобы вернуть пространство от всех выброшенных объектов.

Прочитайте второе предложение: «лучшее усилие вернуть пространство» гораздо сильнее, чем «намек».

Тем не менее, редко есть причина позвонить System.gc(). С извинениями Кнуту:

Мы должны забыть об управлении памятью, скажем, в 97% случаев: явная сборка мусора - корень всех зол

4 голосов
/ 22 сентября 2015

Я создал базовый Java-агент, позволяющий вызывать функцию jvmti ForceGarbageCollection:

#include <stdlib.h>
#include <stdio.h>
#include <jvmti.h>


typedef struct {
 jvmtiEnv *jvmti;
} GlobalAgentData;

static GlobalAgentData *gdata;

JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved)
{
  printf("load garbager agent\n");
  jvmtiEnv *jvmti = NULL;

  // put a jvmtiEnv instance at jvmti.
  jint result = jvm->GetEnv((void **) &jvmti, JVMTI_VERSION_1_1);
  if (result != JNI_OK) {
    printf("ERROR: Unable to access JVMTI!\n");
  }

  // store jvmti in a global data
  gdata = (GlobalAgentData*) malloc(sizeof(GlobalAgentData));
  gdata->jvmti = jvmti;
  return JNI_OK;
}


extern "C"
JNIEXPORT void JNICALL Java_Garbager_forceGarbageCollection(JNIEnv *env, jclass thisClass) 
{
  printf("force garbage collection\n");
  gdata->jvmti->ForceGarbageCollection();
}

Этот агент вызывается через JNI :

class Garbager {
    public static void main(String[] args) {
        Garbager.garbageMemory();
    }

    static void garbageMemory() {
        forceGarbageCollection();
    }

    private static native void forceGarbageCollection();
}

Чтобы скомпилировать агент в MacOSX:

clang -shared -undefined dynamic_lookup -o garbager-agent.so -I /Library/Java/JavaVirtualMachines/jdk1.8.0_40.jdk/Contents/Home/include/ -I /Library/Java/JavaVirtualMachines/jdk1.8.0_40.jdk/Contents/Home/include/darwin garbager-agent.cpp

Для запуска Garbager:

java -agentpath:garbager-agent.so Garbager

На основе этого урока: Собственная куча: повторять экземпляры классов с JVMTI

0 голосов
/ 22 сентября 2015

Как сказал Анон, у нас есть нечто подобное в eclipse для явного запуска сборщика мусора.

Пожалуйста, посмотрите на Затмение: кнопка для сбора мусора

Кажется, это работает довольно хорошо. Я предлагаю вам взглянуть на код этой кнопки «Запустить сборщик мусора» и использовать его повторно.

Некоторые участники говорят, что он использует System.gc (), но я не могу подтвердить это. Специалисты по Eclipse могут пролить немного света здесь.

0 голосов
/ 30 ноября 2011

Да Код интерфейса JNI необходим для использования API JVMTI, поскольку он является собственным API. «нативный» означает, что вы можете вызывать его только напрямую из нативного (understan c или c ++) кода. Поэтому, если вы хотите вызывать этот API из Java, вам нужно написать код JNI для его сопряжения.

...