JVMTIの上で使用できる優れたJavaAPIはありますか?
6 に答える
JVMTIは、JavaAPIを最上位にするために構築されたものではありません。JVMTI定義自体は次のように述べています。
JVMツールインターフェイス(JVM TI)は、ネイティブライブラリがイベントをキャプチャしてJavaプラットフォームのJava仮想マシン(JVM)を制御できるようにする標準のネイティブAPIです。
イベントとコントロールをキャプチャするためのネイティブAPI用に構築されているため、その上にAPIはないと思います。あなたが達成しようとしていることを説明できますか?
JVMTIに加えてJavaAPIを認識していません。
わかりました...試してみました...期待どおりに機能しているようです...実際には、VMInitコールバックは、CJVMTIインターフェイスをミラーリングしたインターフェイスを実装したクラスのインスタンスを返します...Cエージェントはこのインスタンスを保存し、必要に応じてイベントで呼び出します。さらに、VMInit Javaが返される前に、機能とコールバックを設定し、イベントなどを登録します。おそらく、約90%のJVMTIAPIカバレッジを取得できます。 ...それはそれをタイプするだけの場合です....あなたが強いケースを持っているなら私は週末にそれをすることができます:-)
次のコードはこれを生成します:
C:VMInit、Javaメソッド
Javaをコールバックする準備をしています:JVMTIコールバッククラス、VMInit()。
C:VMInit、コールバックJavaメソッドが正常に返されました
Java:そして最後に...こんにちは、私はJavaメインです
package com.stackoverflow;
public class JVMTICallback {
public static void VMInit() {
System.out.println("Java:\tJVMTI callback class, VMInit().");
}
public static void main(String[] args) {
// This main is only here to give us something to run for the test
System.out.println("Java:\tAnd Finally... Hello, I'm the Java main");
}
}
とC
#include <stdlib.h>
#include "jvmti.h"
jvmtiEnv *globalJVMTIInterface;
void JNICALL
vmInit(jvmtiEnv * jvmti_env, JNIEnv * jni_env, jthread thread)
{
printf("C:\tVMInit, preparing to callback Java method\n");
char *className = "com/stackoverflow/JVMTICallback";
char *methodName = "VMInit";
char *descriptor = "()V";
jclass callbackClass = (*jni_env)->FindClass(jni_env, className);
if (!callbackClass) {
fprintf(stderr,"C:\tUnable to locate callback class.\n");
return;
}
jmethodID callbackMethodID = (*jni_env)->GetStaticMethodID(jni_env, callbackClass, methodName, descriptor);
if (!callbackMethodID)
{
fprintf(stderr, "C:\tUnable to locate callback VMInit method\n");
return;
}
(*jni_env)->CallStaticVoidMethodV(jni_env, callbackClass, callbackMethodID, NULL);
printf("C:\tVMInit, callback Java method returned successfully\n");
}
JNIEXPORT jint JNICALL
Agent_OnLoad(JavaVM * jvm, char *options, void *reserved)
{
jint returnCode = (*jvm)->GetEnv(jvm, (void **) &globalJVMTIInterface,
JVMTI_VERSION_1_0);
if (returnCode != JNI_OK)
{
fprintf(stderr,
"The version of JVMTI requested (1.0) is not supported by this JVM.\n");
return JVMTI_ERROR_UNSUPPORTED_VERSION;
}
jvmtiEventCallbacks *eventCallbacks;
eventCallbacks = calloc(1, sizeof(jvmtiEventCallbacks));
if (!eventCallbacks)
{
fprintf(stderr, "Unable to allocate memory\n");
return JVMTI_ERROR_OUT_OF_MEMORY;
}
eventCallbacks->VMInit = &vmInit;
returnCode = (*globalJVMTIInterface)->SetEventCallbacks(globalJVMTIInterface,
eventCallbacks, (jint) sizeof(*eventCallbacks));
if (returnCode != JNI_OK)
{
fprintf(stderr, "C:\tJVM does not have the required capabilities (%d)\n",
returnCode);
exit(-1);
}
returnCode = (*globalJVMTIInterface)->SetEventNotificationMode(
globalJVMTIInterface, JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, (jthread) NULL);
if (returnCode != JNI_OK)
{
fprintf(
stderr,
"C:\tJVM does not have the required capabilities, JVMTI_ENABLE, JVMTI_EVENT_VM_INIT (%d)\n",
returnCode);
exit(-1);
}
return JVMTI_ERROR_NONE;
}
周りを検索しましたが、残念ながら、JVMTIの上にJavaAPIライブラリが見つかりませんでした。運が悪いようです。
ただし、できることは、Javaコードからネイティブlibを呼び出すことです。私はC/C ++があまり得意ではありませんが、JVMTIのドキュメントから、提供されたヘッダーから小さな共有ライブラリを構築できることがわかりました。次に、JNA**を使用して呼び出すことができます。ネイティブライブラリの周りに素晴らしいAPIラッパーを提供します。
JNA入門ページで例を見てください
このページは、必要なすべてのJavaバインディングを生成できるJNAeratorにもリンクしています。
このアプローチの欠点は、ターゲットプラットフォーム用にこの薄いネイティブレイヤーを維持する必要があることです。
** JNAは、通常のJNIと比較して実行時のオーバーヘッドを処理しますが、開発の容易さがIMOのパフォーマンスの利点を上回ります。必要な場合にのみJNIに切り替えてください。
うまくいかないだろう。JVMTIには、Javaコードが直接制御できないコールバックがあります(ClassPrepareなど)。これらのコールバックがJavaで実装されている場合、実行によって他のコールバックが発生し、デッドロックが発生する可能性があります。
書くのは難しいことではありません....JVMTI呼び出しをサンクしてJNIを介してJavaクラスをコールバックするだけです..おそらくいくつかの問題に直面するでしょう...最初にAgent_onLoad..この最初の「登録」関数も発生しますJVMのライフサイクルの早い段階で、Javaをコールバックします。次に、潜在的な循環性の問題があり、JVMがこのようなことを期待して作成された可能性があります。
私は例を書いてみます....数分後に戻って...
JDIは、Javaで記述されたTOPレベルのインターフェースであり、バックエンドAPIとしてJVMTIを使用します。 このリンクはあなたに詳細な情報を提供します。