UsePerfData:如果关闭了UsePerfData这个参数,那么jvm启动过程中perf memory都不会被创建,默认情况是是打开的
PerfDisableSharedMem:该参数决定了存储PerfData的内存是不是可以被共享,也就是说不管这个参数设置没设置,jvm在启动的时候都会分配一块内存来存PerfData,只是说这个PerfData是不是其他进程可见的问题,如果设置了这个参数,说明不能被共享,此时其他进程将访问不了该内存,这样一来,譬如我们jps,jstat等都无法工作。默认这个参数是关闭的,也就是默认支持共享的方式
由于perfdata文件时通过mmap共享的,因此考虑看下perfdata文件的创建过程,看看跟mmap的MAP_SHARED和MAP_PRIVATE两个标志位是如何联系在一起的。perfdata文件底层是使用mmap接口实现的,而mmap接口的参数中有关于内存可见性的两个参数:MAP_SHARED和MAP_PRIVATE,如果JVM参数设置允许perfdata文件共享,则使用MAP_SHARED标记。
源码分析
perfdata文件在jvm启动的时候创,在init.cpp文件中:
void vm_init_globals() { check_ThreadShadow(); basic_types_init(); eventlog_init(); mutex_init(); chunkpool_init(); perfMemory_init(); }
在perfMemory.cpp文件中看下perfMemory_init()方法,
void perfMemory_init() { if (!UsePerfData) return; PerfMemory::initialize(); }
可以看出,如果UsePerfData参数设置为false,则直接返回,不会创建perfdata文件;接着看PerfMemory::initialize()方法,在这个方法里会调用create_memory_region(capacity);,用于申请perfdata的内存区域;create_memory_region这个方法不同的平台有不同的实现,我们这里看linux平台下的实现;
看下perfMemory_linux.cpp里的代码,可以看到另一熟悉的JVM参数——PerfDisableSharedMem,如果这个参数设置为false,则会创建perfdata文件,但是其他进程无法共享这块内存,会导致jps、jstat等工具无法使用;
// create the PerfData memory region//// This method creates the memory region used to store performance// data for the JVM. The memory may be created in standard or// shared memory.//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; }
首先看create_shared_memory(size)的实现:
create_shared_memory(size) ——> mmap_create_shared(size)——>mapAddress = (char)::mmap((char)0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);,在这里看到了MAP_SHARED标记。
然后看create_standard_memory(size)的实现,这里并没有跟之前猜想的一样(用mmap方法建映射,传入MAP_PRIVATE标记),而是使用了os::reserve_memory(size)
方法,用来分配一段堆内存。
// Standard Memory Implementation Details// create the PerfData memory region in standard memory.//static char* create_standard_memory(size_t size) { // allocate an aligned chuck of memory char* mapAddress = os::reserve_memory(size); if (mapAddress == NULL) { return NULL; } // commit memory if (!os::commit_memory(mapAddress, size, !ExecMem)) { if (PrintMiscellaneous && Verbose) { warning("Could not commit PerfData memory\n"); } os::release_memory(mapAddress, size); return NULL; } return mapAddress; }
至此可以确认两个结论
创建shared内存,使用mmap,并传入MAP_SHARED标记
创建standard内存,使用os::reserve_memory分配一段堆内存,这点跟之前猜想的不一样
作者:杜琪
链接:https://www.jianshu.com/p/5bda99bf191b
共同學習,寫下你的評論
評論加載中...
作者其他優(yōu)質文章