2

研究プロジェクトでは、単体テスト (JUnit で記述) が異なるコンテキストで実行されたときに異なる動作をするかどうかを調べようとしています。このために、私は 2 つのことを行います。最初に、カスタム JUnit ランナーを使用してプログラムのテスト スイート全体を実行し、次に同じカスタム JUnit ランナーを使用して単一のテストを実行します (これが理にかなっている理由は重要ではありません。今)。テストが失敗すると、JUnit によって報告される例外スタック トレース全体を記録し、2 つの実行間のスタック トレースを比較します。

これを行っていると、説明できない奇妙なことにつまずきました。以下は、そのように記録された 2 つのスタック トレースからの 2 つの抜粋です。

テスト スイート全体を実行したときに記録されたスタック トレース:

org.fest.swing.edt.GuiActionRunner.resultOf(GuiActionRunner.java:126)
org.fest.swing.edt.GuiActionRunner.execute(GuiActionRunner.java:73)
net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent.AbstractNumericDataTypeUITest.constructTestFrameInEDT(AbstractNumericDataTypeUITest.java:98)
net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent.AbstractNumericDataTypeUITest.setUp(AbstractNumericDataTypeUITest.java:81)
sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source) - sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:616)
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)

単一のテストを実行したときに記録されたスタック トレース:

org.fest.swing.edt.GuiActionRunner.resultOf(GuiActionRunner.java:126)
org.fest.swing.edt.GuiActionRunner.execute(GuiActionRunner.java:73)
net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent.AbstractNumericDataTypeUITest.constructTestFrameInEDT(AbstractNumericDataTypeUITest.java:98)
net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent.AbstractNumericDataTypeUITest.setUp(AbstractNumericDataTypeUITest.java:81)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:616)
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)

両方のスタック トレースは、最後の共通ステートメントから始まる、クラッシュ前の最後のいくつかのエントリを示しています。明らかに、JDK/VM のリフレクション実装内のどこかで、これら 2 つのケースの間で動作が異なります。

私の質問はなぜですか?

これは、以前のリフレクション呼び出しなどからの VM キャッシングと関係があると推測していますが、実際にはわかりません。単一のテストを実行するたびにこれが発生するかどうか(したがって、無視できるかどうか)、または実行中の特定のテストと関係があるかどうかを判断する必要があるため、これを知ることは重要です。

これがかなり曖昧であることは承知していますが、どんな助けでも大歓迎です。

4

1 に答える 1

3

これは、Sun/Oracle JVM (その他はわかりません) がリフレクション呼び出しを最適化するためです。1.4 以降の JVM は、呼び出されたメソッドへのリフレクション呼び出しをブリッジするバイトコードを生成します。コンパイル時にすべてのことがわかっているわけではないため、実行時に行う必要があります。

クラスMethodAccessorGeneratorは、GeneratedMethodAccessor1

NativeMethodAccessorImpl のコメントから見つけたヒント:

Used only for the first few invocations of a Method; afterward, switches to bytecode-based implementation

1 つの Java VM のライフサイクルでスイートと単一のテストを実行していますか?

于 2012-08-20T23:02:32.783 に答える