我建立了一個基本的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
基於此教程:Own your heap: Iterate class instances with JVMTI
基於迂腐解釋我不會把它教條。大多數JVM都可以簡單地禁用對System.gc()的調用,因此你不能相信它做任何事情。 很多時候,當你有一個寫得很好的應用程序,其中gc工作很有趣時,通過調用System.gc(),引入一個開發人員認爲他可以「確保內存可用」的庫,將它關閉是獲得最佳方式回到你的良好gc表現。 – Fredrik 2012-09-11 05:30:34
用戶仍然有控制權。對於熱點VM,您可以設置「-XX:+ DisableExplicitGC」,或者不要。所以只要你能控制JVM標誌'System.gc()'是相當可靠的。該參數僅適用於無法控制這些標誌的庫編寫器/不能假定它將運行在哪個VM上。這是一般情況(規格)與具體使用情況(所有參數由用戶控制)。 – the8472 2015-09-21 13:25:38
應用程序編寫者通常不能控制JVM標誌。例外情況是應用程序被封裝在啓動器中,以防止用戶或系統管理員調整它們。這不是書信。事實上,該標誌專門用於保護人們免受Java應用程序/應用程序編寫者做愚蠢的事情。 – 2015-09-22 02:34:18