Skip to content

jcmd monitoredVM

wangkaiwu edited this page May 29, 2022 · 1 revision

monitoredVM 生成

共享内存的创建

static char* mmap_create_shared(size_t size) {
    int result;
    int fd;
    char* mapAddress;
    int vmid = os::current_process_id();
    char* user_name = get_user_name(geteuid());
    char* dirname = get_user_tmp_dir(user_name, vmid, -1);
    char* filename = get_sharedmem_filename(dirname, vmid, -1);
    char* short_filename = strrchr(filename, '/');
    fd = create_sharedmem_resources(dirname, short_filename, size);
    // share memory 映射
    mapAddress = (char*)::mmap((char*)0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    result = ::close(fd);
    return mapAddress;
}
static char* create_shared_memory(size_t size) {
    return mmap_create_shared(size);
}

perfData 的初始化

class PerfMemory : AllStatic {
private:
    static char*  _start;
    static char*  _end;
    static size_t _capacity;
    static PerfDataPrologue*  _prologue;
};
void PerfMemory::create_memory_region(size_t size) {
    if (PerfDisableSharedMem) {
        // 共享内存禁用
    } else {
        // _start 是分配的 share memory 的起始地址
        _start = create_shared_memory(size);
    }
    if (_start != NULL) _capacity = size;
}

void PerfMemory::initialize() {
    size_t capacity = align_up(PerfDataMemorySize,
                             os::vm_allocation_granularity());
    // 申请一块共享内存,容量是 capacity
    create_memory_region(capacity);
    _prologue = (PerfDataPrologue *)_start;
    _end = _start + _capacity;
    _top = _start + sizeof(PerfDataPrologue);
    // 以下是 perfData 开场白部分的初始化
    // 魔数
    _prologue->magic = (jint)0xcafec0c0;
    // 大小端
    _prologue->byte_order = PERFDATA_BIG_ENDIAN;
    // perfData 版本
    _prologue->major_version = PERFDATA_MAJOR_VERSION;
    _prologue->minor_version = PERFDATA_MINOR_VERSION;
    _prologue->accessible = 0;
    // 数据部分的偏移(刨除了开场白的部分)
    _prologue->entry_offset = sizeof(PerfDataPrologue);
    // 有多少条数据
    _prologue->num_entries = 0;
    // 使用了多少
    _prologue->used = 0;
    // 是否溢出
    _prologue->overflow = 0;
    // 时间戳
    _prologue->mod_time_stamp = 0;
}

创建一个新条目

char* PerfMemory::alloc(size_t size) {
    char* result = _top;
    _top += size;
    _prologue->used = (jint)used();
    _prologue->num_entries = _prologue->num_entries + 1;
    return result;
}
void PerfData::create_entry(BasicType dtype, size_t dsize, size_t vlen) {
    size_t dlen = vlen==0 ? 1 : vlen;
    size_t size = sizeof(PerfDataEntry) + namelen;
    size_t data_start = size;
    size += (dsize * dlen);
    // psmp 是 alloc 之前的 _top 指针
    char* psmp = PerfMemory::alloc(size);
    // 可以看出来,entry 的名字是放在 PerfDataEntry 结构体后面的
    char* cname = psmp + sizeof(PerfDataEntry);
    // 而 valuep 则是数据真正开始的位置(在name后面)
    void* valuep = (void*) (psmp + data_start);
    // 给 name 赋值
    strcpy(cname, name());
    // 开始给 PerfDataEntry 赋值,内容大概看看就好
    PerfDataEntry* pdep = (PerfDataEntry*)psmp;
    pdep->entry_length = (jint)size;
    pdep->name_offset = (jint) ((uintptr_t) cname - (uintptr_t) psmp);
    pdep->vector_length = (jint)vlen;
    pdep->data_type = (jbyte) type2char(dtype);
    pdep->data_units = units();
    pdep->data_variability = variability();
    pdep->flags = (jbyte)flags();
    pdep->data_offset = (jint) data_start;
    // entry 的起始位置
    _pdep = pdep;
    // value 的起始位置
    _valuep = valuep;
}

创建字符串类型条目

PerfByteArray::PerfByteArray(CounterNS ns, const char* namep, Units u,
                             Variability v, jint length)
                            : PerfData(ns, namep, u, v), _length(length) {
    create_entry(T_BYTE, sizeof(jbyte), (size_t)_length);
}
class PerfString : public PerfByteArray {
    PerfString(CounterNS ns, const char* namep, Variability v, jint length,
               const char* initial_value)
              : PerfByteArray(ns, namep, U_String, v, length) {
       if (is_valid()) set_string(initial_value);
    }
};

字符串常量

PerfStringConstant::PerfStringConstant(CounterNS ns, const char* namep,
                                       const char* initial_value)
                     : PerfString(ns, namep, V_Constant,
                                  initial_value == NULL ? 1 :
                                  MIN2((jint)(strlen((char*)initial_value)+1),
                                       (jint)(PerfMaxStringConstLength+1)),
                                  initial_value) {
}

字符串变量

class PerfStringVariable : public PerfString {
    PerfStringVariable(CounterNS ns, const char* namep, jint max_length,
                       const char* initial_value)
                      : PerfString(ns, namep, V_Variable, max_length+1,
                                   initial_value) { }
};

创建 long 类型条目

PerfLong::PerfLong(CounterNS ns, const char* namep, Units u, Variability v)
                 : PerfData(ns, namep, u, v) {
    create_entry(T_LONG, sizeof(jlong));
}

long 类型常量

class PerfLongConstant : public PerfLong {
    PerfLongConstant(CounterNS ns, const char* namep, Units u,
                     jlong initial_value=0)
                    : PerfLong(ns, namep, u, V_Constant) {
        if (is_valid()) *(jlong*)_valuep = initial_value;
    }    
};

long 类型变量

class PerfLongVariant : public PerfLong {
    PerfLongVariant(CounterNS ns, const char* namep, Units u, Variability v,
                    jlong initial_value=0)
                   : PerfLong(ns, namep, u, v) {
        if (is_valid()) *(jlong*)_valuep = initial_value;
    }
};

Clone this wiki locally