我们知道 jmap -histo:live 会触发完整的 gc 以确定活动对象:
由于 jmap -histo 考虑了堆中的所有对象(年轻代和老年代的对象),我的观点是, jmap -histo 也可以触发完整的 gc。但是,我找不到关于 jmap -histo 是否会触发完整 gc 的可靠文档。
jmap -histo 可以触发完整的垃圾收集吗?
我们知道 jmap -histo:live 会触发完整的 gc 以确定活动对象:
由于 jmap -histo 考虑了堆中的所有对象(年轻代和老年代的对象),我的观点是, jmap -histo 也可以触发完整的 gc。但是,我找不到关于 jmap -histo 是否会触发完整 gc 的可靠文档。
jmap -histo 可以触发完整的垃圾收集吗?
jmap -histo
不会触发完整的 gc,但会jmap -histo:live
。
有更多 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);
}
三元运算符 in使用参数Jmap.histo()
调用 heapHisto in :jdk/src/share/classes/sun/tools/attach/HotSpotVirtualMachine.java
-live
// 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。
不,jmap -histo
不会触发 FullGC。我经常打印直方图,在我的 GC 日志中看不到任何 Full GC。
我不知道它是如何在 VM 中实现的,但您不必担心完整的 GC。
以我的经验:是的,它是。当你做这个实验时,你可以使用命令:
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
参数的命令,然后使用此参数再次执行,当命令执行带;live
参数时,您应该看到完整的 gc 活动,换句话说,完整的gc 计数将增加。
第二个命令可能是这样的:
sudo -u tomcat /home/path/to/jmap -histo:live {pid} | head -n 40
顺便说一下,我的JDK版本是JDK7