ich eine Klasse mit dem folgenden Code rebase:VerifyError in Gson Klassen
DynamicType.Unloaded unloaded = new ByteBuddy().with(TypeValidation.DISABLED).rebase(typeDescription,
ClassFileLocator.Simple.of(className, classBytes,
ClassFileLocator.ForClassLoader.of((ClassLoader) classLoader))).method(
ElementMatchers.isPackagePrivate().and(ElementMatchers.not(ElementMatchers.isAbstract()))).intercept(
MethodDelegation.to(PackagePrivateInterceptor.class)).transform(
MethodTransformer.Simple.withModifiers(Visibility.PUBLIC)).make();
return new ClassPair(unloaded.load((ClassLoader) classLoader,
ClassLoadingStrategy.Default.INJECTION.withProtectionDomain(
classLoader.getClass().getProtectionDomain())).getLoaded(), unloaded.getBytes());
Wenn Laden der Klasse class com.google.gson.internal.ConstructorConstructor
es durch den Konstruktor geht, bis es schließlich zum Klasseninitialisierer von com.google.gson.internal.LinkedTreeMap
bekommt.
Während dieser Initialisierung ich eine VerifyError erhalten:
1:24:20.227 [main] ERROR [io.hakansson.dynamicjar.core.main.Bootstrap] - java.lang.RuntimeException: java.lang.VerifyError: Illegal type at constant pool entry 195 in class com.google.gson.internal.LinkedTreeMap$1 Exception Details: Location: com/google/gson/internal/LinkedTreeMap$1.thenComparing$accessor$vT023QbO(Ljava/util/function/Function;)Ljava/util/Comparator; @2: invokespecial Reason: Constant pool index 195 is invalid Bytecode: 0x0000000: 2a2b b700 c3b0 at io.hakansson.dynamicjar.core.api.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:52) at io.hakansson.dynamicjar.core.main.Bootstrap.main(Bootstrap.java:42) Caused by: java.lang.VerifyError: Illegal type at constant pool entry 195 in class com.google.gson.internal.LinkedTreeMap$1 Exception Details: Location: com/google/gson/internal/LinkedTreeMap$1.thenComparing$accessor$vT023QbO(Ljava/util/function/Function;)Ljava/util/Comparator; @2: invokespecial Reason: Constant pool index 195 is invalid Bytecode: 0x0000000: 2a2b b700 c3b0 at com.google.gson.internal.LinkedTreeMap.classInitializer$oNOjADym(LinkedTreeMap.java:40) at com.google.gson.internal.LinkedTreeMap.(LinkedTreeMap.java) at com.google.gson.internal.ConstructorConstructor$13.construct$original$gt92dwVY(ConstructorConstructor.java:207) at com.google.gson.internal.ConstructorConstructor$13.construct$original$gt92dwVY$accessor$lof1omy8(ConstructorConstructor.java) at com.google.gson.internal.ConstructorConstructor$13$auxiliary$oB71rVyd.call(Unknown Source) at io.hakansson.dynamicjar.nestedjarclassloader.PackagePrivateInterceptor.intercept(PackagePrivateInterceptor.java:29) at com.google.gson.internal.ConstructorConstructor$13.construct(ConstructorConstructor.java) at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:167) at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:145) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read$original$ZTjOtCtb(ReflectiveTypeAdapterFactory.java:116) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read$original$ZTjOtCtb$accessor$WgRdwpwl(ReflectiveTypeAdapterFactory.java) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1$auxiliary$41HBhnNS.call(Unknown Source) at io.hakansson.dynamicjar.nestedjarclassloader.PackagePrivateInterceptor.intercept(PackagePrivateInterceptor.java:29) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:216) at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read$original$bOjIYDn5(TypeAdapterRuntimeTypeWrapper.java:40) at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read$original$bOjIYDn5$accessor$hMWEZRZS(TypeAdapterRuntimeTypeWrapper.java) at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper$auxiliary$U1tyihKy.call(Unknown Source) at io.hakansson.dynamicjar.nestedjarclassloader.PackagePrivateInterceptor.intercept(PackagePrivateInterceptor.java:29) at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java) at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:82) at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read$original$ZTjOtCtb(ReflectiveTypeAdapterFactory.java:116) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read$original$ZTjOtCtb$accessor$WgRdwpwl(ReflectiveTypeAdapterFactory.java) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1$auxiliary$41HBhnNS.call(Unknown Source) at io.hakansson.dynamicjar.nestedjarclassloader.PackagePrivateInterceptor.intercept(PackagePrivateInterceptor.java:29) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:216) at com.google.gson.Gson.fromJson(Gson.java:879) at com.google.gson.Gson.fromJson(Gson.java:817)
Als Referenz prüft der Abfangjäger im Grunde nur manuell für Paket-privaten Zugang (seit Paket private Methoden öffentlich gemacht wurden) und rufe dann nur superCall.call()
. Ich glaube nicht, dass das Problem dort liegt.
Irgendwelche Ideen?
EDIT: Hier ist die PackagePrivateInterceptor
: public class PackagePrivateInterceptor {
@RuntimeType
@BindingPriority(1)
public static Object intercept(@SuperCall Callable<?> superCall, @Origin Class targetClass, @Origin String method) throws
Exception
{
Class callingClass = new InternalSecurityManager().getCallingClass();
String targetPackage = targetClass.getPackage().getName();
if (!callingClass.getPackage().getName().equals(targetPackage)) {
throw new IllegalAccessError(callingClass + " cannot access method " + method + " of Class " + targetClass);
}
//Default:
return superCall.call();
}
private static class InternalSecurityManager extends SecurityManager {
Class getCallingClass() {
Class[] classContext = getClassContext();
for (Class current : classContext) {
if (current.getName().startsWith("java.") ||
current.getName().equals(PackagePrivateInterceptor.class.getName()) ||
current.getName().equals(InternalSecurityManager.class.getName()))
{
continue;
}
return current;
}
throw new IllegalStateException("Failed to find calling Class");
}
}
EDIT2: Der folgende Code löst nicht das Problem:
//Only package-private methods should be proxied.
DynamicType.Unloaded unloaded = new ByteBuddy().with(TypeValidation.DISABLED).rebase(typeDescription,
ClassFileLocator.Simple.of(className, classBytes,
ClassFileLocator.ForClassLoader.of((ClassLoader) classLoader))).method(
ElementMatchers.isPackagePrivate().and(ElementMatchers.not(ElementMatchers.isAbstract()))).intercept(
MethodDelegation.to(PackagePrivateInterceptor.class)).transform(
MethodTransformer.Simple.withModifiers(Visibility.PUBLIC)).make();
DynamicType.Loaded loaded = unloaded.load((ClassLoader) classLoader,
ClassLoadingStrategy.Default.INJECTION.withProtectionDomain(
classLoader.getClass().getProtectionDomain()));
if (className.equals("com.google.gson.internal.LinkedTreeMap"))
System.out.println(DatatypeConverter.printHexBinary(loaded.getBytes()));
return new ClassPair(loaded.getLoaded(), unloaded.getBytes());
Aber das folgende tut:
//All non-private methods should be proxied
//TODO: Actually, the class itself should be made visible and still only package-private methods should be proxied.
DynamicType.Unloaded unloaded = new ByteBuddy().with(TypeValidation.DISABLED).rebase(typeDescription,
ClassFileLocator.Simple.of(className, classBytes,
ClassFileLocator.ForClassLoader.of((ClassLoader) classLoader))).method(
ElementMatchers.not(ElementMatchers.isPrivate()).and(
ElementMatchers.not(ElementMatchers.isAbstract()))).intercept(
MethodDelegation.to(PackagePrivateInterceptor.class)).transform(
MethodTransformer.Simple.withModifiers(Visibility.PUBLIC)).make();
return new ClassPair(unloaded.load((ClassLoader) classLoader,
ClassLoadingStrategy.Default.INJECTION.withProtectionDomain(
classLoader.getClass().getProtectionDomain())).getLoaded(), unloaded.getBytes());
Konnten Sie eine Wiederherstellung dieses Fehlers erzeugen? Normalerweise sollte dies nicht passieren und ich kann diesen Fehler nicht erzeugen. Byte Buddy verwendet ASM unter den Abdeckungen, die sich um den gesamten konstanten Pool kümmern, also nehme ich an, dass es ein Problem in der Bibliothek gibt. –
Der Methodencode ist & ldquor; aload_0 aload_1 invokespecial [195] areurn ", der vernünftig aussieht, d. H. Nicht verworfen. Die Frage ist also, was mit dem Konstantenpool passiert ist, der einen Methodendeskriptor bei Index 195 enthalten sollte. Vielleicht könnte das Veröffentlichen des Ergebnisses von 'unloaded.getBytes()' (als hex dump) helfen ... – Holger
@RafaelWinterHalter, ich habe versucht, eine saubere Erholung zu machen, aber das Problem tritt nicht auf. Offensichtlich ist es etwas, was ich tue, aber die Sache ist, dass ich keine Manipulation der Bytes oder irgendetwas mache. Ich werde untersuchen und versuchen zu sehen, was genau ich mache, die diesen Fehler auslöst. – erikh