Reputation: 8209
So I ran into
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)
When trying to redefine a class that is already loaded with the bytecode the JVM loaded.
The code was in a preliminary step already transformed by a soot-framework and we suspect that some of the signature attributes might have become outdated or gone missing in that processs and that ByteBuddy simply insists on the correctness of the info it doesn't have.
Strictly speaking, ByteBuddy doesn't need that information, either. (Obviously, seeing how the signature attribute is optional and how the class is loaded and run by the JVM just fine.) So a quick way to check would be to tell byteBuddy to simply not care and see if that changes anything.
Is there a way to configure ByteBuddy in such a way?
(ByteBuddy version is 1.7.9
)
(Project requires Java 7)
(class reloading is done
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)
;
}
with
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);
}
}
}
thanks to @kutschkern from how to debug an internal error? )
Upvotes: 4
Views: 471
Reputation: 44042
You can set the net.bytebuddy.raw
property to true
what forces Byte Buddy into ignoring any generic type information. Know that setting this property might yield unexpected results as Byte Buddy is for example no longer able to properly resolve bridge methods and other things.
You can typically set this property when you are writing a Java agent that only transforms already existing methods, typically using Advice
.
This is a strange error though, that implies a ParameterizedType
that defines one of its getActualTypeArguments
as null
. Such errors do typically raise errors by the JVM generic signature parser.
As for the reflective operations, the yet unreleased Byte Buddy 1.7.11 will include a convenience method for setting the strategy.
Upvotes: 2
Reputation: 298529
I suppose that whatever the ByteBuddy
frontend is doing here, is part of the support for all the other operations you could chain to perform another transformation. As said in the answer to your other question, you can skip these operations when have the byte code already:
ClassReloadingStrategy s = ClassReloadingStrategy.fromInstalledAgent();
s.load(clazz.getClassLoader(),
Collections.singletonMap(new TypeDescription.ForLoadedType(clazz), bytecode));
Before Java 8, you’ll need Collections.<TypeDescription,byte[]>singletonMap(…)
.
when the class loading strategy is based on ClassReloadingStrategy.Strategy.REDEFINITION
you can also use
ClassReloadingStrategy s = ClassReloadingStrategy.fromInstalledAgent();
s.reset(ClassFileLocator.Simple.of(classname, bytecode), clazz);
as it will use the bytecode retrieved through the ClassFileLocator
as base.
I suggest to stay with the standard way of acquiring the ClassReloadingStrategy
implementation, as you did in your other question, I can’t recognize what you hope to gain with this more complicated reflective operation.
Upvotes: 3