jvm源码解读--02 Array<u1>* tags = MetadataFactory::new_writeable_array<u1>(loader_data, length, 0, CHECK_NULL); 函数引入的jvm内存分配解析
current路径:
#0 Array<unsigned char>::operator new (size=8, loader_data=0x7fd4c802e868, length=87, read_only=false, __the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/utilities/array.hpp:324
#1 0x00007fd4cebf27ba in MetadataFactory::new_writeable_array<unsigned char> (loader_data=0x7fd4c802e868, length=87, __the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/memory/metadataFactory.hpp:52
#2 0x00007fd4cebf2537 in MetadataFactory::new_writeable_array<unsigned char> (loader_data=0x7fd4c802e868, length=87, value=0 '\000', __the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/memory/metadataFactory.hpp:57
#3 0x00007fd4cebe9a95 in ConstantPool::allocate (loader_data=0x7fd4c802e868, length=87, __the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/oops/constantPool.cpp:47
#4 0x00007fd4ceb28bbc in ClassFileParser::parse_constant_pool (this=0x7fd4d06f2010, __the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/classFileParser.cpp:331
#5 0x00007fd4ceb34e84 in ClassFileParser::parseClassFile (this=0x7fd4d06f2010, name=0x7fd4cc1050e8, loader_data=0x7fd4c802e868, protection_domain=..., host_klass=..., cp_patches=0x0, parsed_name=..., verify=false, __the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/classFileParser.cpp:3774
#6 0x00007fd4ceb439b5 in ClassFileParser::parseClassFile (this=0x7fd4d06f2010, name=0x7fd4cc1050e8, loader_data=0x7fd4c802e868, protection_domain=..., parsed_name=..., verify=false, __the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/classFileParser.hpp:468
#7 0x00007fd4ceb417cb in ClassLoader::load_classfile (h_name=0x7fd4cc1050e8, __the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/classLoader.cpp:931
#8 0x00007fd4cf181903 in SystemDictionary::load_instance_class (class_name=0x7fd4cc1050e8, class_loader=..., __the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:1304
#9 0x00007fd4cf17fced in SystemDictionary::resolve_instance_class_or_null (name=0x7fd4cc1050e8, class_loader=..., protection_domain=..., __the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:779
#10 0x00007fd4cf17e6be in SystemDictionary::resolve_or_null (class_name=0x7fd4cc1050e8, class_loader=..., protection_domain=..., __the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:232
#11 0x00007fd4cf17e12f in SystemDictionary::resolve_or_fail (class_name=0x7fd4cc1050e8, class_loader=..., protection_domain=..., throw_error=true, __the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:171
#12 0x00007fd4cf17e451 in SystemDictionary::resolve_or_fail (class_name=0x7fd4cc1050e8, throw_error=true, __the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:212
#13 0x00007fd4cf18327b in SystemDictionary::initialize_wk_klass (id=SystemDictionary::Object_klass_knum, init_opt=0, __the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:1866
#14 0x00007fd4cf18339e in SystemDictionary::initialize_wk_klasses_until (limit_id=SystemDictionary::Cloneable_klass_knum, start_id=@0x7fd4d06f29ec: SystemDictionary::Object_klass_knum, __the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:1882
#15 0x00007fd4cf186b86 in SystemDictionary::initialize_wk_klasses_through (end_id=SystemDictionary::Class_klass_knum, start_id=@0x7fd4d06f29ec: SystemDictionary::Object_klass_knum, __the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.hpp:408
#16 0x00007fd4cf1834d0 in SystemDictionary::initialize_preloaded_classes (__the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:1901
#17 0x00007fd4cf18319d in SystemDictionary::initialize (__the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp:1843
#18 0x00007fd4cf1d41d1 in Universe::genesis (__the_thread__=0x7fd4c800b800) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/memory/universe.cpp:288
#19 0x00007fd4cf1d6439 in universe2_init () at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/memory/universe.cpp:991
#20 0x00007fd4ced6fa5c in init_globals () at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/runtime/init.cpp:114
#21 0x00007fd4cf1b7756 in Threads::create_vm (args=0x7fd4d06f2e40, canTryAgain=0x7fd4d06f2dff) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/runtime/thread.cpp:3424
#22 0x00007fd4cee22232 in JNI_CreateJavaVM (vm=0x7fd4d06f2e88, penv=0x7fd4d06f2e80, args=0x7fd4d06f2e40) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/hotspot/src/share/vm/prims/jni.cpp:5166
#23 0x00007fd4d00bf780 in InitializeJVM (pvm=0x7fd4d06f2e88, penv=0x7fd4d06f2e80, ifn=0x7fd4d06f2e90) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/jdk/src/share/bin/java.c:1145
#24 0x00007fd4d00bd6f9 in JavaMain (_args=0x7ffdde8bac20) at /home/atzhang/atzhang/openjdksource/openjdk8/openjdk/jdk/src/share/bin/java.c:371
#25 0x00007fd4d02d9ea5 in start_thread () from /lib64/libpthread.so.0
#26 0x00007fd4cfbe29fd in clone () from /lib64/libc.so.6
进入这个函数
void* operator new(size_t size, ClassLoaderData* loader_data, int length, bool read_only, TRAPS) throw() {
size_t word_size = Array::size(length);
return (void*) Metaspace::allocate(loader_data, word_size, read_only,
MetaspaceObj::array_type(sizeof(T)), CHECK_NULL);
}
说明length= word_size=12,进入标橘子的函数,解释一下这个T为u1,能看到为case1
static MetaspaceObj::Type array_type(size_t elem_size) { //elem_size=1
switch (elem_size) {
case 1: return TypeArrayU1Type; //这个
case 2: return TypeArrayU2Type;
case 4: return TypeArrayU4Type;
case 8: return TypeArrayU8Type;
default:
return TypeArrayOtherType;
}
}
进入主函数
MetaWord* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size, //word_size=12
bool read_only, MetaspaceObj::Type type, TRAPS) { //参数type= TypeArrayU1Type
if (HAS_PENDING_EXCEPTION) {
assert(false, "Should not allocate with exception pending");
return NULL; // caller does a CHECK_NULL too
} assert(loader_data != NULL, "Should never pass around a NULL loader_data. "
"ClassLoaderData::the_null_class_loader_data() should have been used."); // Allocate in metaspaces without taking out a lock, because it deadlocks
// with the SymbolTable_lock. Dumping is single threaded for now. We'll have
// to revisit this for application class data sharing.
if (DumpSharedSpaces) { //不进入
assert(type > MetaspaceObj::UnknownType && type < MetaspaceObj::_number_of_types, "sanity");
Metaspace* space = read_only ? loader_data->ro_metaspace() : loader_data->rw_metaspace();
MetaWord* result = space->allocate(word_size, NonClassType);
if (result == NULL) {
report_out_of_shared_space(read_only ? SharedReadOnly : SharedReadWrite);
} space->record_allocation(result, type, space->vsm()->get_raw_word_size(word_size)); // Zero initialize.
Copy::fill_to_aligned_words((HeapWord*)result, word_size, 0); return result;
} MetadataType mdtype = (type == MetaspaceObj::ClassType) ? ClassType : NonClassType; //这里mdtype= NonClassType // Try to allocate metadata.
MetaWord* result = loader_data->metaspace_non_null()->allocate(word_size, mdtype); if (result == NULL) {
// Allocation failed.
if (is_init_completed()) {
// Only start a GC if the bootstrapping has completed. // Try to clean out some memory and retry.
result = Universe::heap()->collector_policy()->satisfy_failed_metadata_allocation(
loader_data, word_size, mdtype);
}
} if (result == NULL) {
report_metadata_oome(loader_data, word_size, mdtype, CHECK_NULL);
} // Zero initialize.
Copy::fill_to_aligned_words((HeapWord*)result, word_size, 0); return result;
}
进入主函数,标记为黄色的
Metaspace* ClassLoaderData::metaspace_non_null() {
assert(!DumpSharedSpaces, "wrong metaspace!");
// If the metaspace has not been allocated, create a new one. Might want
// to create smaller arena for Reflection class loaders also.
// The reason for the delayed allocation is because some class loaders are
// simply for delegating with no metadata of their own.
if (_metaspace == NULL) { //不为0 直接返回
MutexLockerEx ml(metaspace_lock(), Mutex::_no_safepoint_check_flag);
// Check again if metaspace has been allocated while we were getting this lock.
if (_metaspace != NULL) {
return _metaspace;
}
if (this == the_null_class_loader_data()) {
assert (class_loader() == NULL, "Must be");
set_metaspace(new Metaspace(_metaspace_lock, Metaspace::BootMetaspaceType));
} else if (is_anonymous()) {
if (TraceClassLoaderData && Verbose && class_loader() != NULL) {
tty->print_cr("is_anonymous: %s", class_loader()->klass()->internal_name());
}
set_metaspace(new Metaspace(_metaspace_lock, Metaspace::AnonymousMetaspaceType));
} else if (class_loader()->is_a(SystemDictionary::reflect_DelegatingClassLoader_klass())) {
if (TraceClassLoaderData && Verbose && class_loader() != NULL) {
tty->print_cr("is_reflection: %s", class_loader()->klass()->internal_name());
}
set_metaspace(new Metaspace(_metaspace_lock, Metaspace::ReflectionMetaspaceType));
} else {
set_metaspace(new Metaspace(_metaspace_lock, Metaspace::StandardMetaspaceType));
}
}
return _metaspace;
}
元空间 _metaspace
上边直接返回没什么可看的,现在看下这个_metaspace
(gdb) p *_metaspace
$2 = (Metaspace) {<CHeapObj<256u>> = {<AllocatedObj> = {_vptr.AllocatedObj = 0x7fd4cfa2c870 <vtable for Metaspace+16>}, <No data fields>},
static _compressed_class_space_size = 0x40000000, //默认大小40M
static _first_chunk_word_size = 0x80000, //第一个NonClassType类型的MetaChunk的大小
static _first_class_chunk_word_size = 0xc000, //第一个ClassType类型的MetaChunk的大小
static _commit_alignment = 0x1000, //commit内存的粒度
static _reserve_alignment = 0x1000, //reserve内存的粒度
_vsm = 0x7fd4c8050298, //NonClassType类型的元数据对应的SpaceManager
_class_vsm = 0x7fd4c8050328, //ClassType类型的元数据对应的SpaceManager
static _space_list = 0x7fd4c802e608, // NonClassType类型的元数据对应的VirtualSpaceList
static _class_space_list = 0x7fd4c802e3a8, // ClassType类型的元数据对应的VirtualSpaceList
static _chunk_manager_metadata = 0x7fd4c802e778, //NonClassType类型的元数据对应的ChunkManager
static _chunk_manager_class = 0x7fd4c802e518, // ClassType类型的元数据对应的ChunkManager
_alloc_record_head = 0x0, //AllocRecord链表的头部元素
_alloc_record_tail = 0x0} //AllocRecord链表的尾部元素
这个现在还不太懂,慢慢来吧
进入主函数标橘子色的后半部分_metaspace->allocate(word_size, mdtype);
MetaWord* Metaspace::allocate(size_t word_size, MetadataType mdtype) {
// DumpSharedSpaces doesn't use class metadata area (yet)
// Also, don't use class_vsm() unless UseCompressedClassPointers is true.
if (is_class_space_allocation(mdtype)) {//不成立
return class_vsm()->allocate(word_size); //不进入
} else {
return vsm()->allocate(word_size);
}
}
SpaceManager* vsm() const { return _vsm; }
_vsm的天下,就是_vsm->allocate()
主流程接着看
MetaWord* SpaceManager::allocate(size_t word_size) {
MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); size_t raw_word_size = get_raw_word_size(word_size);
BlockFreelist* fl = block_freelists();
MetaWord* p = NULL;
// Allocation from the dictionary is expensive in the sense that
// the dictionary has to be searched for a size. Don't allocate
// from the dictionary until it starts to get fat. Is this
// a reasonable policy? Maybe an skinny dictionary is fast enough
// for allocations. Do some profiling. JJJ
if (fl->total_size() > allocation_from_dictionary_limit) {
p = fl->get_block(raw_word_size);
}
if (p == NULL) {
p = allocate_work(raw_word_size);
} return p;
}
进入橘子程序
size_t get_raw_word_size(size_t word_size) {
size_t byte_size = word_size * BytesPerWord; size_t raw_bytes_size = MAX2(byte_size, sizeof(Metablock)); //sizeof(Metablock)=24
//返回96
raw_bytes_size = align_size_up(raw_bytes_size, Metachunk::object_alignment());
size_t raw_word_size = raw_bytes_size / BytesPerWord;
//返回12
assert(raw_word_size * BytesPerWord == raw_bytes_size, "Size problem"); return raw_word_size;
}
查看类结构
class Metablock : public Metabase<Metablock> {
friend class VMStructs;
public:
Metablock(size_t word_size) : Metabase<Metablock>(word_size) {}
};
// Super class of Metablock and Metachunk to allow them to
// be put on the FreeList and in the BinaryTreeDictionary.
template <class T>
class Metabase VALUE_OBJ_CLASS_SPEC {
size_t _word_size;
T* _next;
T* _prev; protected:
Metabase(size_t word_size) : _word_size(word_size), _next(NULL), _prev(NULL) {} public:
T* next() const { return _next; }
T* prev() const { return _prev; }
void set_next(T* v) { _next = v; assert(v != this, "Boom");}
void set_prev(T* v) { _prev = v; assert(v != this, "Boom");}
void clear_next() { set_next(NULL); }
void clear_prev() { set_prev(NULL); } size_t size() const volatile { return _word_size; }
void set_size(size_t v) { _word_size = v; } void link_next(T* ptr) { set_next(ptr); }
void link_prev(T* ptr) { set_prev(ptr); }
void link_after(T* ptr) {
link_next(ptr);
if (ptr != NULL) ptr->link_prev((T*)this);
} uintptr_t* end() const { return ((uintptr_t*) this) + size(); } bool cantCoalesce() const { return false; } bool verify_chunk_in_free_list(T* tc) const { return true; }
bool verify_par_locked() { return true; } void assert_is_mangled() const {/* Don't check "\*/} bool is_free() { return true; }
};
主流程,进入紫色程序
//进入到这个函数 BlockFreelist* fl = block_freelists();
BlockFreelist* block_freelists() const {
return (BlockFreelist*) &_block_freelists;
BlockFreelist _block_freelists;
查看内存内容
(gdb) p _block_freelists
$4 = {_dictionary = 0x0, static WasteMultiplier = 4}
蓝色上边不执行的if判断
if (fl->total_size() > allocation_from_dictionary_limit) {
p = fl->get_block(raw_word_size);
} size_t total_size() {
if (dictionary() == NULL) {
return 0; //执行到这里
} else {
return dictionary()->total_size();
}
}
进入蓝色程序,这个就是_vsm
// Returns the address of spaced allocated for "word_size".
// This methods does not know about blocks (Metablocks)
MetaWord* SpaceManager::allocate_work(size_t word_size) {
assert_lock_strong(_lock); // Is there space in the current chunk?
MetaWord* result = NULL; // For DumpSharedSpaces, only allocate out of the current chunk which is
// never null because we gave it the size we wanted. Caller reports out
// of memory if this returns null.
if (DumpSharedSpaces) { //不进入,跳过
assert(current_chunk() != NULL, "should never happen");
inc_used_metrics(word_size);
return current_chunk()->allocate(word_size); // caller handles null result
} if (current_chunk() != NULL) { //到这里 Metachunk* current_chunk() const { return _current_chunk; }
result = current_chunk()->allocate(word_size); //Metachunk* _current_chunk;
} if (result == NULL) {
result = grow_and_allocate(word_size);
} if (result != NULL) {
inc_used_metrics(word_size);
assert(result != (MetaWord*) chunks_in_use(MediumIndex),
"Head of the list is being allocated");
} return result;
}
主程序进入灰色的函数,是这个Metachunk的类进行了内存分配
//接着进入
MetaWord* Metachunk::allocate(size_t word_size) { //word_size =12
MetaWord* result = NULL;
// If available, bump the pointer to allocate.
if (free_word_size() >= word_size) {
result = _top;
_top = _top + word_size;
}
return result;
}
看下Metachunk对象的内存结构
(gdb) p/x _current_chunk
$5 = 0x7fd4b8800000
(gdb) p/x * _current_chunk
$6 = {<Metabase<Metachunk>> = {_word_size = 0x80000, _next = 0x0, _prev = 0x0},
_container = 0x7fd4c802e678,
_top = 0x7fd4b88000a8,
_is_tagged_free = 0x0}
查看Metachunk类的结果
class Metachunk : public Metabase<Metachunk> {
friend class TestMetachunk; // The VirtualSpaceNode containing this chunk.
VirtualSpaceNode *_container; // Current allocation top.
MetaWord *_top;
...省略方法
}
进入黄色函数内部
进入free_word_size() 方法
size_t Metachunk::free_word_size() const {
return pointer_delta(end(), _top, sizeof(MetaWord));
}
inline size_t pointer_delta(const void* left,
const void* right,
size_t element_size) {
return (((uintptr_t) left) - ((uintptr_t) right)) / element_size;
}
看的这里就知道了是用_current_chunk的end()-_top地址
// Metachunk - Quantum of allocation from a Virtualspace
// Metachunks are reused (when freed are put on a global freelist) and
// have no permanent association to a SpaceManager. // +--------------+ <- end --+ --+ 0x7fd4b8c00000
// | | | |
// | | | free |
// | | | |
// | | | | size | capacity
// | | | |
// | | <- top -- + | 0x7fd4b88000a8
// | | | |
// | | | used |
// | | | |
// | | | |
// +--------------+ <- bottom --+ --+
看end()函数的实现,是在Metachunk的父类Metabase中定义的
class Metabase VALUE_OBJ_CLASS_SPEC {
size_t _word_size;
T* _next;
T* _prev; protected:
size_t size() const volatile { return _word_size; }
Metabase(size_t word_size) : _word_size(word_size), _next(NULL), _prev(NULL) {} public:
....
uintptr_t* end() const { return ((uintptr_t*) this) + size(); } ...
};
那么这个end() 就是理解为Metabase的word_size=0x80000+ Metabase的地址 计算后得到 0x7fd4b8c00000
那么这个top就是Metachunk类中_top成员函数
接着进入红色函数
void SpaceManager::inc_used_metrics(size_t words) {
// Add to the per SpaceManager total
Atomic::add_ptr(words, &_allocated_blocks_words);
// Add to the global total
MetaspaceAux::inc_used(mdtype(), words);
}
其中查看内存
// Sum of all space in allocated chunks
size_t _allocated_blocks_words; //15个 这条就牛逼了
Atomic::add_ptr(words, &_allocated_blocks_words); //word=12 ,
(gdb) p this
$25 = (SpaceManager * const) 0x7fd4c8050298
(gdb) p _allocated_blocks_words
$26 = 15
进入分红函数
inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) {
intptr_t addend = add_value;
bool mp = os::is_MP();
__asm__ __volatile__ (LOCK_IF_MP(%3) "xaddq %0,(%2)"
: "=r" (addend)
: "0" (addend), "r" (dest), "r" (mp)
: "cc", "memory");
return addend + add_value;
}
这个是内联汇编的打印汇编内容
//解释,这个是将12 加上 目标地址的值15,和为27,汇编指令为
(gdb) x/15i $pc
=> 0x7fd4ce975528 <Atomic::add_ptr(long, long volatile*)+32>: mov -0x8(%rbp),%rax //这个是参数1,为12
0x7fd4ce97552c <Atomic::add_ptr(long, long volatile*)+36>: mov -0x20(%rbp),%rdx //这个是参数2,为指针地址
0x7fd4ce975530 <Atomic::add_ptr(long, long volatile*)+40>: movzbl -0x9(%rbp),%ecx
0x7fd4ce975534 <Atomic::add_ptr(long, long volatile*)+44>: cmp $0x0,%cl
0x7fd4ce975537 <Atomic::add_ptr(long, long volatile*)+47>: je 0x7fd4ce97553a <Atomic::add_ptr(long, long volatile*)+50>
0x7fd4ce975539 <Atomic::add_ptr(long, long volatile*)+49>: lock xadd %rax,(%rdx) //交换叫加,等价于 xchg eax,(),那么$rax=15,(%rdx)=12,然后$rax=27
0x7fd4ce97553e <Atomic::add_ptr(long, long volatile*)+54>: mov %rax,-0x8(%rbp) 将27 存到指针地址,即为参数2的地址,将和存入了_allocated_blocks_words
0x7fd4ce975542 <Atomic::add_ptr(long, long volatile*)+58>: mov -0x18(%rbp),%rax
0x7fd4ce975546 <Atomic::add_ptr(long, long volatile*)+62>: mov -0x8(%rbp),%rdx
0x7fd4ce97554a <Atomic::add_ptr(long, long volatile*)+66>: add %rdx,%rax
0x7fd4ce97554d <Atomic::add_ptr(long, long volatile*)+69>: leaveq
0x7fd4ce97554e <Atomic::add_ptr(long, long volatile*)+70>: retq
查看内存情况
(gdb) p this
$39 = (SpaceManager * const) 0x7fd4c8050298
(gdb) p * this
$40 = (SpaceManager) {<CHeapObj<256u>> = {<AllocatedObj> = {_vptr.AllocatedObj = 0x7fd4cfa2c890 <vtable for SpaceManager+16>}, <No data fields>},
_lock = 0x7fd4c802e8f8,
_mdtype = Metaspace::NonClassType,
_chunks_in_use = {0x0, 0x0, 0x0, 0x7fd4b8800000},
_current_chunk = 0x7fd4b8800000,
static _small_chunk_limit = 4,
_allocated_blocks_words = 27, //将上边的汇编操作将15变成了17
_allocated_chunks_words = 524288,
_allocated_chunks_count = 1,
_block_freelists = {_dictionary = 0x0, static WasteMultiplier = 4},
static _expand_lock_name = 0x7fd4cf466138 "SpaceManager chunk allocation lock",
static _expand_lock_rank = 3, static _expand_lock = 0x930758}
(gdb) p _vsm
$42 = (SpaceManager *) 0x7fd4c8050298,上面的就是这个_vsm
接着走流程 return result; 就是分配的top值
(gdb) p result
$43 = (MetaWord *) 0x7fd4b88000a8
这个对象上边的黄色函数跳出的结果
接着走流程进入最早的橘色2
// Zero initialize.
Copy::fill_to_aligned_words((HeapWord*)result, word_size, 0);
copy.hpp
static void fill_to_aligned_words(HeapWord* to, size_t count, juint value = 0) {
assert_params_aligned(to);
pd_fill_to_aligned_words(to, count, value);
} //copy_x86.cpp
static void pd_fill_to_aligned_words(HeapWord* tohw, size_t count, juint value) {
pd_fill_to_words(tohw, count, value);
} static void pd_fill_to_words(HeapWord* tohw, size_t count, juint value) {
#ifdef AMD64
julong* to = (julong*) tohw;
julong v = ((julong) value << 32) | value;
while (count-- > 0) {
*to++ = v;
}
#else
juint* to = (juint*)tohw;
count *= HeapWordSize / BytesPerInt;
while (count-- > 0) {
*to++ = value;
}
#endif // AMD64
}
打印内存结构
(gdb) p tohw
$44 = (HeapWord *) 0x7fd4b88000a8
//以上是使用0 进行填充
(gdb) x/40x 0x7fd4b88000a8
0x7fd4b88000a8: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fd4b88000b8: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fd4b88000c8: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fd4b88000d8: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fd4b88000e8: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fd4b88000f8: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fd4b8800108: 0xf7f7f7f7 0xf7f7f7f7 0xf7f7f7f7 0xf7f7f7f7
至此就完成了 Array<u1>* 的12*8个字节的内存分配和初始化,即12个MetaWord
jvm源码解读--02 Array<u1>* tags = MetadataFactory::new_writeable_array<u1>(loader_data, length, 0, CHECK_NULL); 函数引入的jvm内存分配解析的更多相关文章
- jvm源码解读--03 常量池的解析ConstantPool
先看bt栈 (gdb) bt #0 ConstantPool::allocate (loader_data=0x7fe21802e868, length=87, __the_thread__=0x7f ...
- JVM 源码解读之 CMS 何时会进行 Full GC
t点击上方"涤生的博客",关注我 转载请注明原创出处,谢谢!如果读完觉得有收获的话,欢迎点赞加关注. 前言 本文内容是基于 JDK 8 在文章 JVM 源码解读之 CMS GC 触 ...
- jvm源码解读--06 Method 方法解析
进入 // Methods bool has_final_method = false; AccessFlags promoted_flags; promoted_flags.set_flags(0) ...
- jvm源码解读--08 创建oop对象,将static静态变量放置在oop的96 offset处
之前分析的已经加载的.Class文件中都没有Static 静态变量,所以也就没这部分的解析,自己也是不懂hotspot 将静态变量放哪里去了,追踪源码之后,看清楚了整个套路,总体上来说,可以举例来说对 ...
- jvm源码解读--17 Java的wait()、notify()学习
write and debug by 张艳涛 wait()和notify()的通常用法 A线程取得锁,执行wait(),释放锁; B线程取得锁,完成业务后执行notify(),再释放锁; B线程释放锁 ...
- jvm源码解读--11 ldc指令的解读
写一个java文件 public static void main(String[] args) { String str1="abc"; String str2 ="a ...
- jvm源码解读--04 常量池 常量项的解析CONSTANT_Class_info
接上篇的继续 ConstantPool* constant_pool = ConstantPool::allocate(_loader_data, length, CHECK_(nullHandle) ...
- jvm源码解读--16 cas 用法解析
CAS的意思是campare and sweep比较交换 这个如果不用代码会比较抽象,那么在源码中进行解释 void ATTR ObjectMonitor::enter(TRAPS) { // The ...
- jvm源码解读--13 gc_root中的栈中oop的mark 和copy 过程分析
粘贴源码 package com.test; import java.util.Random; public class Test { static int number=12; private in ...
随机推荐
- day20200911
UG12.0进入运动仿真模块 新建仿真 定义固定连杆 定义其他连杆 定义运动副 定义驱动 定义解算方案并求解 导出动画
- Vue——v-for动态绑定id的问题
问题:在Vue中,会遇到许多个多选框,倘若数量很庞大那么一个一个input框.label节点寻找,这样操作很繁琐. 直接上解决方案吧: html页面: <ul v-for="(item ...
- NOIP模拟测试9「随·单·题」
liu_runda出的题,先$\%\%\%\%\%\%\%\%\%\%\%$为敬 随 考试时没有Qj 然后甚至没做,甚至没交 我不知道我怎么想的 这个题挺难改 你需要用到 循环矩阵快速幂,矩阵快速幂优 ...
- Java安全之Fastjson内网利用
Java安全之Fastjson内网利用 0x00 前言 在打Fastjson的时候,基本上都是使用JNDI注入的方式去打,也就是 JdbcRowSetImpl 链分析的链去打,但是遇到一些不出网的情况 ...
- hive学习笔记之四:分区表
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- excel VBA中Xldown和xlup用法
1.Worksheets("Sheet1").Range("A1").End(xlDown).Select '意思为自A1起,返回从上往下的最后一个非空 ...
- 浅谈最长上升子序列(O(n*logn)算法)
今天GM讲了最长上升子序列的logn*n算法,但没讲思路... 我看了篇博客,发现-- 说的有道理!!! 首先,举例子: a[7]={1,2,4,3,6,7,5}(假设以1开头) 很明显,LIS=5: ...
- web自动化之windows页面切换
一.为什么切换windows页面 在页面操作过程中,存在点击某个元素之后会重新打开一个windows页面,如果不切换至新页面的话,无法在新页面中进行操作,程序会出现报错 二.如何切换 1.获取当前所有 ...
- [心得体会]SpringMVC源码分析
1. SpringMVC (1) springmvc 是什么? 前端控制器, 主要控制前端请求分配请求任务到service层获取数据后反馈到springmvc的view层进行包装返回给tomcat, ...
- mysql中的空值
空值,即NULL,在数据库中通过is null 和is not null来查询 陷阱一:空值不一定为空 空值是一个比较特殊的字段.在MySQL数据库中,在不同的情形下,空值往往代表不同的含义.这是My ...