我到处都在寻找如何强制停止Java中的线程的方法,我看到“相反,只是检查出口变量,如果您需要强制终止,则程序会损坏。”
我有一个非常独特的情况。我正在编写一个Java程序,该程序可以在单独的线程中动态加载和运行其他Java类。 (请不要对安全风险发表任何评论,这是一个非常特定的用例。)
问题在于,由于其他人已经编写了需要加载的类,因此无法保证他们将实现停止检查以及无法正确执行的检查。我需要一种方法来立即终止其线程,接受所有涉及的风险。基本上,如果需要,我想kill -9
他们的线程。如何用Java做到这一点?
更新:这里有更多信息:
这实际上是一个Android应用程序
用户代码取决于我的应用程序中的类
用户类必须用@UserProgram
注释,以便被我的应用“注册”
用户还可以选择将其类直接构建到应用程序中(通过下载已将内部类编译到库中的项目并将其类放在单独的模块中),而不是从其动态加载它们一个JAR。
用户类是从我的模板类扩展的,该模板类具有一个被其覆盖的runUserProgram()
方法。在这种方法内,他们可以自由地做任何他们想做的事情。他们可以检查isStopRequested()
看看我是否要他们停止,但是我不能保证他们会这样做。
在启动时,我的应用程序会加载指定的所有JAR,并扫描该应用程序中的所有类以及这些JAR中的类,以查找带有上述注释的所有类。一旦构建了这些类的列表,它就会被馈送到前端,UI会在其中提供可以运行的程序列表。选择程序后,必须按下“开始”按钮才能真正启动它。按下该按钮后,该按钮将变为“停止”按钮,并向后端触发回调,以在新线程中加载选定的类并调用runUserProgram()
方法。当按下“停止”按钮时,将设置一个变量,该变量使isStopRequested()
返回true
。
答案 0 :(得分:4)
您可以通过在其自己的进程中运行来kill -9
,即以ProcessBuilder
开头并调用Process.destroyForcibly()
将其杀死。
ProcessBuilder pb = new ProcessBuilder("java", "-cp", "myjar.jar");
pb.redirectErrorStream();
Process process = pb.start();
// do something with the program.
Scanner sc = new Scanner(process.getOutputStream());
while (sc.hasNextLine()) {
System.out.println(sc.nextLine());
}
// when done, possibly in another thread so it doesn't get blocked by reading.
process.waitFor(1, TimeUnit.SECONDS);
if (process.isAlive())
process.destroyForcibly();
Java 8具有Thread.stop()。问题是,它只能在非常有限的用例中合理地工作,因此在有限的情况下,最好使用中断,并且如果代码不受信任,那么两者都不会有好处。
答案 1 :(得分:2)
有已弃用的Thread.stop()
,但请勿使用。
没有其他线程的配合就无法干净地终止它。
线程可以处于分配一些内存或将某些对象添加到某个全局状态,锁定某些互斥锁等的状态。如果在错误的时间将其杀死,则可能会泄漏内存甚至导致死锁。
答案 2 :(得分:2)
有可能通过JNI,在Windows下可以调用一个TerminateThread API,(希望)在Android下可能也有类似的事情。问题在于获取线程的本机句柄,您可能需要在首次加载用户“程序”时获得该信息,这可能是作为初始化过程的一部分,从有问题的线程中调用另一个JNI方法,并从中获取当前线程的句柄。那。
我自己还没有尝试过,最好的情况是该“工作”并杀死了线程,但这将导致该线程泄漏资源。最糟糕的情况是,它将在内部使JVM处于不一致状态,这可能会使整个应用程序崩溃。
我真的认为这是一个坏主意。
如果要允许这样做,更好的设计是在另一个进程中运行用户代码,并通过套接字或管道与之通信。这样,您可以在必要时相对安全地终止其他过程。这是更多的工作,但从长远来看,它将变得更好。
答案 3 :(得分:-4)