Repository navigation
jcmd jmap_old
ceragon edited this page Aug 2, 2022
·
5 revisions
$ jmap -histo:live pid
num #instances #bytes class name (module)
-------------------------------------------------------
1: 350965 612819840 [B (java.base@11.0.4)
2: 75791 21757000 [Ljava.lang.Object; (java.base@11.0.4)
3: 658665 21077280 java.util.HashMap$Node (java.base@11.0.4)
4: 384262 18444576 java.util.HashMap (java.base@11.0.4)
5: 175259 16354736 [Ljava.util.HashMap$Node; (java.base@11.0.4)
6: 84084 15047344 [I (java.base@11.0.4)
7: 131072 11534336 io.netty.buffer.PooledUnsafeDirectByteBuf
8: 287688 9206016 io.netty.util.Recycler$DefaultHandle以 histo 为例
public class JMap {
public static void main(String[] args) throws Exception {
if (option.equals("-histo")) {
histo(pid, "");
} else if (option.startsWith("-histo:")) {
histo(pid, option.substring("-histo:".length()));
} else if (option.startsWith("-dump:")) {
dump(pid, option.substring("-dump:".length()));
} else if (option.equals("-finalizerinfo")) {
executeCommandForPid(pid, "jcmd", "GC.finalizer_info");
} else if (option.equals("-clstats")) {
executeCommandForPid(pid, "jcmd", "GC.class_stats");
}
}
}public class JMap {
private static void histo(String pid, String options)
throws AttachNotSupportedException, IOException,
UnsupportedEncodingException {
String liveopt = "-all";
if (subopt.equals("live")) {
liveopt = "-live";
}
executeCommandForPid(pid, "inspectheap", liveopt, parallel);
}
private static void executeCommandForPid(String pid, String command, Object ... args)
throws AttachNotSupportedException, IOException,
UnsupportedEncodingException {
VirtualMachine vm = VirtualMachine.attach(pid);
HotSpotVirtualMachine hvm = (HotSpotVirtualMachine) vm;
try (InputStream in = hvm.executeCommand(command, args)) {
byte b[] = new byte[256];
int n;
do {
n = in.read(b);
if (n > 0) {
String s = new String(b, 0, n, "UTF-8");
System.out.print(s);
}
} while (n > 0);
}
vm.detach();
}
}public abstract class HotSpotVirtualMachine extends VirtualMachine {
public InputStream executeCommand(String cmd, Object ... args) throws IOException {
return execute(cmd, args);
}
}public class VirtualMachineImpl extends HotSpotVirtualMachine {
String socket_path;
InputStream execute(String cmd, Object ... args) throws AgentLoadException, IOException {
int s = socket();
connect(s, socket_path);
IOException ioe = null;
// 写协议类型和命令
writeString(s, PROTOCOL_VERSION);
writeString(s, cmd);
// 写入参数
for (int i=0; i<3; i++) {
if (i < args.length && args[i] != null) {
writeString(s, (String)args[i]);
} else {
writeString(s, "");
}
}
SocketInputStream sis = new SocketInputStream(s);
int completionStatus;
completionStatus = readInt(sis);
return sis;
}
}public class VirtualMachineImpl extends HotSpotVirtualMachine {
static native int socket() throws IOException;
static native void connect(int fd, String path) throws IOException;
static native void write(int fd, byte buf[], int off, int bufLen) throws IOException;
}JNIEXPORT jint JNICALL Java_sun_tools_attach_VirtualMachineImpl_socket
(JNIEnv *env, jclass cls)
{
int fd = socket(PF_UNIX, SOCK_STREAM, 0);
return (jint)fd;
}JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_connect
(JNIEnv *env, jclass cls, jint fd, jstring path)
{
const char* p = GetStringPlatformChars(env, path, &isCopy);
struct sockaddr_un addr;
strncpy(addr.sun_path, p, sizeof(addr.sun_path) - 1);
connect(fd, (struct sockaddr*)&addr, sizeof(addr));
}JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_write
(JNIEnv *env, jclass cls, jint fd, jbyteArray ba, jint off, jint bufLen)
{
write(fd, buf, len)
}static AttachOperationFunctionInfo funcs[] = {
{ "agentProperties", get_agent_properties },
{ "datadump", data_dump },
{ "dumpheap", dump_heap },
{ "load", load_agent },
{ "properties", get_system_properties },
{ "threaddump", thread_dump },
{ "inspectheap", heap_inspection },
{ "setflag", set_flag },
{ "printflag", print_flag },
{ "jcmd", jcmd },
{ NULL, NULL }
};static jint heap_inspection(AttachOperation* op, outputStream* out) {
bool live_objects_only = true;
const char* arg0 = op->arg(0);
live_objects_only = strcmp(arg0, "-live") == 0;
VM_GC_HeapInspection heapop(out, live_objects_only /* request full gc */);
VMThread::execute(&heapop);
return JNI_OK;
}class VM_GC_HeapInspection: public VM_GC_Operation {
outputStream* _out;
bool _full_gc;
};
void VM_GC_HeapInspection::doit() {
if (_full_gc) {
// 执行 fullgc
collect()
}
HeapInspection inspect(_csv_format, _print_help, _print_class_stats,
_columns);
inspect.heap_inspection(_out);
}
bool VM_GC_HeapInspection::collect() {
if (GCLocker::is_active()) {
return false;
}
Universe::heap()->collect_as_vm_thread(GCCause::_heap_inspection);
return true;
}void CollectedHeap::collect_as_vm_thread(GCCause::Cause cause) {
switch (cause) {
case GCCause::_heap_inspection:
case GCCause::_heap_dump:
case GCCause::_metadata_GC_threshold : {
do_full_collection(false); // don't clear all soft refs
break;
}
}
}