2016-08-22 7 views
1

現在、Javaで実装されたACIDセマンティクスを使用してトランザクションシステムをテストしています。システムは、トランザクション中に任意のデバッグ動作を実行することを可能にするコールバックハンドラを有する。エラーをシミュレートする例外をスローします。テストの目的でJavaスレッドを終了する

しかし実際には、スレッドの破棄(たとえばOutOfMemoryErrorによる)またはJVM全体の破棄(sigsevまたはOSプロセスの強制終了)が実際に起こります。 JUnitテストでJVMプロセスの予期しないシャットダウンをシミュレートすることは不可能であることがわかります(JUnitは同じJVMで実行されるため)。しかし、スレッドを殺すことはどうですか?私はThread#stop()について知っていますが、廃止予定であり、さらにスレッド内にThreadDeathErrorがスローされています。私がシミュレートしたいのは、catch(Throwable t)句の発火を防ぐスレッドの瞬間的な「死」です。これはJUnitテストランナーと並行してJavaで実行できますか?

この場合も、これはであり、実稼働用ではありません、厳密にテストしています。

+1

方法について明示的にスレッドで 'OutOfMemoryError'を投げますか? –

+0

"手動で"スローされた "OutOfMemoryError"が実際のOoMEとJVMで実際に同じ効果を持っているかどうかは分かりません。 OoMEに達するまでメモリを割り当てることが考えられるが、JUnitテスト環境も同様に破損する可能性があると主張できる。 – Alan47

+0

または、非常に大きなファイルをロードしようとする。 OOMは再現が非常に簡単です。 – kosa

答えて

2

スレッドの瞬間的な「死」によって、(Throwable t)句が鳴らなくなることがあります。これはJavaでできますか?

いいえ不可能です。

JVMはOSスレッドを使用するため、基盤となるOSスケジューラに依存します。したがって、JVMレベルでは、JVMはJavaスレッドをプリエンプトできません。 Javaスレッドはボランティアで中断する必要があります。 (これは、一般的なケースだが、それでも、プラットフォームやJVM固有)

public static void main(String[] args) throws InterruptedException { 
    Thread t1 = new Thread(new Runnable() { 
    @Override 
    public void run() { 
     while (true) { 
     int i = 0; 
     i++; 
     } 
    } 
    }); 
    t1.start(); 
    Thread.sleep(1000); 
    t1.stop(); 
    Thread.sleep(1000); 
    System.out.println(t1.isAlive()); 
} 

上記のコードでは、stop()が働いていた。しかし、あなたはwait()/sleep()なしで無限ループがどのように見える理由を「一時停止するボランティアしません」不思議に思うかもしれません?

stop()t1asynchronous exceptionを上げるt1スレッドがポーリングにより非同期例外を検出することができ

Java Virtual Machine Specificationから:。。

stopメソッドは、特定のスレッドグループ内の別のスレッドまたはすべてのスレッドに影響を与えるために、あるスレッドによって呼び出される場合があります。これらのスレッドは、他のスレッドまたはスレッドの実行中の任意の時点で発生する可能性があるため、非同期です。内部エラーは非同期と見なされます

簡単な実装では、各制御転送命令のポイントで非同期例外をポーリングする可能性があります。

つまり、コンパイルされたコードでは、whileループの最後にjumpの前に、例外をポーリングするという指示があります。例外が存在する場合、t1スレッドは例外ハンドラにジャンプし、それ自身で停止します。

スレッドがすべての例外を無視するようにし、スレッドが自己停止しない場合は、Javaスレッドを強制終了することはできません。ここで

stop()が動作しない例です:

public static void main(String [] args) throws InterruptedException { 
    Thread t1 = new Thread(new Runnable() { 
    @Override 
    public void run() { 
     while (true) { 
     try { 
      while (true) { 
      int i = 0; 
      i++; 
      } 
     } catch (Throwable e) { 
      e.printStackTrace(); 
     } 
     } 
    } 
    }); 
    t1.start(); 
    Thread.sleep(1000); 
    t1.stop(); 
    Thread.sleep(1000); 
    System.out.println(t1.isAlive()); 
} 
+1

説明をありがとう。私は答えが "いいえ、それは不可能です"と恐れていましたが、JVMについてのいくつかの新しいことを学びました。 – Alan47

関連する問題