我有一些代码可以从目录中的多个 JAR 动态加载类。因为 JAR 中的代码是不受信任的,所以我希望通过“沙箱化”它们来保护主应用程序免受编码不良或恶意动态类的影响。我正在尝试做的一件事是“timebox”不受信任的代码的执行,如果它花费的时间太长,则将其杀死(例如,因为它陷入了无限循环)。我正在尝试使用 Callable 和 Future 来实现这一点,不是因为我想并行运行任务(我不这样做),而是为了利用已完成的工作来提供返回值、捕获异常并取消正在运行的任务。但是,当我在一些测试代码上运行它时,我发现调用 Future.cancel(true) 似乎并没有取消任务。
我在 StackOverflow 上看到了几个关于为什么会发生这种情况的问题(例如这个),答案总是一样的:cancel(true) 通过在运行 Callable 的线程上调用 interrupt() 来工作,这需要取消取消生效之前的可中断()操作(例如 Thread.sleep())上的任务块。因为我不控制正在执行的代码,所以不能保证它会这样做,所以我不能确定我已经取消了它。
有什么方法可以让我运行动态加载的代码,然后在进行中杀死它并确保它死掉,即使它从不阻塞中断()可操作的操作?
// 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
}