简体   繁体   English

如何从 java 代理停止/停止主程序/线程

[英]How to stop/halt the main program/thread from a java agent

I have a gradle test task which runs a list of tests from a given file.我有一个 gradle 测试任务,它运行来自给定文件的测试列表。 Sometimes, any particular test execution simply gets stuck and does not move on to execute the next test(s) in the list.有时,任何特定的测试执行都会卡住,并且不会继续执行列表中的下一个测试。

For this, I am trying to add a java agent which will detect timeouts in each test execution and calls System.exit() in this case.为此,我尝试添加一个 java 代理,它将检测每次测试执行中的超时并在这种情况下调用 System.exit()。 (I know calling System.exit() seems to be a rash decision, but throwing exception does not seem to stop the test execution) The java agent uses byte-buddy advices for doing this. (我知道调用 System.exit() 似乎是一个轻率的决定,但抛出异常似乎不会停止测试执行) java 代理使用字节伙伴建议来执行此操作。

public class TimerAdvice {
    public static CountDownLatch latch;

    @Advice.OnMethodEnter
    static long enter(@Advice.This Object thisObject,
                      @Advice.Origin String origin,
                      @Advice.Origin("#t #m") String detaildOrigin) throws InterruptedException {
        System.out.println("Timer Advice Enter thread: " + Thread.currentThread().getName() + " time: " + Instant.now().toString());

        latch = new CountDownLatch(1);

        ThreadFactory factory = new MyThreadFactory(new MyExceptionHandler());
        ExecutorService threadPool = Executors.newFixedThreadPool(1, factory);
        threadPool.execute(new TestCallable());

        return System.nanoTime();
    }

    @Advice.OnMethodExit (onThrowable = Throwable.class)
    static void onExit(@Advice.Origin Method method) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        System.out.println("Timer Advice Exit thread: " + Thread.currentThread().getName() + " time: " + Instant.now().toString());
        System.out.println("Counting down");
        latch.countDown();
    }
}

Basically this will spawn a background thread that will wait until the latch is counted down.基本上,这将产生一个后台线程,该线程将等到闩锁倒计时。

public class TestCallable implements Runnable {
    @Override
    public void run()  {
        try {
            latch.await(10, TimeUnit.MINUTES);
        } catch (InterruptedException e) {
            e.printStackTrace();
            throw new IllegalStateException(e.getMessage());
        }
        if(latch.getCount() > 0) {
            System.err.println("Callable thread"
                    + Thread.currentThread().getName() +
                    "TIMEOUT OCCURED!!!!");
            System.exit(1);
        }
    }
}

The latch countDown() method will be called by the method that handles the OnExit advice.处理 OnExit 通知的方法将调用闩锁 countDown() 方法。 Until then, the thread will wait for the specified timeout.在那之前,线程将等待指定的超时时间。

My question is, Why is the System.exit() call not affecting the test execution/jvm When this thread calls the System.exit(), the test thread still continues to execute as if nothing had happened.我的问题是,为什么 System.exit() 调用不影响测试执行/jvm 当这个线程调用 System.exit() 时,测试线程仍然继续执行,就好像什么都没发生一样。 I would like to stop the execution of the test at this point.我想在这一点上停止执行测试。

Any suggestions on how should I stop the entire test execution process when the timeout is detected?关于在检测到超时时我应该如何停止整个测试执行过程的任何建议?

The OP said that my comment concerning security manager helped him find the root cause, so I am converting it into an answer: OP 说我关于安全经理的评论帮助他找到了根本原因,所以我将其转换为答案:

As is documented, System.exit() will not shut down the JVM if there is a security manager stopping it from doing so.如文件所述,如果有安全管理器阻止 JVM,则System.exit()不会关闭它。 In that case you should see a SecurityException , though.不过,在这种情况下,您应该会看到SecurityException

A discussion in Gradle issue #11195 mentions a problem that Kafka sporadically exits unexpectedly and suggests a security manager policy for Spring-Kafka stopping it from doing so. Gradle issue #11195中的讨论提到了 Kafka 偶尔意外退出的问题,并建议 Spring-Kafka 的安全管理器策略阻止它这样做。 This was committed to Spring-Kafka, but - if I understand correctly - not to Gradle.这是致力于 Spring-Kafka,但 - 如果我理解正确 - 不是 Gradle。


Another edge case is shutdown hooks: The thread invoking System.exit() blocks until the JVM terminates.另一个极端情况是关闭钩子:调用System.exit()的线程阻塞,直到 JVM 终止。 If a shutdown hook submits a task to this thread, it leads to a deadlock.如果关闭钩子向该线程提交任务,则会导致死锁。

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

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