JNI DelphiでのJVMの取得と接続

すべての人に良い一日を! 今日は、ロードされたJVMを取得して接続する方法の例を分析します。 JVM内でコードを実行するためにこれが必要です。

新しいDLLプロジェクトを作成します。 プロセス接続を追加します。

procedure DllMain(dwReason: LongWord); begin case dwReason of DLL_PROCESS_ATTACH: begin //************************** end; DLL_PROCESS_DETACH: begin //*************************** end; end; end; begin DllProc := @DllMain; DllProc(DLL_PROCESS_ATTACH); end. 

素晴らしい、追加しました。 次に、JNIコンポーネントをUsesに追加する必要があります。

 uses System.SysUtils, System.Classes, windows, JNI; 

ここで、検索を実装してJVMに接続しましょう。 これを行うには、変数をDllMainに追加します。

 var I: Integer; JVMArray: array of PJavaVM; NumberOfVMs: JSize; JNIEnv: PJNIEnv; GetCreatedJavaVMs: TJNI_GetCreatedJavaVMs; const BufferSize = 128; 

次に、 DLL_PROCESS_ATTACHで、ロードされたJVMの検索と接続DLL_PROCESS_ATTACH実装します

 begin try GetCreatedJavaVMs := GetProcAddress(GetModuleHandle('jvm.dll'), 'JNI_GetCreatedJavaVMs'); SetLength(JVMArray, BufferSize); GetCreatedJavaVMs(@JVMArray[0], BufferSize, @NumberOfVMs); except Exit; end; if NumberOfVMs > 0 then begin for I := 0 to NumberOfVMs - 1 do begin JVMArray[I]^.GetEnv(JVMArray[I], @JNIEnv, JNI_VERSION_1_8); JVMArray[I]^.AttachCurrentThread(JVMArray[I], @JNIEnv, Nil); end; end else begin Exit; end; 

ここで何が起こっていますか。 まず、jvm.dllからJNI_GetCreatedJavaVMs関数のアドレスを取得する必要があります。 次に、バッファーの長さを設定します。 次に、 GetCreatedJavaVMs関数を使用して、ロードされたすべてのJVMを取得します。 さて、ロードされたJVMが残るまでAttachCurrentThread.をバッファーにドロップするだけAttachCurrentThread.

そこで、ロードされたJVMを見つけて接続しました。 これで、 AttachCurrentThread行の後にJVM内の任意のコードを使用できます。 そして最後に、DLLコードを取得します。

 library Project1; uses System.SysUtils, System.Classes, windows, JNI; procedure DllMain(dwReason: LongWord); var I: Integer; JVMArray: array of PJavaVM; NumberOfVMs: JSize; JNIEnv: PJNIEnv; GetCreatedJavaVMs: TJNI_GetCreatedJavaVMs; const BufferSize = 256; begin case dwReason of DLL_PROCESS_ATTACH: begin try GetCreatedJavaVMs := GetProcAddress(GetModuleHandle('jvm.dll'), 'JNI_GetCreatedJavaVMs'); SetLength(JVMArray, BufferSize); GetCreatedJavaVMs(@JVMArray[0], BufferSize, @NumberOfVMs); except Exit; end; if NumberOfVMs > 0 then begin for I := 0 to NumberOfVMs - 1 do begin JVMArray[I]^.GetEnv(JVMArray[I], @JNIEnv, JNI_VERSION_1_8); JVMArray[I]^.AttachCurrentThread(JVMArray[I], @JNIEnv, Nil); end; end else begin Exit; end; end; DLL_PROCESS_DETACH: begin Exit; end; end; end; begin DllProc := @DllMain; DllProc(DLL_PROCESS_ATTACH); end. 

使い方の例を挙げましょう。 Javaで使用したい関数があるとします。

 procedure Com(JNIEnv: PJNIEnv); var JC: JClass; JM: JMethodID; Begin JC:=jnienv^.FindClass(JNIEnv, 'ru/er_log/components/Frame'); JM:=jnienv^.GetMethodID(jnienv, jc, 'login', 'Ljavax/swing/JTextField;'); jnienv^.CallObjectMethod(jnienv, jc, jm); End; 

これはJNIのMethodの単純な呼び出しであり、使用するには、このプロシージャをAttachCurrentThread後にAttachCurrentThreadます。

  begin JVMArray[I]^.GetEnv(JVMArray[I], @JNIEnv, JNI_VERSION_1_8); JVMArray[I]^.AttachCurrentThread(JVMArray[I], @JNIEnv, Nil); Com(JNIEnv); end; 

その結果、JVMへの接続とその中の特定のプロシージャの実行を取得します。

Source: https://habr.com/ru/post/J324594/


All Articles