Java的:你如何真正迫使使用JVMTI的ForceGargabeCollection一个GC?Ja

2019-05-12 01:23发布

我不是在找通常的“你只能用暗示System.gc()的在Java中GC”的答案,这是不是在所有的这个问题是关于什么的。

我的问题是不是主观的,是基于一个现实:GC 可以在Java被强制的事实。 许多我们每天使用做节目:IntelliJ IDEA的,NetBeans中,VisualVM的。

它们都可以强制 GC发生。

它是如何做?

我把它他们都使用JVMTI和更具体的ForceGarbageCollection(注意“强制”),但我怎么可以尝试为自己?

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

另外请注意,这个问题不是“为什么”,我想这样做:“为什么”可能是“好奇”或“我们正在写类似于VisualVM的程序”,等等。

真正的问题是“你如何使用JVMTI的ForceGarbageCollection强制GC”?

请问JVM需要与任何特殊参数来启动的?

是否需要任何JNI? 如果是这样,什么样的代码是什么呢?

是否只有在Sun的虚拟机工作?

任何完整的编译例子将是最受欢迎的。

Answer 1:

NetBeans中,至少,使用System.gc()的: http://hg.netbeans.org/main/annotate/9779f138a9c9/openide.actions/src/org/openide/actions/GarbageCollectAction.java (这是为小按钮显示当前堆,让你开始GC)。 如果你点击该链接,你会看到,他们明确地运行终结。 如果你的磁盘空间几无演出,并希望自己调查的代码,它通过水银的可用: hg clone http://hg.netbeans.org/main/

据我所知道的,“System.gc()的仅仅是一个暗示”教条在JLS和JVM规范,该规范允许没有一个垃圾收集堆Java实现的迂腐解释起源。 在这一点,和一个不完整的读的JavaDoc :

调用gc方法表明Java虚拟机了一些努力,以使他们目前占据可快速重用的内存回收未使用的对象。 当从方法调用控制返回时,Java虚拟机已经从所有丢弃的对象中回收了空间最大的努力。

阅读第二句:“回收空间尽力而为”比强很多“暗示”。

这就是说,有很少的理由调用System.gc() 。 随着道歉克努特:

我们应该忘记内存管理,说的时候约97%:显式垃圾收集是一切罪恶的根源



Answer 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迭代类实例



Answer 3:

是的JNI接口的代码需要使用JVMTI API,因为它是一个原生API。 “天然的”意味着可以只把它直接形成天然(understan C或C ++)码。 所以,如果你想打电话从您需要编写代码,JNI接口它的Java这个API。



Answer 4:

由于匿名说,我们在日食类似,明确运行垃圾收集器。

请看看在Eclipse中:垃圾收集器按钮

这似乎工作得很好。 我建议你看看这背后的“运行垃圾收集器”按钮的代码重用。

一些成员说,它使用的System.gc(),但我不能确认。 Eclipse的专家可以在这里提供一些线索。



文章来源: Java: How do you really force a GC using JVMTI's ForceGargabeCollection?