简体   繁体   English

杀死Java线程进行测试

[英]Kill Java Thread for testing purposes

I'm currently testing a transaction system with ACID semantics implemented in Java. 我目前正在测试具有Java实现的ACID语义的事务处理系统。 The system has callback handlers that allow to perform arbitrary debug actions during a transaction, eg to throw an exception that simulates an error. 系统具有允许在事务期间执行任意调试操作的回调处理程序,例如,引发模拟错误的异常。

However, in practice what can happen is the death of a thread (eg by OutOfMemoryError) or the death of the entire JVM (sigsev or OS process kill). 但是,实际上可能发生的情况是线程死亡(例如,由于OutOfMemoryError)或整个JVM死亡(sigsev或OS进程终止)。 I can see that it's impossible to simulate the unexpected shutdown of the JVM process in a JUnit test (because JUnit runs in the same JVM). 我可以看到,不可能在JUnit测试中模拟JVM进程的意外关闭(因为JUnit在同一JVM中运行)。 But what about killing a thread? 但是杀死线程呢? I know about Thread#stop() , but it's deprecated and moreover throws a ThreadDeathError in the thread. 我知道Thread#stop() ,但是它已被弃用,并且在线程中抛出ThreadDeathError What I would like to simulate is the instantaneous "death" of a thread that prevents even catch(Throwable t) clauses from firing. 我想模拟的是线程的瞬时“死亡”,该事件阻止甚至触发catch(Throwable t)子句。 Can this be done in Java, without killing the JUnit test runner alongside it? 可以用Java做到这一点,而又不会杀死JUnit测试运行程序吗?

Again, this is not for production use , it's strictly testing only. 同样,这不是用于生产 ,仅用于严格测试。

the instantaneous "death" of a thread that prevents even catch(Throwable t) clauses from firing. 线程的瞬时“死亡”,可防止甚至触发catch(Throwable t)子句。 Can this be done in Java? 可以用Java完成吗?

No. It's impossible. 不,这是不可能的。

JVM uses OS threads and thus relies on the underlying OS scheduler. JVM使用OS线程,因此依赖于底层OS调度程序。 So in JVM level, JVM can't preempt a java thread. 因此,在JVM级别,JVM不能抢占Java线程。 A java thread must volunteer to be suspended. Java线程必须自愿挂起。 (It's common case, but still platform- and JVM-specific) (这是很常见的情况,但仍特定于平台和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());
}

In the above code, stop() worked. 在上面的代码中, stop()有效。 But you might wonder why an infinite loop without wait()/sleep() looks like "doesn't volunteer to be suspended"? 但是您可能想知道为什么没有wait()/sleep()的无限循环看起来像“不是自愿被暂停”吗?

stop() raise an asynchronous exception in t1 . stop()t1引发一个asynchronous exception t1 thread can detect the async exception by polling. t1线程可以通过轮询来检测异步异常。

From Java Virtual Machine Specification : Java虚拟机规范

The stop methods may be invoked by one thread to affect another thread or all the threads in a specified thread group. 一个线程可以调用stop方法以影响另一个线程或指定线程组中的所有线程。 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. 一个简单的实现可以在每条控制转移指令的位置轮询异步异常。

Which means, in the compiled code, at the end of the while-loop before jump , there's an instruction to poll the exception. 这意味着,在已编译的代码中,在jump之前的while循环结束时,有一条查询该异常的指令。 If the exception exists, the t1 thread jump to exception handler and stop by it self. 如果存在异常,则t1线程跳转到异常处理程序并自行停止。

So if I make the thread ignore all exceptions, and if the thread doesn't stop by it self, it's impossible to kill a java thread. 因此,如果我让线程忽略所有异常,并且如果线程自身无法停止运行,则无法杀死Java线程。

Here's an example where stop() doesn't work: 这是一个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());
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM