我不是在找通常的“你只能用暗示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的虚拟机工作?
任何完整的编译例子将是最受欢迎的。
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%:显式垃圾收集是一切罪恶的根源
我建立了一个基本的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迭代类实例
是的JNI接口的代码需要使用JVMTI API,因为它是一个原生API。 “天然的”意味着可以只把它直接形成天然(understan C或C ++)码。 所以,如果你想打电话从您需要编写代码,JNI接口它的Java这个API。
由于匿名说,我们在日食类似,明确运行垃圾收集器。
请看看在Eclipse中:垃圾收集器按钮
这似乎工作得很好。 我建议你看看这背后的“运行垃圾收集器”按钮的代码重用。
一些成员说,它使用的System.gc(),但我不能确认。 Eclipse的专家可以在这里提供一些线索。