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 ,还原工作完成。

 

posted @ 2020-12-11 09:47  执生  阅读(437)  评论(0编辑  收藏  举报