2

私のC++コードで定義された、Java内で呼び出されるネイティブ関数があります(JavaコードがC ++によって呼び出された後)。

(1)C ++でのネイティブ関数の宣言/定義:

// C++ declaration/definition of the native function:

JNIEXPORT void JNICALL setEncoderProgressStatus (JNIEnv * env, jobject theClass, jlong jEncoderDecoderDlg, jstring status)
{
    // Do nothing.  Obviously, the real function does something.
    // But an access violation is reported even in the do-nothing case.
}

(2)C++でのネイティブ関数の登録

// Registration of this function with JNI in the C++ code

JNINativeMethod commandLineEncoderMethods[] =
{
    {"setEncoderProgressStatus","(JLjava/lang/String;)V", (void*)setEncoderProgressStatus}
};

// pEnv is a valid JNIEnv *
// jCommandLineEncoderClass has already been initialized
pEnv->RegisterNatives(jCommandLineEncoderClass, commandLineEncoderMethods, sizeof(commandLineEncoderMethods)/sizeof(JNINativeMethod))

(3)Javaでのネイティブ関数の宣言:

// The Java code, in turn, declares the native function as follows:

public static native void setEncoderProgressStatus(long EncoderDecoderDlg, String status);

(4)Javaコード内でネイティブ関数を呼び出す:

// Finally, the Java code calls the native function as follows:

// The real code passes different args,
// but an access violation is reported even in the do-nothing case.
// Commenting out the following line of code makes the access violation disappear.

setEncoderProgressStatus(0, "");

このコードは100%正常に機能し、長い間機能していることに注意してください。Visual Studio 2010のデバッガーで実行すると、アクセス違反が報告されることに気づきました。Javaのネイティブ関数への呼び出しをコメントアウトするだけで、アクセス違反がなくなります。

これがVS2010でデバッグモードでアプリケーションを実行しているときのJNIの既知の「問題」であり、コードに問題がないことを知っていれば、満足できます。

ただし、コードに問題がないことを確認したいと思います。

..。

*補遺*

アクセス違反によってプログラムの実行が停止することはありません。代わりに、アクセス違反の唯一の兆候は、出力ウィンドウの行です。これがアクセス違反が処理されたことを意味するかどうかはわかりません。しかし、それは処理されたことを意味すると思います。ただし、処理されたとしても、コードに問題があることを必ずしも示しているのかどうかを知りたいと思います。

出力ウィンドウのメッセージは次のとおりです。

EncoderDecoder.exeの0x03fbb256でのファーストチャンス例外:0xC0000005:アクセス違反の読み取り場所0x003d0100

..。

*第2補遺*

C ++アプリケーションがJVMに接続されたままで、C ++アプリケーションから同じコードを再度実行すると(同じJavaコードが呼び出され、Javaコードが同じJNI関数を呼び出すようになります)、アクセス違反は表示されません

(私の実際のプログラムでは、いくつかの異なるクラス内で呼び出されるいくつかの異なるネイティブ関数があるため、アクセス違反が報告されたときと報告されなくなったときを正確に分離するのは簡単ではありませんが、3回目の実行までに同じロードされたJVMを使用して、C ++アプリケーションを終了せずに同じ機能を使用すると、初回アクセス違反エラーは発生しません(また、プレーンアクセス違反エラーも発生しません)。

これは、以下のBen Voigtの回答(および関連するコメント)と併せて、JVMコードfirst-chance exception (access violation)NORMAL処理の一部として発生する原因であり、これは私のコードの問題ではないと私に信じさせます。

..。

*補遺3*

http://blogs.msdn.com/b/davidklinems/archive/2005/07/12/438061.aspxから:

ファーストチャンス例外メッセージは、ほとんどの場合、コードに問題があることを意味するものではありません。

アクセス違反である可能性が高い最初のチャンスの例外が実際の問題を表す可能性がまだあります。その場合、私の質問はまだ開いています。しかし-証拠は、これがJVMの動作方法であり、私のコードの問題を表していない可能性を示していると思います。

4

1 に答える 1

2

これは未処理のアクセス違反ですか、それとも続行すると(例外ハンドラーを実行させて)呼び出しが続行されますか?

JITコンパイラには、関数がJITされているかどうかを確認するための条件付きのコストをかけることなく、関数のネイティブコードを生成するためのさまざまなトリックがあります。そのような手法の1つは、アクセス違反を生成してJITコンパイラーをトリガーするため、最初の呼び出しがインターセプトされることです。コードが一度生成された後、それ以降の呼び出しは例外なく実行されます。

Java JITコンパイラが実際にそうするかどうかはよくわかりませんが、実行しているJITに関する具体的な情報を提供しないと、明確な答えを得ることができません。Sun / Oracle HotSpotコンパイラですか?x86またはx86_64または他のプラットフォーム?あなたは、実装によって異なる実装の詳細に深く関わっています。

于 2012-11-18T05:54:26.233 に答える