ByteBuddy 1.10.2抛出`java.lang.IllegalStateException:无法解析java.lang.Exception`的类型描述,并且类似

时间:2019-12-13 08:41:01

标签: mule byte-buddy byteman

在为Cannot resolve type description安装AgentBuilder.Listener.onError(...)转换时,我看到AgentBuilder出现Instrumentation错误。

代理代码为:

  public static void premain(final String agentArgs, final Instrumentation inst) {
    System.out.println("from bytebuddy: agent premain");
    new AgentBuilder.Default(new ByteBuddy().with(TypeValidation.DISABLED))
      .disableClassFormatChanges()
      .ignore(none())
      .with(RedefinitionStrategy.RETRANSFORMATION)
      .with(InitializationStrategy.NoOp.INSTANCE)
      .with(TypeStrategy.Default.REDEFINE)
      .with(new AgentBuilder.Listener() {
        public void onDiscovery(final String typeName, final ClassLoader classLoader, final JavaModule module, final boolean loaded) {
          log("Event::onDiscovery(" + typeName + ", " + getNameId(classLoader) + ", " + module + ", " + loaded + ")");
        }

        public void onTransformation(final TypeDescription typeDescription, final ClassLoader classLoader, final JavaModule module, final boolean loaded, final DynamicType dynamicType) {
          log("Event::onTransformation(" + typeDescription.getName() + ", " + getNameId(classLoader) + ", " + module + ", " + loaded + ", " + dynamicType + ")");
        }

        public void onIgnored(final TypeDescription typeDescription, final ClassLoader classLoader, final JavaModule module, final boolean loaded) {
          log("Event::onIgnored(" + typeDescription.getName() + ", " + getNameId(classLoader) + ", " + module + ", " + loaded + ")");
        }

        public void onError(final String typeName, final ClassLoader classLoader, final JavaModule module, final boolean loaded, final Throwable throwable) {
          log("Event::onError(" + typeName + ", " + getNameId(classLoader) + ", " + module + ", " + loaded + ")", throwable);
        }

        public void onComplete(final String typeName, final ClassLoader classLoader, final JavaModule module, final boolean loaded) {
          log("Event::onComplete(" + typeName + ", " + getNameId(classLoader) + ", " + module + ", " + loaded + ")");
        }
      })
      .type(hasSuperType(named("com.ning.http.client.AsyncHttpClientConfig$Builder")))
      .transform(new Transformer() {
        public DynamicType.Builder<?> transform(final DynamicType.Builder<?> builder, final     
          System.out.println("from bytebuddy: transform");
          TypeDescription typeDescription, final ClassLoader classLoader, final JavaModule module) {
          return builder.visit(Advice.to(AHCBuilderExit.class).on(isDefaultConstructor()));
        }})
      .installOn(inst);
  }

这是使用ByteBuddy v1.10.2和Mule 4(jdk1.8)作为目标应用程序。

关于同一问题here,有一篇类似的帖子,但答复并未使我找到解决方案。

输出显示“ from bytebuddy:agent premain”,但不显示“ from bytebuddy:transform”。相反,日志会显示许多属于引导类加载器的类的异常,例如:

Event::onError(org.mule.weave.v2.el.WeaveExpressionLanguage, org.mule.runtime.module.artifact.api.classloader.MuleArtifactClassLoader@6d4b1d14, null, false)
java.lang.IllegalStateException: Cannot resolve type description for java.lang.Exception
    at net.bytebuddy.pool.TypePool$Resolution$Illegal.resolve(TypePool.java:159)
    at net.bytebuddy.pool.TypePool$Default$WithLazyResolution$LazyTypeDescription.delegate(TypePool.java:914)
    at net.bytebuddy.description.type.TypeDescription$AbstractBase$OfSimpleType$WithDelegation.getSuperClass(TypeDescription.java:8031)
    at net.bytebuddy.description.type.TypeDescription$Generic$OfNonGenericType.getSuperClass(TypeDescription.java:3619)
    at net.bytebuddy.description.type.TypeDefinition$SuperClassIterator.next(TypeDefinition.java:314)
    at net.bytebuddy.description.type.TypeDefinition$SuperClassIterator.next(TypeDefinition.java:281)
    at net.bytebuddy.matcher.HasSuperTypeMatcher.matches(HasSuperTypeMatcher.java:53)
...

似乎正在为类型描述查询的类加载器没有提供所需的类。是否可以为这些查询指定备用ClassFileLocator

导致错误的特定类加载器是: org.mule.runtime.module.artifact.api.classloader.MuleArtifactClassLoader

有趣的是,使用Byteman作为代理并使用以下规则文件时,该工具可以按预期工作:

RULE AsyncHttpClientConfig.Builder.<init>
CLASS com.ning.http.client.AsyncHttpClientConfig$Builder
METHOD <init>
AT EXIT
IF TRUE
DO
  traceln("from byteman: AsyncHttpClientConfig$Builder.<init> triggered: " + getClass().getClassLoader());
ENDRULE

任何建议将不胜感激! 谢谢您的帮助!

1 个答案:

答案 0 :(得分:1)

堆栈跟踪表明您正在对不与Byteman一起使用的Byte Buddy应用超级类型检查。如果仅将hasSuperType(named(...))匹配器替换为named(...),则可能会没有错误,因为这似乎是发生错误的地方。字节好友需要解析一个类层次结构中的所有类,以便能够应用此匹配器,这在您的情况下似乎是不可能的。

但是,ClassLoader无法解析java.lang.Exception的类文件似乎很奇怪;可能您正在使用的类加载器是不委托给启动加载器的自定义实现。

您可以通过在代理程序中定义一个自定义LocationStrategy来解决此问题,该自定义项始终会查询引导加载程序作为替代选项:

class BootFallbackLocationStrategy implements AgentBuilder.LocationStrategy {

  @Override
  public ClassFileLocator classFileLocator(ClassLoader classLoader, JavaModule module) {
     return new ClassFileLocator.Compound(
       ClassFileLocator.ForClassLoader.of(classLoader),  
       ClassFileLocator.ForClassLoader.ofBootLoader())
  }
}

如我的评论中所述,如果您可以命名无法解析类文件的类加载器的类型,那么我也许可以提供更详细的答案。

我将在Byte Buddy的未来版本中添加这种位置策略的标准实现,以使解决此问题变得更加容易。此票证中跟踪进度:https://github.com/raphw/byte-buddy/issues/794