我目前正在测试一个用 Java 实现的具有 ACID 语义的事务系统。系统具有回调处理程序,允许在事务期间执行任意调试操作,例如抛出模拟错误的异常。
然而,实际上可能发生的是线程死亡(例如,由于 OutOfMemoryError)或整个 JVM 死亡(sigsev 或操作系统进程终止)。我可以看到,在 JUnit 测试中模拟 JVM 进程的意外关闭是不可能的(因为 JUnit 运行在同一个 JVM 中)。但是杀死一个线程呢?我知道 Thread#stop() ,但它已被弃用,而且会在线程中引发 ThreadDeathError 。我想模拟的是线程的瞬时“死亡”,它甚至阻止了 catch(Throwable t) 子句的触发。这可以在 Java 中完成,而不杀死 JUnit 测试运行程序吗?
再次强调,这不用于生产用途,它仅用于严格测试。
最佳答案
the instantaneous "death" of a thread that prevents even catch(Throwable t) clauses from firing. Can this be done in Java?
没有。这是不可能的。
JVM 使用操作系统线程,因此依赖于底层操作系统调度程序。所以在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()
在 t1
中引发异步异常
。 t1
线程可以通过轮询的方式检测异步异常。
来自Java Virtual Machine Specification :
The stop methods may be invoked by one thread to affect another thread or all the threads in a specified thread group. They are asynchronous because they may occur at any point in the execution of the other thread or threads. An internal error is considered asynchronous
A simple implementation might poll for asynchronous exceptions at the point of each control transfer instruction.
这意味着,在编译后的代码中,在 jump
之前的 while 循环末尾,有一条指令来轮询异常。如果异常存在,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());
}
关于java - 出于测试目的终止 Java 线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39083394/