Java19でプレビュー、Java21で正式リリースとなった Virtual Thread(仮想スレッド)を使ってみた。続編。
JNIに追加された関数を使ってみた。
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());
}
}
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
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言語側の関数定義を作る
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);
}
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
実行結果
# 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
なるほど。