ディレクトリ内の複数のJARからクラスを動的にロードするコードがいくつかあります。JAR内のコードは信頼できないため、メインアプリケーションを「サンドボックス化」することで、コーディングが不十分な動的クラスや悪意のある動的クラスからメインアプリケーションを保護したいと思います。私がやろうとしていることの1つは、信頼できないコードの実行を「タイムボックス化」し、時間がかかりすぎる場合はコードを強制終了することです(たとえば、無限ループでスタックしているため)。CallableとFutureを使用してこれを実装しようとしています。これは、タスクを並行して実行するためではなく(実行しない)、戻り値を提供し、例外をキャプチャし、実行中のタスクをキャンセルするために行われた作業を利用するためです。ただし、いくつかのテストコードで実行すると、Future.cancel(true)を呼び出してもタスクがキャンセルされないようです。
StackOverflowでこれが発生する理由についていくつかの質問(これなど)を見てきましたが、答えは常に同じです。cancel(true)は、Callableを実行しているスレッドでinterrupt()を呼び出すことで機能します。これには、キャンセルが必要です。キャンセルが有効になる前のinterrupt()ible操作(Thread.sleep()など)のタスクブロック。私は実行中のコードを制御していないので、それが実行される保証はありません。したがって、キャンセルしたかどうかはわかりません。
動的にロードされたコードを実行し、後で進行中のコードを強制終了して、interrupt()ible操作でブロックされない場合でも確実に停止する方法はありますか?
// Assume: ExecutorService pool, Callable<T> task,
// long timeout, TimeUnit timeUnit
Future<T> future = pool.submit(task);
T result;
try {
result = future.get(timeout, timeUnit);
// do something with result
} catch (TimeoutException ex) {
future.cancel(true);
// handle timeout
} catch (ExecutionException ex) {
// handle exeception thrown by task
} catch (InterruptedException ex) {
// handle InterruptedException
}