设为首页 加入收藏

TOP

源码分析:Java对象的内存分配(二)
2015-12-01 14:11:47 来源: 作者: 【 】 浏览:21
Tags:源码 分析 Java 对象 内存 分配
数定义在/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp中:


IRT_ENTRY(void, InterpreterRuntime::_new(JavaThread* thread, constantPoolOopDesc* pool, int index))
? klassOop k_oop = pool->klass_at(index, CHECK);
? instanceKlassHandle klass (THREAD, k_oop);


? // Make sure we are not instantiating an abstract klass
? klass->check_valid_for_instantiation(true, CHECK);


? // Make sure klass is initialized
? klass->initialize(CHECK);


? oop obj = klass->allocate_instance(CHECK);
? thread->set_vm_result(obj);
IRT_END


  该函数在进行了对象类的检查(确保不是抽象类)和对该类型进行初始化后,调用instanceKlassHandle的allocate_instance进行内存分配。
  其中instanceKlassHandle类由DEF_KLASS_HANDLE宏进行声明,注意该类重载了成员访问运算符”->”,这里的一系列成员方法的访问实际上是instanceKlass对象的访问。


?type*? ? operator -> () const? ? ? { return (type*)obj()->klass_part(); }


  2.所以实际上是调用了instanceKlass的allocate_instance()成员函数:
  allocate_instance()定义在/hotspot/src/share/vm/oops/instanceKlass.cpp
  (1).检查是否设置了Finalizer函数,获取对象所需空间的大小


instanceOop instanceKlass::allocate_instance(TRAPS) {
? ? bool has_finalizer_flag = has_finalizer(); // Query before possible GC
? ? int size = size_helper();? // Query before forming handle.


  (2).调用CollectedHeap的obj_allocate()创建一个instanceOop(堆上的对象实例),并根据情况注册Finalizer函数


    KlassHandle h_k(THREAD, as_klassOop());


? ? ? instanceOop i;


? ? ? i = (instanceOop)CollectedHeap::obj_allocate(h_k, size, CHECK_NULL);
? ? ? if (has_finalizer_flag && !RegisterFinalizersAtInit) {
? ? ? ? i = register_finalizer(i, CHECK_NULL);
? ? ? }
? ? ? return i;


  3.CollectedHeap::ojb_allocate()定义在/hotspot/src/share/vm/gc_interface/CollectedHeap.hpp中,它将转而调用内联函数obj_allocate()


  4.obj_allocate()定义在/hotspot/src/share/vm/gc_interface/CollectedHeap.inline.h中,若当正处于gc状态时,不允许进行内存分配申请,否则将调用common_mem_allocate_init()进行内存分配并返回获得内存的起始地址,随后将调用post_allocation_setup_obj()进行一些初始化工作 


oop CollectedHeap::obj_allocate(KlassHandle klass, int size, TRAPS) {
?//...assert
? HeapWord* obj = common_mem_allocate_init(size, false, CHECK_NULL);
? post_allocation_setup_obj(klass, obj, size);
? NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size));
? return (oop)obj;
}


  5.common_mem_allocate_init()分为两部分,将分别调用common_mem_allocate_noinit()进行内存空间的分配和调用init_obj()进行对象空间的初始化


HeapWord* CollectedHeap::common_mem_allocate_init(size_t size, bool is_noref, TRAPS) {
? HeapWord* obj = common_mem_allocate_noinit(size, is_noref, CHECK_NULL);
? init_obj(obj, size);
? return obj;
}


  6.common_mem_allocate_noinit()如下:
  (1).若使用了本地线程分配缓冲TLAB,则会调用allocate_from_tlab()尝试从TLAB中分配内存


? HeapWord* result = NULL;
? if (UseTLAB) {
? ? result = CollectedHeap::allocate_from_tlab(THREAD, size);
? ? if (result != NULL) {
? ? ? assert(!HAS_PENDING_EXCEPTION,
? ? ? ? ? ? "Unexpected exception, will result in uninitialized storage");
? ? ? return result;
? ? }
? }


  (2).否则会调用堆的mem_allocate()尝试分配


 


? bool gc_overhead_limit_was_exceeded = false;
? result = Universe::heap()->mem_allocate(size,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? is_noref,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? false,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? &gc_overhead_limit_was_exceeded);


  (3).统计分配的字节数


?if (result != NULL) {
? //...
? ? THREAD->incr_allocated_bytes(size * HeapWordSize);
? ? return result;
? }


  (4).否则说明申请失败,若在申请过程中gc没有超时,则抛出OOM异常


if (!gc_overhead_limit_was_exceeded) {
? ? // -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError support
? ? report_java_out_of_memory("Java heap s

首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇数据库Blob数据类型转String 下一篇Java常量池解析与字符串intern简介

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: