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

问题描述 投票:0回答:6

当使用 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 日志来确定引入此问题的提交。在 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 中的断言失败?

java gradle jvm
6个回答
8
投票

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

这意味着您的 JVM 有一个实现

java.lang.instrument.ClassFileTransformer
的代理,并且方法
transform(java.lang.Module, java.lang.ClassLoader, java.lang.String, java.lang.Class<?>, java.security.ProtectionDomain, byte[])
抛出了异常。

就我而言,我同时拥有 BlockHound 和 ByteBuddy(由 BlockHound 加载)。我的代码中的

StackOverflowError
触发了新类的加载,然后两个代理也抛出了
StackOverflowError
并且没有捕获它。我为 ByteBuddy 创建了一个问题,但我开始认为只有 JDK 中的错误报告需要更改。 由于异常的来源是 Java 代码,因此您可以附加调试器并在抛出的情况下设置断点 StackOverflowError

。您很可能首先在代码中或 Jackson 中找到

StackOverflowError

,您应该修复/报告该问题。

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

3
投票
下面是一些 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

编辑:
我相信这是上面 Scala 代码的 java 等价物:

List<RuntimeException> es = IntStream.iterate(0, i -> i + 1) .mapToObj(i -> new RuntimeException("" + i)) .limit(1024 * 1024) .toList(); List<RuntimeException> zipped = com.google.common.collect.Streams.zip(es.stream(), es.subList(1, es.size()).stream(), (e1, e2) -> { e1.initCause(e2); return e1; }) .toList(); throw es.get(0);

当我进行递归调用时(在不知情的情况下),我得到了这个,此外,这个调用有一个 try/catch,我在其中捕获了 Throwable(最高可能的异常类型)。我的解释是,我的捕获捕获了 StackOverflowException(并进一步研究了这一点),这使得整个事情变得疯狂!当我在 IntelliJ 调试器中运行它时,我无法真正停止线程 - 不知何故,新线程正在创建。一旦我删除了递归调用,一切都很好。

1
投票

我使用spring验证循环依赖的时候也会出现这个问题。我的代码应该是JVM中报错的。检查你的代码。一定有死循环。

1
投票

我在创建 Spring boot API 时遇到此错误。这个异常的原因似乎是Filter递归调用。

0
投票
我添加了一个过滤器,在某些情况下它会重定向到某个页面。

if(request.getServletPath().startWith("/....") { response.sendRedirect(redirectUrl); }

我忘了在
sendRedirect
之后添加return。我认为当我在调试模式下运行程序时会创建无限线程。 只需在重定向后添加一个

return

 语句,您就可以开始了。

我也遇到了这个问题,解决办法是控制器上方Swagger Annotation的@ApiOperation响应描述错误...

0
投票
该类与控制器返回的ResponseEntity不同:

@ApiOperation(value = "An api description", response = **Entity.class**)


© www.soinside.com 2019 - 2024. All rights reserved.