我们知道jmap -histo:live会触发一个完整的gc以确定活动对象:
Does jmap force garbage collection when the live option is used?
由于jmap -histo考虑堆中的所有对象(年轻和老一代中的对象),我的观点是,jmap -histo也可以触发完整的gc。但是,我无法找到关于jmap -histo是否可以触发完整gc的可靠文档。
jmap -histo可以触发完整的垃圾回收吗?
答案 0 :(得分:6)
具有更多JDK经验的人应该验证这一点,但我相信它确实触发了完整的GC,至少在OpenJDK 1.7中。从jdk/src/share/classes/sun/tools/jmap/JMap.java
开始:
public class JMap {
...
private static String LIVE_HISTO_OPTION = "-histo:live";
...
...
} else if (option.equals(LIVE_HISTO_OPTION)) {
histo(pid, true);
...
private static final String LIVE_OBJECTS_OPTION = "-live";
private static final String ALL_OBJECTS_OPTION = "-all";
private static void histo(String pid, boolean live) throws IOException {
VirtualMachine vm = attach(pid);
InputStream in = ((HotSpotVirtualMachine)vm).
heapHisto(live ? LIVE_OBJECTS_OPTION : ALL_OBJECTS_OPTION);
drain(vm, in);
}
Jmap.histo()
中的三元运算符使用jdk/src/share/classes/sun/tools/attach/HotSpotVirtualMachine.java
参数调用-live
中的heapHisto:
// Heap histogram (heap inspection in HotSpot)
public InputStream heapHisto(Object ... args) throws IOException {
return executeCommand("inspectheap", args);
}
如果我们在inspectheap
中查看hotspot/src/share/vm/services/attachListener.cpp
本身:
// Implementation of "inspectheap" command
//
// Input arguments :-
// arg0: "-live" or "-all"
static jint heap_inspection(AttachOperation* op, outputStream* out) {
bool live_objects_only = true; // default is true to retain the behavior before this change is made
const char* arg0 = op->arg(0);
if (arg0 != NULL && (strlen(arg0) > 0)) {
if (strcmp(arg0, "-all") != 0 && strcmp(arg0, "-live") != 0) {
out->print_cr("Invalid argument to inspectheap operation: %s", arg0);
return JNI_ERR;
}
live_objects_only = strcmp(arg0, "-live") == 0;
}
VM_GC_HeapInspection heapop(out, live_objects_only /* request full gc */, true /* need_prologue */);
VMThread::execute(&heapop);
return JNI_OK;
}
请注意,特别是live_objects_only
strcmp和生成的heapop
稍后会调用两行。如果inspectheap
通过任何途径获得-live
参数,则它会请求完整的gc。
答案 1 :(得分:3)
jmap -histo
不会触发完整的gc,但jmap -histo:live
会。
答案 2 :(得分:1)
不,jmap -histo
不会触发FullGC。我正在定期打印直方图,并且在我的GC日志中看不到任何完整的GC。
我不知道它是如何在VM中实现的,但您不必担心完整的GC。
答案 3 :(得分:0)
根据我的经验:是的,它是。当你做这个实验时,你可以使用命令:
sudo -utomcat jstat -gcutil {PID} 1000 1000
描述: pid后的第一个参数1000是打印的时间间隔。 pid之后的第二个参数1000是循环计数。 使用此命令可以监视jvm gc活动。您可以看到完整的gc时间和计数如下:
S0 S1 E O P YGC YGCT FGC FGCT GCT
0.00 18.45 13.12 84.23 47.64 206149 5781.308 83 115.479 5896.786
0.00 21.84 5.64 84.24 47.64 206151 5781.358 83 115.479 5896.837
0.00 32.27 1.66 84.24 47.64 206153 5781.409 83 115.479 5896.888
0.00 13.96 53.54 84.24 47.64 206155 5781.450 83 115.479 5896.929
0.00 21.56 91.77 84.24 47.64 206157 5781.496 83 115.479 5896.974
现在您可以在其他终端执行jmap命令,首先执行不带:live
参数的命令,然后使用此参数再次执行该命令,执行命令时应该看到完整的gc活动;live
参数,换句话说,完整的gc计数将递增。
第二个命令可能是这样的:
sudo -u tomcat /home/path/to/jmap -histo:live {pid} | head -n 40
顺便说一句,我的JDK版本是JDK7