Arena 决定一块堆外内存的寿命。四种 Arena 差在哪?段能多大?堆段与原生段有哪些差别?内存映射文件怎么用?这篇逐项运行。
1 四种 Arena:
global:可写读 16 字节;scope().isAlive()=true
global.close():UnsupportedOperationException: Attempted to close a non-closeable session
auto:isAlive=true
auto.close():UnsupportedOperationException: Attempted to close a non-closeable session
confined:isAlive=true;close 之后 isAlive=false
shared:isAlive=true;close 之后 isAlive=false
confined 在其它线程 close():WrongThreadException: Attempted access outside owning thread
shared 在其它线程 close():成功
同一个 Arena 里再分配 3 次,地址是否各不相同:true 2 新分配的 1 MB 段是否全为 0:true;对齐:allocate(1, 64) 的地址 % 64 = 0;allocate(1, 4096) 的地址 % 4096 = 0
allocate(8, 3):IllegalArgumentException: Invalid alignment constraint : 3
allocate(-1):IllegalArgumentException: The provided allocation size is negative: -1 3 allocate(3 GB):byteSize=3221225472;RSS 增加 3076 MB(allocate 把整段清零,页被真正占用)
写最后一个字节 9;RSS 增加 3082 MB
3 GB 段 asByteBuffer():IllegalStateException: Segment is too large to wrap as ByteBuffer. Size: 3221225472
3 GB 段 toArray(JAVA_BYTE):IllegalStateException: Segment is too large to wrap as byte[]. Size: 3221225472
asSlice(1 GB, 16).byteSize()=16
asSlice 越过末尾:IndexOutOfBoundsException: Out of bound access on segment MemorySegment{ kind: native, address: 0x7c40800000, byteSize: 3221225472 }; attempting to get slice of length
Arena 关闭后立即 RSS 相对开始增加 3084 MB
关闭 2 秒并 System.gc() 之后 RSS 相对开始增加 3086 MB 4 128 MB:fill 4 ms;MemorySegment.copy 原生→堆 5 ms;copyFrom 2 ms;System.arraycopy 堆→堆 13 ms;mismatch(相同内容)返回 -1,11 ms
改动堆数组第 1000 字节后 mismatch = 1000
堆段:isNative=false,heapBase 存在=true;原生段 isNative=true
堆段 address()=0(只是数组内偏移)
堆段 reinterpret(16):UnsupportedOperationException: Not a native segment
int[] 段 byteSize=16;按 JAVA_INT 读第 2 个=2;按 JAVA_BYTE 读第 4 个字节(小端的 2)=2
int[] 段上读 JAVA_LONG offset 0:IllegalArgumentException: Target offset 0 is incompatible with alignment constraint 8 (of j8) for segment MemorySegment{ kind: heap, heapBase: [I@3d646c37, address: 0
int[] 段上读 JAVA_LONG_UNALIGNED offset 4:12884901890 5 映射文件 4096 字节:isMapped=true,isNative=true;写入 magic 与字符串并 force()
映射 3 GB:byteSize=3221225472,文件长度变为 3072 MB
Arena 关闭后用普通 IO 读回前 4 字节(小端):bebafeca;字符串位置读回:mapped-by-FFM