Подтвердить что ты не робот

Java: Как вы действительно заставляете GC использовать JVMTI ForceGargabeCollection?

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

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

У всех может быть force GC.

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

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

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

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

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

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

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

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

Приветствуется любой полный и компилируемый пример.

4b9b3361

Ответ 1

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 Spec, которые позволяют реализовать Java-реализации, у которых нет кучи мусора. Это и неполное чтение JavaDoc:

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

Прочитайте второе предложение: "Лучшее усилие для освобождения пространства" намного сильнее, чем "намек".

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

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

Ответ 2

Я создал базовый 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

Ответ 3

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

Ответ 4

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

Пожалуйста, посмотрите Eclipse: кнопка сборщика мусора

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

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