曾今讨论过jstat 的实现,见另一篇博客(http://blog.csdn.net/raintungli/article/details/7444980),这里就不详细讨论了。jstat 主要是负责读取,而在这篇博客主要是讨论performance data的初始化和产生的。
初始话
vm_init_globals()
void vm_init_globals() {check_ThreadShadow();basic_types_init();eventlog_init();mutex_init();chunkpool_init();perfMemory_init();
}
源码中可以看到perfMemory.cpp中perfMemory_init()函数,也就是performance data 的初始化,对于参数UsePerfData , 在product是编译成true,也就是我们使用oracle提供的编译的jvm时,是打开perf data的
void perfMemory_init() {if (!UsePerfData) return;PerfMemory::initialize();
}
对于initialize 的方法中调用不同的操作系统的create_memory_region方法,这里主要讨论的是linux环境
void PerfMemory::create_memory_region(size_t size) {if (PerfDisableSharedMem) {// do not share the memory for the performance data._start = create_standard_memory(size);}else {_start = create_shared_memory(size);if (_start == NULL) {// creation of the shared memory region failed, attempt// to create a contiguous, non-shared memory region instead.//if (PrintMiscellaneous && Verbose) {warning("Reverting to non-shared PerfMemory region.\n");}PerfDisableSharedMem = true;_start = create_standard_memory(size);}}if (_start != NULL) _capacity = size;}
参数PerfDisableSharedMem控制是使用标准的或者共享的内存,标准和共享的区分在一个是jvm的内存里,一个是生成文件/tmp/hsperfdata_{userid}/{pid} 通过mmap映射到内存中去,而别的进程可以通过文件来访问内容。对参数PerfDisableSharedMem,产品线上编译成false,也就是默认使用共享策略。
申请内存
perfData.cpp中的方法PerfData::create_entry(BasicType dtype, size_t dsize, size_t vlen) 调用perfMemory.alloc的方法,perfData中对内存做了保护,如果大于performance memory 初始话申请的内存的大小时,会直接在c的heap中申请.
两个基本类PerfByteArray, PerfLong 的构造器中都是调用了方法PerfData::create_entry从performance data 的内存中申请到了内存。其他的PerfLongConstant,PerfLongCounter,等都是继承这两个类中的一个。
类PerfDataManager 是util类,是别的组件的申请调用写入performance data的入口,主要作用去实例化PerfLongConstant,PerfLongCounter的类调用的顺序PerDataManager.create_long_counter->new Class PerfLong->PerfData::create_entry->PerfMemory::alloc