所以我遇到了
Exception in thread "Thread-0" java.lang.IllegalArgumentException: Unknown type: null
at net.bytebuddy.description.type.TypeDefinition$Sort.describe(TypeDefinition.java:213)
at net.bytebuddy.description.type.TypeDescription$Generic$OfParameterizedType$ForLoadedType$ParameterArgumentTypeList.get(TypeDescription.java:4595)
at net.bytebuddy.description.type.TypeDescription$Generic$OfParameterizedType$ForLoadedType$ParameterArgumentTypeList.get(TypeDescription.java:4569)
at java.util.AbstractList$Itr.next(AbstractList.java:358)
at net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Substitutor.onParameterizedType(TypeDescription.java:1556)
at net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Substitutor$ForDetachment.onParameterizedType(TypeDescription.java:1709)
at net.bytebuddy.description.type.TypeDescription$Generic$OfParameterizedType.accept(TypeDescription.java:4407)
at net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Substitutor.onParameterizedType(TypeDescription.java:1557)
at net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Substitutor$ForDetachment.onParameterizedType(TypeDescription.java:1709)
at net.bytebuddy.description.type.TypeDescription$Generic$OfParameterizedType.accept(TypeDescription.java:4407)
at net.bytebuddy.description.type.TypeDescription$Generic$LazyProjection.accept(TypeDescription.java:5308)
at net.bytebuddy.description.field.FieldDescription$AbstractBase.asToken(FieldDescription.java:143)
at net.bytebuddy.description.field.FieldDescription$AbstractBase.asToken(FieldDescription.java:87)
at net.bytebuddy.description.field.FieldList$AbstractBase.asTokenList(FieldList.java:47)
at net.bytebuddy.dynamic.scaffold.InstrumentedType$Factory$Default$1.represent(InstrumentedType.java:222)
at net.bytebuddy.ByteBuddy.redefine(ByteBuddy.java:698)
at net.bytebuddy.ByteBuddy.redefine(ByteBuddy.java:676)
at parc.Foo.redefineClass(Foo.java:137)
尝试重新定义已使用字节码加载的类时,已加载JVM。
该代码处于由烟灰框架转换的初步步骤中,我们怀疑某些签名属性在该过程中可能已过时或丢失,并且ByteBuddy只是坚持认为它没有信息的正确性。
严格来说,ByteBuddy也不需要该信息。 (显然,了解一下签名属性是如何可选的,以及如何由JVM加载和运行该类就很好了。)
因此,一种快速的检查方法是告诉byteBuddy根本不在乎,看看是否有任何改变。
有没有办法以这种方式配置ByteBuddy?
(ByteBuddy版本为
1.7.9
)(项目需要Java 7)
(类重新加载完成
private void redefineClass(String classname, byte[] bytecode) {
ClassFileLocator cfl = ClassFileLocator.Simple.of(classname,bytecode);
Class clazz;
try{
clazz = Class.forName(classname);
}catch(ClassNotFoundException e){
throw new RuntimeException(e);
}
Debug._print("REDEFINING %s",clazz.getName());
new ByteBuddy()
.redefine(clazz,cfl)
.make()
.load(clazz.getClassLoader(),ByteBuddyConfig.reloadingStrategy)
;
}
与
public class ByteBuddyConfig {
static final ClassReloadingStrategy reloadingStrategy;
static {
try {
reloadingStrategy = new ClassReloadingStrategy(
(Instrumentation) ClassLoader.getSystemClassLoader()
.loadClass("net.bytebuddy.agent.Installer")
.getMethod("getInstrumentation")
.invoke(null),
ClassReloadingStrategy.Strategy.RETRANSFORMATION);
}catch(ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e){
throw new RuntimeException(e);
}
}
}
感谢how to debug an internal error?的@kutschkern)
最佳答案
我想不管ByteBuddy
前端在这里做什么,都是对您可以链接以执行另一种转换的所有其他操作的支持的一部分。如the answer to your other question中所述,当已经有字节代码时,可以跳过以下操作:
ClassReloadingStrategy s = ClassReloadingStrategy.fromInstalledAgent();
s.load(clazz.getClassLoader(),
Collections.singletonMap(new TypeDescription.ForLoadedType(clazz), bytecode));
在Java 8之前,您需要
Collections.<TypeDescription,byte[]>singletonMap(…)
。当类加载策略基于
ClassReloadingStrategy.Strategy.REDEFINITION
时,您也可以使用ClassReloadingStrategy s = ClassReloadingStrategy.fromInstalledAgent();
s.reset(ClassFileLocator.Simple.of(classname, bytecode), clazz);
因为它将使用通过
ClassFileLocator
检索的字节码作为基础。我建议保持标准的获取
ClassReloadingStrategy
实现的方式,就像您在其他问题中所做的那样,我无法理解您希望通过这种更为复杂的反射操作获得什么。