S-JIS[2024-09-23] 変更履歴

Java外部関数およびメモリーAPI MemorySegment

Java外部関数およびメモリーAPIのMemorySegmentのメモ。


概要

MemorySegmentは、メモリー領域を指すインターフェース。
(内部では、メモリーのアドレス(ポインター)とバイト数を保持している)

import java.lang.foreign.MemorySegment;

MemorySegmentはArenaのallocate()allocateFrom()によって生成する。 (メモリーを確保する)

    MemorySegment m = arena.allocateFrom(ValueLayout.JAVA_INT, 123);
    System.out.println(m);		// → MemorySegment{ address: 0x195f40a20f0, byteSize: 4 }

また、SymbolLookupのfind()によって見つけられたシンボルもMemorySegmentで返される。

    MemorySegment add = symbolLookup.findOrThrow("add");

Javaのヒープ上のオブジェクト(配列)をMemorySegmentとして管理させることも出来る。(このときはアドレスは0になる)

    byte[] bytes = { 0x12, 0x34 };
    MemorySegment m = MemorySegment.ofArray(bytes);

MemorySegmentのstaticメソッド

メソッド 説明
MemorySegment ofBuffer(Buffer buffer) BufferからMemorySegmentを生成する。 var buffer = ByteBuffer.wrap(new byte[] { 0x12, 0x34 });
MemorySegment m = MemorySegment.ofBuffer(buffer);
MemorySegment ofArray(xxx[] byteArray) Javaの配列からMemorySegmentを生成する。 MemorySegment m = MemorySegment.ofArray(new byte[] { 0x12, 0x34 });
void copy(MemorySegment srcSegment, long srcOffset, MemorySegment dstSegment, long dstOffset, long bytes) データをコピーする。 MemorySegment s = MemorySegment.ofArray(new byte[] { 0x12, 0x34 });
MemorySegment d = arena.allocate(2);
MemorySegment.copy(s, 0, d, 0, 2);
void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long srcOffset, MemorySegment dstSegment, ValueLayout dstElementLayout, long dstOffset, long elementCount) MemorySegment.copy(s, ValueLayout.JAVA_BYTE, 0, d, ValueLayout.JAVA_BYTE, 0, 2);
void copy(MemorySegment srcSegment, ValueLayout srcLayout, long srcOffset, Object dstArray, int dstIndex, int elementCount) var bytes = new byte[2];
MemorySegment.copy(s, ValueLayout.JAVA_BYTE, 0, bytes, 0, 2);
static void copy(Object srcArray, int srcIndex, MemorySegment dstSegment, ValueLayout dstLayout, long dstOffset, int elementCount) byte[] bytes = { 0x12, 0x34 };
MemorySegment.copy(bytes, 0, d, ValueLayout.JAVA_BYTE, 0, 2);
long mismatch(MemorySegment srcSegment, long srcFromOffset, long srcToOffset, MemorySegment dstSegment, long dstFromOffset, long dstToOffset)    

MemorySegmentのメソッド

メソッド 説明
long address() アドレスを返す。
(Javaヒープ上のオブジェクトを管理している場合は0が返る)
m.address()
long byteSize() バイト数を返す。 m.byteSize()
Optional<Object> heapBase() Javaヒープ上のオブジェクトを管理している場合は、そのオブジェクトを返す。  
Stream<MemorySegment> elements(MemoryLayout elementLayout) データのStreamを返す。 Stream<MemorySegment> stream = m.elements(ValueLayout.JAVA_BYTE);
List<String> list = stream.map(ms -> ms.get(ValueLayout.JAVA_BYTE, 0)).map("%02x"::formatted).toList();
Scope scope() スコープを返す。 m.scope().isAlive()
boolean isAccessibleBy(Thread thread)    
long maxByteAlignment()    
MemorySegment asSlice(long offset, long newSize) スライス(元のメモリー領域の一部分への参照)を返す。
スライスに対して値をセットすると、元のMemorySegmentにも反映される。
MemorySegment slice = m.asSlice(0, 2);
MemorySegment asSlice(long offset, long newSize, long byteAlignment)  
MemorySegment asSlice(long offset, MemoryLayout layout)  
MemorySegment asSlice(long offset)  
MemorySegment reinterpret(long newSize)    
MemorySegment reinterpret(Arena arena, Consumer<MemorySegment> cleanup);  
MemorySegment reinterpret(long newSize, Arena arena, Consumer<MemorySegment> cleanup)  
boolean isReadOnly() 読み取り専用かどうか。  
MemorySegment asReadOnly() 読み取り専用のMemorySegmentを返す。  
boolean isNative()    
boolean isMapped()    
Optional<MemorySegment> asOverlappingSlice(MemorySegment other)    
MemorySegment fill(byte value) 指定された値で埋める。
(戻り値は自分自身)
m.fill((byte) 0);
MemorySegment copyFrom(MemorySegment src)   MemorySegment s = MemorySegment.ofArray(new byte[] { 0x12, 0x34 });
MemorySegment d = arena.allocate(2);
d.copyFrom(s);
long mismatch(MemorySegment other)    
boolean isLoaded()    
void load()    
void unload()    
void force()    
ByteBuffer asByteBuffer() ByteBufferを返す。  
xxx[] toArray(ValueLayout.XXX elementLayout) 配列を返す。 byte[] bytes = s.toArray(ValueLayout.JAVA_BYTE);
String getString(long offset) '\0'で終端されたUTF-8をStringにして返す。 String s = m.getString(0);
String getString(long offset, Charset charset)    
void setString(long offset, String str) Stringを'\0'で終端されたUTF-8に変換して格納する。
領域サイズより長い文字列を格納することは出来ない。
m.setString(0, "def");
void setString(long offset, String str, Charset charset)    
xxx get(ValueLayout.XXX layout, long offset) xxx型として値を取得する。 for (int i = 0; i < m.byteSize(); i++) {
  byte b = m.get(ValueLayout.JAVA_BYTE, i);
  System.out.printf("%02x%n", b);
}
void set(ValueLayout.XXX layout, long offset, xxx value) xxx型の値をセットする。 m.set(ValueLayout.JAVA_BYTE, 0, (byte) 0xff);
MemorySegment get(AddressLayout layout, long offset)    
void set(AddressLayout layout, long offset, MemorySegment value)    
xxx getAtIndex(ValueLayout.XXX layout, long index)    
void setAtIndex(ValueLayout.XXX layout, long index, xxx value)    
MemorySegment getAtIndex(AddressLayout layout, long index)    
void setAtIndex(AddressLayout layout, long index, MemorySegment value)    

外部関数およびメモリーAPIへ戻る / Java目次へ戻る / 新機能へ戻る / 技術メモへ戻る
メールの送信先:ひしだま