Java21で正式リリースの Virtual Thread を使ってみた(その2)

Java19でプレビュー、Java21で正式リリースとなった Virtual Thread（仮想スレッド）を使ってみた。続編。
JNIに追加された関数を使ってみた。

```java: ThreadExecutor.java
package pkg;

public class ThreadExecutor {
	
	/*
	 * JNI C言語ライブラリのロード
	 */
	static {
		System.loadLibrary("JNIVThread");
	}
		
	public static void main(String[] args) throws InterruptedException {

		MyRunnable runnable = new MyRunnable();
		
		// プラットフォームスレッドとして実行する場合
		Thread pthread = Thread.ofPlatform().start(runnable);
		System.out.println("pthread is Virtual ? : " + pthread.isVirtual());
		// スレッドが終了するまで待つ
		pthread.join();
		
		// 仮想スレッドとして実行する場合
		Thread vthread = Thread.ofVirtual().start(runnable);
		System.out.println("vthread is Virthal ? : " + vthread.isVirtual());
		// スレッドが終了するまで待つ
		vthread.join();
	}
}

/**
 * スレッドで実行したい処理
 */
class MyRunnable implements Runnable {

	/*
	 * JNI nativeを付けたメソッドを呼ぶとC言語の関数が呼び出される
	 */
	public native static void writeLog(String message);

	public native static void putThreadObj(Thread thread);

	@Override
	public void run() {
		System.out.println("--> I am Thread. I am Virtual ? : "
			+ Thread.currentThread().isVirtual());
		
		// JNI: C言語モジュールに文字列を渡す
		writeLog("Java");

		// JNI: C言語モジュールに現在のThreadオブジェクトを渡す
		putThreadObj(Thread.currentThread());
		
	}
}
```

```shell: JavaコンパイルとJNIヘッダ生成
# java -version
java version "21.0.2" 2024-01-16 LTS
Java(TM) SE Runtime Environment (build 21.0.2+13-LTS-58)
Java HotSpot(TM) 64-Bit Server VM (build 21.0.2+13-LTS-58, mixed mode, sharing)

# javac -h jni pkg/ThreadExecutor.java

# tree
.
tqq jni
x   mqq pkg_MyRunnable.h
mqq pkg
    tqq MyRunnable.class
    tqq ThreadExecutor.class
    mqq ThreadExecutor.java
```
```c: pkg_MyRunnable.h (自動生成コード)
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class pkg_MyRunnable */

#ifndef _Included_pkg_MyRunnable
#define _Included_pkg_MyRunnable
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     pkg_MyRunnable
 * Method:    writeLog
 * Signature: (Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_pkg_MyRunnable_writeLog
  (JNIEnv *, jclass, jstring);

/*
 * Class:     pkg_MyRunnable
 * Method:    putThreadObj
 * Signature: (Ljava/lang/Thread;)V
 */
JNIEXPORT void JNICALL Java_pkg_MyRunnable_putThreadObj
  (JNIEnv *, jclass, jobject);

#ifdef __cplusplus
}
#endif
#endif
```


C言語側の関数定義を作る
```c:pkg_MyRunnable.c
#include "pkg_MyRunnable.h"

JNIEXPORT void JNICALL Java_pkg_MyRunnable_writeLog(JNIEnv *env, jclass class, jstring message)
{
    int jni_ver = (*env)->GetVersion(env);
    switch (jni_ver)
    {
        case JNI_VERSION_21:
            printf("====> JNI_VERSION = JNI_VERSION_21\n");
            printf("====> 0x%08x\n", jni_ver);
            break;
    
        default:
            printf("====> 0x%08x\n", jni_ver);
            break;
    }

    const char *pmsg = (*env)->GetStringUTFChars(env, message, NULL);
    printf("====> C meets : %s\n", pmsg);
    return;
}

JNIEXPORT void JNICALL Java_pkg_MyRunnable_putThreadObj(JNIEnv *env, jclass class, jobject thread)
{
    jboolean jbool = (*env)->IsVirtualThread(env, thread);
    printf("====> IsVirtualThread ? : %hhu\n", jbool);
}
```
```shell: Cコンパイルと共有ライブラリを生成
# gcc -fPIC -shared -I /usr/java/jdk-21/include/ -I /usr/java/jdk-21/include/linux/ -o libJNIVThread.so jni/pkg_MyRunnable.c

# tree
.
tqq jni
x   tqq pkg_MyRunnable.c
x   mqq pkg_MyRunnable.h
tqq libJNIVThread.so
mqq pkg
    tqq MyRunnable.class
    tqq ThreadExecutor.class
    mqq ThreadExecutor.java
```

```shell: 実行結果
# java -version
java version "21.0.2" 2024-01-16 LTS
Java(TM) SE Runtime Environment (build 21.0.2+13-LTS-58)
Java HotSpot(TM) 64-Bit Server VM (build 21.0.2+13-LTS-58, mixed mode, sharing)

# java -Djava.library.path=. pkg/ThreadExecutor
pthread is Virtual ? : false
--> I am Thread. I am Virtual ? : false
====> JNI_VERSION = JNI_VERSION_21
====> 0x00150000
====> C meets : Java
====> IsVirtualThread ? : 0
vthread is Virthal ? : true
--> I am Thread. I am Virtual ? : true
====> JNI_VERSION = JNI_VERSION_21
====> 0x00150000
====> C meets : Java
====> IsVirtualThread ? : 1
```

なるほど。