Javassist:ClassPool.makeClass() 的副作用?

标签 java classloader instrumentation javassist javaagents

我正在调查一个奇怪的异常,当运行由使用Javassist代理检测的java 8应用程序时>:

Exception in thread "main" java.lang.BootstrapMethodError: java.lang.NoClassDefFoundError: Could not initialize class java.lang.invoke.CallSite
        at java.lang.invoke.MethodHandleNatives.linkCallSiteImpl(MethodHandleNatives.java:307)
        at java.lang.invoke.MethodHandleNatives.linkCallSite(MethodHandleNatives.java:297)
        ... 7 more


在进一步调查中,似乎 Javassist 的 ClassPool.makeClass()导致这种情况。调用此方法时肯定会有一些(类加载?)副作用
我的 ClassFileTransformer 的简约版本已经重现了该错误:

  public byte[] transform(ClassLoader loader, String className,
      Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
      byte[] classfileBuffer) throws IllegalClassFormatException
  {
    ClassPool pool = ClassPool.getDefault();
    try
    {
      CtClass makeClass = pool.makeClass(new java.io.ByteArrayInputStream(
          classfileBuffer));
    }
    catch (IOException | RuntimeException e)
    {
      e.printStackTrace();
    }

    return classfileBuffer;
  }


如您所见,我总是返回类的未更改的 byte[] 表示形式,我不会修改任何类。
当删除带有 pool.makeClass() 的行,应用程序将正常运行。

问题:
您能给我提示一下这里出了什么问题以及 makeClass() 的哪些副作用导致了这种情况吗?

最佳答案

当您执行加载时转换时,一旦安装了转换器,就会为所有尝试加载的类调用您的 transform 方法。这包括 Javassist 本身所需的类(如果尚未加载)。因此,如果不排除这些类,就会创建循环依赖。当您尝试使用变压器仍在运行(在同一线程内)的类时,JVM 似乎会响应 NoClassDefFoundError

顺便说一句,如果您不更改类,我建议返回 null 来告诉 JVM 您没有更改任何内容。否则,JVM 不知道您是否已写入数组,并且必须重新解析数据(或将它们与原始字节进行比较以发现它们没有更改)。这只是一个性能问题。

关于Javassist:ClassPool.makeClass() 的副作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33038650/

相关文章:

java - 使用 jdom 和 jaxen 选择元素

java - socketChannel 抛出 IOException 且权限被拒绝

java - 如何在 JBOSS AS7 中关闭或禁用 vfs 文件加载

java - 从 junit 获取位于源文件夹中的包的完整路径

java - Android如何解析XHTML

java - 如何合并 2 个数组?

java - Thread.currentThread().setContextClassLoader 似乎无法正常工作

debugging - 远程调试 javaagent jar 文件

java - 解决使用javaagent命令时出现java.lang.NoClassDefFoundError异常

java - 拦截来自特定命名空间的所有方法/构造函数/getters/setters