これは、 JVMTIエージェントで実現できます。
アイデアは、ネイティブ メソッドをインターセプトしThread.start0()
、呼び出されるたびに例外をスローすることです。
C++ で記述されたサンプル エージェントを次に示します。
#include <jvmti.h>
// Original native implementation of Thread.start0(), if you wish to call it
extern "C" void JNICALL JVM_StartThread(JNIEnv* env, jthread thread);
void JNICALL StartThreadHook(JNIEnv* env, jthread thread) {
env->ThrowNew(env->FindClass("java/lang/Error"), "Threads forbidden");
}
void JNICALL VMInit(jvmtiEnv* jvmti, JNIEnv* env, jthread thread) {
// After VM is initialized, intercept Thread.start0() with our hook function
jclass thread_class = env->FindClass("java/lang/Thread");
JNINativeMethod start0 = {(char*)"start0", (char*)"()V", (void*)StartThreadHook};
env->RegisterNatives(thread_class, &start0, 1);
}
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* vm, char* options, void* reserved) {
jvmtiEnv* jvmti;
vm->GetEnv((void**)&jvmti, JVMTI_VERSION_1_0);
jvmtiEventCallbacks callbacks = {0};
callbacks.VMInit = VMInit;
jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks));
jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, NULL);
return 0;
}
エージェントをコンパイルします。
g++ -fPIC -shared -olibnothreads.so -Wl,-soname,libnothreads.so nothreads.cpp
エージェントを使用してアプリケーションを実行します。
java -agentpath:/path/to/libnothreads.so -jar app.jar
JVMTI を使用して、新しいスレッドの開始をいつ許可し、いつ拒否するかというカスタム ロジックを実装することもできます。たとえば、ThreadStartおよびThreadEndイベントは、作成されたスレッドをカウントするのに役立ちます。GetStackTrace関数は、スレッドを作成しようとしているクラスを見つけるのに役立ちます。