instrumentation.retransformClasses() 抛出致命错误

Posted

技术标签:

【中文标题】instrumentation.retransformClasses() 抛出致命错误【英文标题】:instrumentation.retransformClasses() throwing fatal error 【发布时间】:2021-02-03 14:54:37 【问题描述】:

我正在尝试开发javaagent。它还提供对注释的支持。

preMain 方法中,我试图扫描类路径中的注释。然后使用instrumentatino.addTransformer()方法添加变压器。

因为在注解处理过程中已经加载了类,所以转换不会发生(如果我删除注解处理代码和重新转换代码见下文,一切正常)。

为了克服这个问题,我现在正在尝试重新转换类。所有与清单条目相关的必要设置以及在addTransformer 方法中启用canRetransform 标志都已完成。

我的代码大致是这样的:

annotationProcessor.processAnnotation();
instrumentation.addTransformer(new DummyTransformer(), true);
try 
  instrumentation.retransformClasses(instrumentation.getAllLoadedClasses());
 catch (UnmodifiableClassException e) 
  e.printStackTrace();

DummyTransformer 不执行任何操作。它只是按原样返回 classBytes(我也尝试在每次调用时返回 null)

这里发生的是我收到此错误

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x000000010c5254dd, pid=5912, tid=0x0000000000001603
#
# JRE version: OpenJDK Runtime Environment (8.0_282) (build 1.8.0_282-bre_2021_01_20_16_06-b00)
# Java VM: OpenJDK 64-Bit Server VM (25.282-b00 mixed mode bsd-amd64 compressed oops)
# Problematic frame:
# V  [libjvm.dylib+0x5254dd]  Symbol::as_C_string() const+0xd
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /some/obfuscated/path/hs_err_pid5912.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
#
zsh: abort      java  -cp build/libs/jvm-agent-0.1-all.jar 

最初我认为转换器行为不端,但当我尝试使用DummyTransformer 时,返回null 或相同的bytes 会产生类似的结果。

【问题讨论】:

我认为这个问题不复制就无法解决。您的代码 sn-p 连同肤浅的解释是有帮助的,但还不够。我想知道“注释处理器”的作用,甚至在转换之前。我还希望看到代码的其余部分,尤其是转换器,从您的角度来看可能是微不足道的。所以请提供MCVE,最好是在 GitHub 上。谢谢。 顺便说一句,我在您的日志中看到 java -cp build/libs/jvm-agent-0.1-all.jar 作为命令行。似乎没有-javaagent: 参数。您是否正在热连接代理?如果是这样,我也想看看你是怎么做的。 @kriegaex 这里是命令行 java -javaagent:build/libs/jvm-agent-0.1-all.jar -cp build/libs/jvm-agent-0.1-all.jar some.package .name.HelloWorldApplication 【参考方案1】:

问题是我试图使用instrumentation.getAllLoadedClasses() 重新转换所有类。相反,我根据包名称过滤掉了我感兴趣的类,并且它适用于一组有限的类。

也许有一些加载的类不应该被重新转换。

【讨论】:

嗯,当然可以。我本来可以告诉你的。但是你说你想重新转换所有类。当我尝试时,JVM 在这种情况下只是抛出了一个异常,但它没有段错误。这就是为什么我曾经并且仍然对 MCVE 感兴趣的原因。如果JVM有问题,这是值得了解和跟踪的。 我尝试查看其他一些项目并尝试创建 MCVE。我无法重现该问题。这引导我找到解决方案。谢谢@kriegaex 我在 MCVE 工作时收到了UnmodifiableClassException 是的,我在尝试重现您的问题时遇到了相同的异常类型,但就像我说的,绝不会出现段错误。无论如何,我很高兴你的问题得到了解决。如果您可以重现段错误,请确保创建一个 Java 错误票(如果它尚不存在),就像错误消息所暗示的那样(甚至还有一个 URL)。理想情况下,还要创建一个核心转储。

以上是关于instrumentation.retransformClasses() 抛出致命错误的主要内容,如果未能解决你的问题,请参考以下文章