JVM学习:Handle-中间指针,HandleArea-记录Handle存区,Chunk-存储区域,HandleMark-保存chunk链状态
Chunk
HandlArea
等继承了 CheapObj 的类,都是需要重载 new,delete 等方法的,而这些new,delete方法,其实就是 平常C的 malloc (通过os::malloc)和 free(通过os::delete)方法
而JVM的Heap对象堆和上面的C堆是不同概念
Handle 主要是为了 JNI 代码引用的 java 对象在 GC 时候被移动,也能被 JNI 代码找到,类似智能指针包装真正的指针,起到一层代理的作用
java 线程 有一条内存块链条专门存 handle
JNI代码在执行 java 方法的时候,会记录 当前这条内存链用到哪里了,当调用java方法结束,需要回到之前记录的地方,也就是 如果调用的java方法中有创建对象,那么调用完成的时候就需要解除对他们的引用,java 方法执行过程中,因为有 handle 引用他们,所以不会被 GC 回收。
一个指针p指向对象A的起始地址,如果每个人都拿着这个指针p。
那么GC改变这个对象A的位置的时候,每个人的指针都要变,很不方便。
让这些人持有一个指向Handle的指针,通过Handle的指针去获取Handle里关于对象的起始地址就很方便
只用改一次Handle就行了
Handle重载了操作符(),obj就是被包装对象的指针
Handle在哪分配?在HandleArea分配,属于同一个线程的HandleArea通过 _prev 指针连成一条链。
HandArea保存了一条Chunk,Chunk是真正用来存储东西的区域,在堆中。
其实Chunk自己只有两个属性,_next记录下一个Chunk,_len记录长度,剩下一大片空白是额外分配来真真正正存储东西的区域
_first 记录了第一个chunk的起始地址,_chunk记录了当前chunk的起始地址
_max记录了当前chunk的可用极限地址,_hwm是已经使用了的部分的顶部,下面灰色部分是已经被分配使用了的。
Chunk的底部是 Chunk的起始地址 + sizeof(Chunk) 也就是_next的结尾
top = bottom + len,可以看出Chunk的顶部在高地址部分,Chunk是向高地址增长的,大概率在堆中
HandleMark:
也是一种成链的结构,每个HandleMark保存当前线程chunk链的状态(当前_hwm 和 _max 和 当前 _chunk 以及area引用)
在HandleMark销毁(析构函数)时,HandleMark通过next_chop()调用free去把当前chunk链中当前chunk之后的chunk都销毁。
这些chunk都是HandleMark创建之后分配的,也就是HandleMark保存的状态之后的改变,所以要销毁。接着把area的chunk设置成当前
chunk,并且设置_hwm 和 _max ,还原工作完成。