内存堆Gc时公认的根对象

    内存堆的Gc就是回收内存堆中垃圾对象(非active对象),那么这里就有一个问题了,如何寻找垃圾对象?换个思路来解,就是如何找到所有的active的对象,那么剩下的就是垃圾对象了.HotSpot是通过首先找到所谓的根对象,然后根据这些根对象递归或迭代的搜索所有的引用对象,而找到的这些个对象就是所谓的active对象了.其实,Gc时的根对象是一个与运行时上下文相关的概念,以基于内存分代管理的内存代管理器来讲,当对某一个内存代惊进行Minor Gc时,其它内存代中的所有对象都应该被看做是根对象(尽管某些对象可能真的已经是垃圾对象了).本文所要讲的根对象指的是在对内存堆或内存代进行Minor/Full Gc时都认同的“根对象”,这些跟对象主要来源于:Universe相关对象,Java/本地方法栈中的对象等等.

1. Universe相关对象

    Universe模块在JVM中主要负责内存堆的管理这一块,核心就是内存堆管理器的初始化工作.Universe中的根对象主要和JVM内部的Java对象表示模型相关:Klass框架和Oop框架.Klass对象表示的是Java类型的描述信息,Oop对象则是Java实例对象在JVM内存的存在形式.下面简要的介绍常用的几个Klass或Oop对象的内存布局

Klass对象布局


instanceKlass的内存布局

                                                                          

普通java对象的内存布局                                                                                     数组对象的内存布局


   java对象的内存布局中,_metadata表示的是该类型的描述信息对象指针,_mark表示的是该对象运行时状态信息.

1.1 基本类型对应的java.lang.Class对象


   
   
  1. oop Universe::_int_mirror = NULL;
  2. oop Universe::_float_mirror = NULL;
  3. oop Universe::_double_mirror = NULL;
  4. oop Universe::_byte_mirror = NULL;
  5. oop Universe::_bool_mirror = NULL;
  6. oop Universe::_char_mirror = NULL;
  7. oop Universe::_long_mirror = NULL;
  8. oop Universe::_short_mirror = NULL;
  9. oop Universe::_void_mirror = NULL;
  10. oop Universe::_mirrors[T_VOID+ 1] = { NULL /*, NULL...*/ };

1.2 基本类型对应的数组类型的描述信息对象


   
   
  1. klassOop Universe::_boolArrayKlassObj = NULL;
  2. klassOop Universe::_byteArrayKlassObj = NULL;
  3. klassOop Universe::_charArrayKlassObj = NULL;
  4. klassOop Universe::_intArrayKlassObj = NULL;
  5. klassOop Universe::_shortArrayKlassObj = NULL;
  6. klassOop Universe::_longArrayKlassObj = NULL;
  7. klassOop Universe::_singleArrayKlassObj = NULL;
  8. klassOop Universe::_doubleArrayKlassObj = NULL;
  9. klassOop Universe::_typeArrayKlassObjs[T_VOID+ 1] = { NULL /*, NULL...*/ };

1.3 Java类型相关的描述信息对象


   
   
  1. klassOop Universe::_objectArrayKlassObj = NULL;
  2. klassOop Universe::_methodKlassObj = NULL;
  3. klassOop Universe::_constMethodKlassObj = NULL;
  4. klassOop Universe::_methodDataKlassObj = NULL;
  5. klassOop Universe::_klassKlassObj = NULL;
  6. klassOop Universe::_arrayKlassKlassObj = NULL;
  7. klassOop Universe::_objArrayKlassKlassObj = NULL;
  8. klassOop Universe::_typeArrayKlassKlassObj = NULL;
  9. klassOop Universe::_instanceKlassKlassObj = NULL;
  10. klassOop Universe::_constantPoolKlassObj = NULL;
  11. klassOop Universe::_constantPoolCacheKlassObj = NULL;
  12. klassOop Universe::_compiledICHolderKlassObj = NULL;
  13. klassOop Universe::_systemObjArrayKlassObj = NULL;

1.4 常用Java方法描述信息对象

   这里包含了JVM内部频繁使用的3个java方法:java.lang.ref.Finalizer.register()/java.lang.ClassLoader.addClass()/java.lang.reflect.Method.invoke(),先简单的介绍一下这三个java方法的主要用途.


   
   
  1. LatestMethodOopCache* Universe::_finalizer_register_cache = NULL;
  2. LatestMethodOopCache* Universe::_loader_addClass_cache = NULL;
  3. ActiveMethodOopsCache* Universe::_reflect_invoke_cache = NULL;

    在java.lang.Object里面有一个finalize()的空方法,一旦某个类型实现了这个方法,就会触发JVM的内部行为:该类型对应的实例对象在被Gc之后,JVM就会调用它的finalize(),但并不保证一定会调用.


   
   
  1. /**
  2. * 注册一个实现了finalize()的对象,当gc回收该对象时会掉用它的finalize()
  3. */
  4. instanceOop instanceKlass::register_finalizer(instanceOop i, TRAPS) {
  5. if (TraceFinalizerRegistration) {
  6. tty-> print( "Registered ");
  7. i-> print_value_on(tty);
  8. tty-> print_cr( " (" INTPTR_FORMAT ") as finalizable", (address)i);
  9. }
  10. /**
  11. * 构造调用Java方法所需的参数
  12. */
  13. instanceHandle h_i(THREAD, i);
  14. // Pass the handle as argument, JavaCalls::call expects oop as jobjects
  15. JavaValue result(T_VOID);
  16. JavaCallArguments args(h_i);
  17. methodHandle mh (THREAD, Universe::finalizer_register_method());
  18. //调用java.lang.ref.Finalizer.register()方法
  19. JavaCalls:: call(&result, mh, &args, CHECK_NULL);
  20. return h_i();
  21. }
   java.lang.ClassLoader.addClass()主要用于在jni中加载类的调用.

1.5 内存分配相关的异常实例对象


   
   
  1. oop Universe::_out_of_memory_error_java_heap = NULL;
  2. oop Universe::_out_of_memory_error_perm_gen = NULL;
  3. oop Universe::_out_of_memory_error_array_size = NULL;
  4. oop Universe::_out_of_memory_error_gc_overhead_limit = NULL;
  5. objArrayOop Universe::_preallocated_out_of_memory_error_array = NULL;
  6. oop Universe::_null_ptr_exception_instance = NULL;
  7. oop Universe::_arithmetic_exception_instance = NULL;
  8. oop Universe::_virtual_machine_error_instance = NULL;
  9. oop Universe::_vm_exception = NULL;

2. 本地方法创建的全局对象

    JNIHandles中保存了所有Java线程在执行本地方法时申请的全局对象句柄:

JNIHandleBlock* JNIHandles::_global_handles       = NULL;
   
   


全局本地对象句柄的视图


   
   
  1. /**
  2. * 为指定的实例对象分配一个句柄
  3. */
  4. jobject JNIHandleBlock::allocate_handle(oop obj) {
  5. assert(Universe:: heap()-> is_in_reserved(obj), "sanity check");
  6. if (_top == 0) {
  7. // This is the first allocation or the initial block got zapped when
  8. // entering a native function. If we have any following blocks they are
  9. // not valid anymore.
  10. for (JNIHandleBlock* current = _next; current != NULL;
  11. current = current->_next) {
  12. assert(current->_last == NULL, "only first block should have _last set");
  13. assert(current->_free_list == NULL,
  14. "only first block should have _free_list set");
  15. current->_top = 0;
  16. if (ZapJNIHandleArea) current-> zap();
  17. }
  18. // Clear initial block
  19. _free_list = NULL;
  20. _allocate_before_rebuild = 0;
  21. _last = this;
  22. if (ZapJNIHandleArea) zap();
  23. }
  24. //最后一个块有空闲句柄
  25. if (_last->_top < block_size_in_oops) {
  26. oop* handle = &(_last->_handles)[_last->_top++];
  27. *handle = obj;
  28. return (jobject) handle;
  29. }
  30. // Try free list
  31. if (_free_list != NULL) {
  32. oop* handle = _free_list;
  33. _free_list = (oop*) *_free_list;
  34. *handle = obj;
  35. return (jobject) handle;
  36. }
  37. // Check if unused block follow last
  38. if (_last->_next != NULL) {
  39. // update last and retry
  40. _last = _last->_next;
  41. return allocate_handle(obj);
  42. }
  43. // No space available, we have to rebuild free list or expand
  44. if (_allocate_before_rebuild == 0) {
  45. rebuild_free_list(); // updates _allocate_before_rebuild counter
  46. } else { //分配一个新的句柄存储块
  47. // Append new block
  48. Thread* thread = Thread:: current();
  49. Handle obj_handle(thread, obj);
  50. // This can block, so we need to preserve obj accross call.
  51. _last->_next = JNIHandleBlock:: allocate_block(thread);
  52. _last = _last->_next;
  53. _allocate_before_rebuild--;
  54. obj = obj_handle();
  55. }
  56. return allocate_handle(obj); // retry
  57. }
  58. void JNIHandleBlock::oops_do(OopClosure* f) {
  59. JNIHandleBlock* current_chain = this;
  60. // Iterate over chain of blocks, followed by chains linked through the
  61. // pop frame links.
  62. while (current_chain != NULL) {
  63. for (JNIHandleBlock* current = current_chain; current != NULL;
  64. current = current->_next) {
  65. assert(current == current_chain || current-> pop_frame_link() == NULL,
  66. "only blocks first in chain should have pop frame link set");
  67. for ( int index = 0; index < current->_top; index++) {
  68. oop* root = &(current->_handles)[index];
  69. oop value = *root;
  70. // traverse heap pointers only, not deleted handles or free list
  71. // pointers
  72. if (value != NULL && Universe:: heap()-> is_in_reserved(value)) {
  73. f-> do_oop(root);
  74. }
  75. }
  76. // the next handle block is valid only if current block is full
  77. if (current->_top < block_size_in_oops) {
  78. break;
  79. }
  80. }
  81. current_chain = current_chain-> pop_frame_link();
  82. } //while
  83. }
  84. /**
  85. * 遍历所有的全局本地对象
  86. */
  87. void JNIHandles::oops_do(OopClosure* f) {
  88. f-> do_oop(&_deleted_handle);
  89. _global_handles-> oops_do(f);
  90. }

3. 方法栈中的对象

    这里主要指的是每一个Java线程在执行过程中创建的私有局部变量,分为两块:一是在执行Java方法时创建的,二是在执行本地方法时创建的.


   
   
  1. void Threads::oops_do(OopClosure* f, CodeBlobClosure* cf) {
  2. ALL_JAVA_THREADS(p) {
  3. p-> oops_do(f, cf);
  4. }
  5. VMThread:: vm_thread()-> oops_do(f, cf);
  6. }
  7. void Thread::oops_do(OopClosure* f, CodeBlobClosure* cf) {
  8. active_handles()-> oops_do(f); //本地局部对象
  9. // Do oop for ThreadShadow
  10. f-> do_oop((oop*)&_pending_exception); //当前线程可能已经抛出的异常对象
  11. handle_area()-> oops_do(f); //局部对象
  12. }

1.Java方法栈中的对象

  每一个Java线程都私有一个句柄区_handle_area来存储其运行过程中创建的临时对象,这个句柄区是随着Java线程的栈帧变化的,这个句柄区的数据结构如下


    Java线程每调用一个Java方法就会创建一个对应HandleMark来保存此时Java线程分配对象句柄的上下文环境,然后等调用返回后即行恢复:


   
   
  1. void JavaCalls::call_helper(JavaValue* result, methodHandle* m, JavaCallArguments* args, TRAPS) {
  2. ...
  3. {
  4. HandleMark hm(thread); // HandleMark used by HandleMarkCleaner
  5. printf( "%s[%d] [tid: %lu]: 开始执行方法[%s]...\n", __FILE__, __LINE__, pthread_self(), method-> name()-> as_C_string());
  6. StubRoutines:: call_stub()(
  7. (address)&link,
  8. // (intptr_t*)&(result->_value), // see NOTE above (compiler problem)
  9. result_val_address, // see NOTE above (compiler problem)
  10. result_type,
  11. method(),
  12. entry_point,
  13. args-> parameters(),
  14. args-> size_of_parameters(),
  15. CHECK
  16. );
  17. result = link. result(); // circumvent MS C++ 5.0 compiler bug (result is clobbered across call)
  18. // Preserve oop return value across possible gc points
  19. if (oop_result_flag) {
  20. thread-> set_vm_result((oop) result-> get_jobject());
  21. }
  22. }
  23. ...
  24. }
  25. void HandleMark::initialize(Thread* thread) {
  26. _thread = thread;
  27. //保存当前线程分配对象句柄的地址
  28. _area = thread-> handle_area();
  29. // Save current top
  30. _chunk = _area->_chunk;
  31. _hwm = _area->_hwm;
  32. _max = _area->_max;
  33. NOT_PRODUCT(_size_in_bytes = _area->_size_in_bytes;)
  34. debug_only(_area->_handle_mark_nesting++);
  35. assert(_area->_handle_mark_nesting > 0, "must stack allocate HandleMarks");
  36. debug_only(Atomic:: inc(&_nof_handlemarks);)
  37. // Link this in the thread
  38. set_previous_handle_mark(thread-> last_handle_mark());
  39. thread-> set_last_handle_mark( this);
  40. }
  41. HandleMark::~ HandleMark() {
  42. HandleArea* area = _area; // help compilers with poor alias analysis
  43. assert(area == _thread-> handle_area(), "sanity check");
  44. assert(area->_handle_mark_nesting > 0, "must stack allocate HandleMarks" );
  45. debug_only(area->_handle_mark_nesting--);
  46. // Debug code to trace the number of handles allocated per mark/
  47. #ifdef ASSERT
  48. if (TraceHandleAllocation) {
  49. size_t handles = 0;
  50. Chunk *c = _chunk-> next();
  51. if (c == NULL) {
  52. handles = area->_hwm - _hwm; // no new chunk allocated
  53. } else {
  54. handles = _max - _hwm; // add rest in first chunk
  55. while(c != NULL) {
  56. handles += c-> length();
  57. c = c-> next();
  58. }
  59. handles -= area->_max - area->_hwm; // adjust for last trunk not full
  60. }
  61. handles /= sizeof( void *); // Adjust for size of a handle
  62. if (handles > HandleAllocationLimit) {
  63. // Note: _nof_handlemarks is only set in debug mode
  64. warning( "%d: Allocated in HandleMark : %d", _nof_handlemarks, handles);
  65. }
  66. }
  67. #endif
  68. // Delete later chunks
  69. if( _chunk-> next() ) {
  70. _chunk-> next_chop();
  71. }
  72. // 恢复之前线程分配对象句柄的地址
  73. area->_chunk = _chunk;
  74. area->_hwm = _hwm;
  75. area->_max = _max;
  76. NOT_PRODUCT(area-> set_size_in_bytes(_size_in_bytes);)
  77. #ifdef ASSERT
  78. // clear out first chunk (to detect allocation bugs)
  79. if (ZapVMHandleArea) {
  80. memset(_hwm, badHandleValue, _max - _hwm);
  81. }
  82. Atomic:: dec(&_nof_handlemarks);
  83. #endif
  84. // Unlink this from the thread
  85. _thread-> set_last_handle_mark( previous_handle_mark());
  86. }


2.本地方法栈中的对象

    Java线程使用一个对象句柄存储块JNIHandleBlock来为其于在本地方法中申请的临时对象创建对应的句柄,JNIHandleBlock中有一个_pop_frame_link属性,被用来保存Java线程切换方法时分配本地对象句柄的上下文环境.


4. 对象同步监视器中的对象

  对于每一个被synchronized的Java对象,JVM会在内部为其创建一个对应的对象监视器ObjectMonitor,用来控制与其相关的线程:


   
   
  1. void ObjectSynchronizer::oops_do(OopClosure* f) {
  2. assert(SafepointSynchronize:: is_at_safepoint(), "must be at safepoint");
  3. for (ObjectMonitor* block = gBlockList; block != NULL; block = next(block)) {
  4. assert(block-> object() == CHAINMARKER, "must be a block header");
  5. for ( int i = 1; i < _BLOCKSIZE; i++) {
  6. ObjectMonitor* mid = &block[i];
  7. if (mid-> object() != NULL) {
  8. f-> do_oop((oop*)mid-> object_addr());
  9. }
  10. }
  11. }
  12. }

5. Java级管理接口(Management)中的对象

    Management中的根对象主要是关于JVM中的线程/内存/Gc的统计,监控等相关的类型描述信息或对象:


   
   
  1. void Management::oops_do(OopClosure* f) {
  2. MemoryService:: oops_do(f);
  3. ThreadService:: oops_do(f);
  4. f-> do_oop((oop*) &_sensor_klass);
  5. f-> do_oop((oop*) &_threadInfo_klass);
  6. f-> do_oop((oop*) &_memoryUsage_klass);
  7. f-> do_oop((oop*) &_memoryPoolMXBean_klass);
  8. f-> do_oop((oop*) &_memoryManagerMXBean_klass);
  9. f-> do_oop((oop*) &_garbageCollectorMXBean_klass);
  10. f-> do_oop((oop*) &_managementFactory_klass);
  11. f-> do_oop((oop*) &_garbageCollectorImpl_klass);
  12. f-> do_oop((oop*) &_gcInfo_klass);
  13. }

6. 虚拟机工具接口(JVMTI)中的对象

     关于Java虚拟机工具接口中的根对象,本文不详细介绍

7. 系统字典(SystemDictionary)中的对象

    SystemDictionary中的根对象主要包括各种基础类型的描述信息:


   
   
  1. java.lang.Object
  2. java.lang.String
  3. java.lang.Class
  4. java.lang.Cloneable
  5. java.lang.ClassLoader
  6. java.io.Serializable
  7. java.lang.System
  8. java.lang.Throwable
  9. java.lang.Error
  10. java.lang.ThreadDeath
  11. java.lang.Exception
  12. java.lang.RuntimeException
  13. java.security.ProtectionDomain
  14. java.security.AccessControlContext
  15. java.lang.ClassNotFoundException
  16. java.lang.NoClassDefFoundError
  17. java.lang.LinkageError
  18. java.lang.ClassCastException
  19. java.lang.ArrayStoreException
  20. java.lang.VirtualMachineError
  21. java.lang.OutOfMemoryError
  22. java.lang.StackOverflowError
  23. java.lang.IllegalMonitorStateException
  24. java.lang.ref.Reference
  25. java.lang.ref.SoftReference
  26. java.lang.ref.WeakReference
  27. java.lang.ref.FinalReference
  28. java.lang.ref.PhantomReference
  29. java.lang.ref.Finalizer
  30. java.lang.Thread
  31. java.lang.ThreadGroup
  32. java.util.Properties
  33. java.lang.reflect.AccessibleObject
  34. java.lang.reflect.Field
  35. java.lang.reflect.Method
  36. java.lang.reflect.Constructor
  37. sun.reflect.MagicAccessorImpl
  38. sun.reflect.MethodAccessorImpl
  39. sun.reflect.ConstructorAccessorImpl
  40. sun.reflect.DelegatingClassLoader
  41. sun.reflect.ConstantPool
  42. sun.reflect.UnsafeStaticFieldAccessorImpl
  43. java.lang.invoke.MethodHandle
  44. java.lang.invoke.MemberName
  45. java.lang.invoke.MethodHandleNatives
  46. java.lang.invoke.AdapterMethodHandle
  47. java.lang.invoke.BoundMethodHandle
  48. java.lang.invoke.DirectMethodHandle
  49. java.lang.invoke.MethodType
  50. java.lang.invoke.MethodTypeForm
  51. java.lang.BootstrapMethodError
  52. java.lang.invoke.WrongMethodTypeException
  53. java.lang.invoke.CallSite
  54. java.lang.invoke.CountingMethodHandle
  55. java.lang.invoke.ConstantCallSite
  56. java.lang.invoke.MutableCallSite
  57. java.lang.invoke.VolatileCallSite
  58. java.lang.StringBuffer
  59. java.lang.StringBuilder
  60. java.nio.Buffer
  61. sun.misc.AtomicLongCSImpl
  62. sun.jkernel.DownloadManager
  63. sun.misc.PostVMInitHook
  64. java.lang.Boolean
  65. java.lang.Character
  66. java.lang.Float
  67. java.lang.Double
  68. java.lang.Byte
  69. java.lang.Short
  70. java.lang.Integer
  71. java.lang.Long

8. 字符串常量表(StringTable)中的对象

   顾名思义,字符串常量表中存储的主要是常量字符串,特别是类型的全限定名,方法的签名等对应的字符串.

9. 代码高速缓存区中的对象

    代码高速缓存区CodeCache中主要存储的Java方法被本地编译之后对应的代码片段.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值