ByteBuddy 1.10.2 抛出 `java.lang.IllegalStateException: 无法解析 java.lang.Exception` 的类型描述,以及类似的
ByteBuddy 1.10.2 throws `java.lang.IllegalStateException: Cannot resolve type description for java.lang.Exception`, and similar
我在为 Instrumentation
.
安装 AgentBuilder
转换时看到来自 AgentBuilder.Listener.onError(...)
的 Cannot resolve type description
错误
代理代码是:
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);
}
这是使用带有 Mule 4 (jdk1.8) 的 ByteBuddy v1.10.2 作为目标应用程序。
对于同一问题 也有类似的 post,但回复并没有让我找到解决方案。
输出显示"from bytebuddy: agent premain",但不显示"from bytebuddy: transform"。相反,日志显示属于 bootstrap class 加载程序的许多 classes 的异常,例如:
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)
...
似乎正在为类型描述查询的 class 加载器没有提供所需的 classes。有没有办法为这些查找指定备用 ClassFileLocator
?
导致错误的特定 class 加载器是:
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
如有任何建议,我们将不胜感激!
感谢您的帮助!
堆栈跟踪显示您正在对 Byte Buddy 应用超类型检查,而您不对 Byteman 使用该检查。如果您仅用 named(...)
替换 hasSuperType(named(...))
匹配器,它可能会正常工作,因为这似乎是错误发生的地方。 Byte Buddy 需要解析 class 层次结构中的所有 classes 才能应用此匹配器,这在您的情况下似乎是不可能的。
然而,ClassLoader
无法解析 java.lang.Exception
的 class 文件似乎很奇怪;您正在使用的 class 加载程序可能是自定义实现,不会委托给引导加载程序。
您可以通过在您的代理中定义自定义 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())
}
}
正如我在评论中提到的,如果您能说出无法解析 class 文件的 class 加载程序的类型,我也许能够提供更详细的答案。
我将在 Byte Buddy 的未来版本中添加此类定位策略的标准实现,以便更轻松地解决此问题。在此工单中跟踪进度:https://github.com/raphw/byte-buddy/issues/794
我在为 Instrumentation
.
AgentBuilder
转换时看到来自 AgentBuilder.Listener.onError(...)
的 Cannot resolve type description
错误
代理代码是:
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);
}
这是使用带有 Mule 4 (jdk1.8) 的 ByteBuddy v1.10.2 作为目标应用程序。
对于同一问题
输出显示"from bytebuddy: agent premain",但不显示"from bytebuddy: transform"。相反,日志显示属于 bootstrap class 加载程序的许多 classes 的异常,例如:
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)
...
似乎正在为类型描述查询的 class 加载器没有提供所需的 classes。有没有办法为这些查找指定备用 ClassFileLocator
?
导致错误的特定 class 加载器是:
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
如有任何建议,我们将不胜感激! 感谢您的帮助!
堆栈跟踪显示您正在对 Byte Buddy 应用超类型检查,而您不对 Byteman 使用该检查。如果您仅用 named(...)
替换 hasSuperType(named(...))
匹配器,它可能会正常工作,因为这似乎是错误发生的地方。 Byte Buddy 需要解析 class 层次结构中的所有 classes 才能应用此匹配器,这在您的情况下似乎是不可能的。
然而,ClassLoader
无法解析 java.lang.Exception
的 class 文件似乎很奇怪;您正在使用的 class 加载程序可能是自定义实现,不会委托给引导加载程序。
您可以通过在您的代理中定义自定义 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())
}
}
正如我在评论中提到的,如果您能说出无法解析 class 文件的 class 加载程序的类型,我也许能够提供更详细的答案。
我将在 Byte Buddy 的未来版本中添加此类定位策略的标准实现,以便更轻松地解决此问题。在此工单中跟踪进度:https://github.com/raphw/byte-buddy/issues/794