1

我有一些代码可以从目录中的多个 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
}
4

2 回答 2

3

取消,或者更确切地说是线程中断,机制基本上是协作的,你无法中断恶意任务。你唯一的选择,出于许多原因非常危险,就是对Thread.stop()他们来说。

于 2012-07-24T19:56:06.047 回答
1

Thread.stop在和旁边Thread.destroy,您可以使用Process p = Runtime.getRuntime().exec( cmd );. 这个过程真的可以被破坏Process.destroy if necessary.

要简化流程创建,请使用ProcessBuilder. 另外,查看可用的教程(这个是法语的)来执行流程,等到完成(使用waitFor),并管理流。

我已经看到它在我们需要将 ps 文档转换为 pdf 的产品中工作。我们正在转储 ps 文件,执行ps2pdf,然后读取输出文件。

优点/缺点Process

  • (+) 真正的沙盒进入一个单独的进程
  • (-) JVM之间的通信更难处理
  • (-) 使应用程序的部署复杂化(JVM 的路径、选项、当前目录等)

请注意,不鼓励使用Thread.stopand Thread.destroy(我不确定它是否已实际实现),因为它们在获取和释放锁方面是不安全的。确保您阅读了为什么不推荐使用 Thread.stop、Thread.suspend、Thread.resume 和 Runtime.runFinalizersOnExit?如果在单独的线程中运行的不受信任的模块不会弄乱应用程序的锁,只有在最坏的情况下使用自己的锁,那么Thread.stop可能仍然是最好的选择。

的优点/缺点Thread.stop

  • (+) 易于使用
  • (+) 受信任代码和不受信任代码之间的通信很容易
  • (-) 已弃用
  • (-) 在某些必须首先评估的非常具体的情况下可能不安全
于 2012-07-27T08:25:58.240 回答