3. 内存管理模型中对内存描述的封装
关于ProjectTungsten相关内容,可以参考https://github.com/hustnn/TungstenSecret。其中对PageTable给出了描述非常详细的说明图。
下面从最基本的源码开始逐步分析内存管理模型中内存描述的封装。主要包含内存地址的封装和内存块的封装,分别对应MemoryLocation与MemoryBlock。
在ProjectTungsten中,为了统一管理on-heap与off-heap两种内存模式,引入了统一的地址表示形式,即通过MemoryLocation类来表示on-heap或off-heap两种内存模式下的地址。
首先查看该类的注释信息,具体如下所示:
1. /** 2. * A memory location. Tracked either by a memory address (with off-heap allocation), 3. * or by an offset from a JVM object (in-heap allocation). 4. *一个内存地址。用于跟踪off-heap模式下的内存地址或on-heap模式下的内存地址。 5. */ 6. public class MemoryLocation { |
当使用off-heap内存模式时,内存地址可以通过64bit的绝对地址来描述,对应的,但使用on-heap内存模式时,由于GC过程中会对堆(heap)内存进行重组,因此地址的定位需要通过对象在堆内存的引用以及在该对象内的偏移量来表示,此时便需要对象引用和一个偏移量来表示内存地址。
因此,在MemoryLocation中定义了两个成员变量,具体代码如下所示:
1. @Nullable 2. Object obj; 3. long offset; |
对应两种不同的内存模式,两个成员变量的描述如下:
off-heap内存模式:obj为null,地址由64bit的offset唯一标识。
on-heap内存模式:obj为堆中该对象的引用,offset对应数据在该对象中的偏移量。
由以上分析可知,通过MemoryLocation类可以统一定位一个off-heap与on-heap两种内存模式下的内存地址。
对应MemoryLocation类的继承子类为MemoryBlock,顾名思义,该子类表示一个内存块,不管是是off-heap或on-heap内存模式,在ProjectTungsten内存管理时,都使用一块连续的内存空间来存储数据,因此即使是在on-heap模式下,也可以降低GC的开销。下面查看下MemoryBlock类的注释信息,具体如下所示:
1. /** 2. * A consecutive block of memory, starting at a {@link MemoryLocation} with a fixed size. 3. *一个连续的内存块,继承自描述内存地址的 MemoryLocation 类,同时提供内存块的 4. *大小。 5. */ 6. public class MemoryBlock extends MemoryLocation { |
补充:在代码复用方式上存在两种形式,继承与组合。目前在MemoryBlock中使用继承的方式包含内存块的地址信息。在实现上,也可以采用组合这种复用方式,指定内存块的地址,以及内存块本身的内存大小。
下面简单介绍下MemoryBlock类中除了继承自MemoryLocation类之外的部分成员:
private final long length:表示内存块的长度。
public int pageNumber :表示内存块对应的page号,该属性在后续部分会详细讲解。
public static MemoryBlockfromLongArray(final long[] array):这是提供的一个将long型数组转换为MemoryBlock内存块的接口。
在提供了内存块之后,进一步的就是如何去组织这些内存块,在Project Tungsten中采用了类似操作系统的内存管理模式,即使用Page Table方式来管理内存。因此,下面开始对Page Table管理方式进行解析。