GCC の -c
で得られるオブジェクトファイルを Foreign Function & Memory API を使って実行します。
Warning
動的リンカが働かないため、 printf()
など libc を含む外部ライブラリの呼び出しは機能しません。
- Java 22
- Maven
- GCC
$ mvn package
$ mvn exec:exec@run
呼び出し対象の C ソースは src/main/native/test.c です。呼び出す関数は pom.xml の以下の部分で変更可能です。
<execution>
<id>run</id>
<phase>exec</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>${java.home}/bin/java</executable>
<arguments>
<argument>--enable-preview</argument>
<argument>-jar</argument>
<argument>${project.build.directory}/${imageName}.jar</argument>
<argument>${project.build.directory}/test.o</argument>
<!-- ここで関数を指定する(mul2 か mul3) -->
<argument>mul2</argument>
<!-- <argument>mul3</argument> -->
</arguments>
</configuration>
</execution>
gcc -c
で得られたオブジェクトファイルを FileChannel::map で MappedByteBuffer にマップします。そこから MemorySegment
を ofBuffer()
で取得します。
FileChannel::map
には MemorySegment
を返すものも存在しますが、ELF の解析に使う JElf v0.9.0 の ElfFile が ByteBuffer
系は MappedByteBuffer
しか受け付けないため、これを経由して MemorySegment
を取得するようにします。
これに FFM 経由で mprotect()
で実行ビットを立て、実行可能メモリセグメントにします。ELF から取得した関数開始オフセットに対して MethodHandle
を作成し、実行します。