*** java.lang.instrument ASSERTION FAILED 的含义/原因是什么:“!errorOutstanding”,消息转换方法调用失败?

2022-09-01 06:15:40

当使用gradle运行我的测试时,我开始在控制台上获得下面的输出。此输出来自 JVM 而不是我的代码。Kotlin DSL 用于配置我的 gradle 构建。

*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at  line: 873
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at  line: 873
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at  line: 873
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at  line: 873

这发生在Java 11上

java --version
openjdk 11.0.6 2020-01-14
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.6+10)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.6+10, mixed mode)

这个输出不是来自我的代码,它似乎来自JVM。没有列出以前版本的Java的文件名似乎有与此相关的错误 https://bugs.openjdk.java.net/browse/JDK-8061621

JPLISAgent.c 第 873 行可能是生成消息的原因。

更新:

我遍历了所有 CI 日志,以确定导致此问题的提交。在基于Jackson的Json格式化程序实用程序的单元测试中将其跟踪到此代码。

    // try with a circular dependencies
    Node a = new Node("a");
    Node b = new Node("b");
    a.setChild(b);
    b.setParent(a);

    assertThatExceptionOfType(JsonUtilsException.class).isThrownBy(() -> JsonUtils.toJson(a));

特别是循环依赖关系会触发 JVM 输出。我猜Jackson真的被循环依赖关系绊倒了,但我不明白为什么这会导致JVM断言错误。

问题: - 此警告/错误的含义是什么?- 此错误的典型原因是什么,JVM中的断言失败?


答案 1

该消息确实来自JPLISAgent.c:873

这意味着您的 JVM 有一个实现的代理,并且方法引发了一个异常。java.lang.instrument.ClassFileTransformertransform(java.lang.Module, java.lang.ClassLoader, java.lang.String, java.lang.Class<?>, java.security.ProtectionDomain, byte[])

在我的情况下,我同时拥有BlockHound和ByteBuddy(由BlockHound加载)。在我的代码中,A 触发了新类的加载,然后两个代理也都抛出并且没有捕获它。我为ByteBuddy创建了一个问题,但我开始认为只有JDK中的错误报告需要改变。StackOverflowErrorStackOverflowError

由于异常的来源是在 Java 代码中,因此您可以附加调试器并在抛出时设置断点。您很可能首先在代码或Jackson中找到一个,您应该修复/报告它。StackOverflowErrorStackOverflowError


答案 2

您的测试正在生成一个非常大的异常原因链。

下面是一些 Scala 代码,它生成一个非常长的异常原因链,然后抛出它:

val iter = Iterator.from(0).map(_.toString).map(new Exception(_))
val es = iter.take(1024 * 1024).toSeq
for {
  (e0, e1) <- es.zip(es.tail)
} {
  e0.initCause(e1)
}
//es.last.initCause(es.head) //uncomment this line for extra fun
throw es.head

这会产生相同的

*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at JPLISAgent.c line: 844

推荐