Skip to content

jcmd jmap_old

ceragon edited this page Aug 2, 2022 · 5 revisions

jmap old

显示样例

$ 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");
        } 
    }
}

以 histo 为例

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;
    }
}

jvm 文件socket 接口

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;
}

socket

JNIEXPORT jint JNICALL Java_sun_tools_attach_VirtualMachineImpl_socket
  (JNIEnv *env, jclass cls)
{
    int fd = socket(PF_UNIX, SOCK_STREAM, 0);
    return (jint)fd;
}

connect

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));
}

write

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)
}

jvm 执行指令

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;
}

HeapInspection & GC

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;
}

gc

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;
        }
    }
}

HeapInspection

Clone this wiki locally