diff --git a/README.md b/README.md index 80d4b4a..cbb8e91 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,6 @@ Import as a Gradle dependency: ```groovy dependencies { - implementation("io.github.over-run:marshal:0.1.0-alpha.11-jdk22") + implementation("io.github.over-run:marshal:0.1.0-alpha.12-jdk22") } ``` diff --git a/gradle.properties b/gradle.properties index 2c17ec0..0a1ed51 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ projGroupId=io.github.over-run projArtifactId=marshal # The project name should only contain lowercase letters, numbers and hyphen. projName=marshal -projVersion=0.1.0-alpha.11-jdk22 +projVersion=0.1.0-alpha.12-jdk22 projDesc=Marshaler of native libraries # Uncomment them if you want to publish to maven repository. projUrl=https://github.com/Over-Run/marshal diff --git a/src/main/java/overrun/marshal/Downcall.java b/src/main/java/overrun/marshal/Downcall.java index 013088f..52df4f6 100644 --- a/src/main/java/overrun/marshal/Downcall.java +++ b/src/main/java/overrun/marshal/Downcall.java @@ -394,11 +394,11 @@ private static Method findUpcallWrapper(Class aClass) { } @SuppressWarnings("unchecked") - private static T loadBytecode(Class callerClass, SymbolLookup lookup, Map descriptorMap) { + private static T loadBytecode(Class targetClass, SymbolLookup lookup, Map descriptorMap) { final ClassFile cf = of(); - final ClassDesc cd_thisClass = ClassDesc.of(callerClass.getPackageName(), DEFAULT_NAME); + final ClassDesc cd_thisClass = ClassDesc.of(targetClass.getPackageName(), DEFAULT_NAME); final byte[] bytes = cf.build(cd_thisClass, classBuilder -> { - final List methodList = Arrays.stream(callerClass.getMethods()) + final List methodList = Arrays.stream(targetClass.getMethods()) .filter(method -> method.getDeclaredAnnotation(Skip.class) == null && !Modifier.isStatic(method.getModifiers())) @@ -425,7 +425,8 @@ private static T loadBytecode(Class callerClass, SymbolLookup lookup, Map classBuilder.withFlags(ACC_FINAL | ACC_SUPER); // interface - classBuilder.withInterfaceSymbols(callerClass.describeConstable().orElseThrow()); + final ClassDesc cd_targetClass = targetClass.describeConstable().orElseThrow(); + classBuilder.withInterfaceSymbols(cd_targetClass); // linker classBuilder.withField("$LINKER", CD_Linker, ACC_PRIVATE | ACC_FINAL | ACC_STATIC); @@ -833,11 +834,10 @@ private static T loadBytecode(Class callerClass, SymbolLookup lookup, Map blockCodeBuilder -> { // invoke super interface invokeSuperMethod(blockCodeBuilder, parameters); - final Class declaringClass = method.getDeclaringClass(); - blockCodeBuilder.invokespecial(ClassDesc.ofDescriptor(declaringClass.descriptorString()), + blockCodeBuilder.invokespecial(cd_targetClass, methodName, mtd_method, - declaringClass.isInterface()) + targetClass.isInterface()) .areturn(); }); } else { @@ -854,11 +854,10 @@ private static T loadBytecode(Class callerClass, SymbolLookup lookup, Map blockCodeBuilder -> { // invoke super interface invokeSuperMethod(blockCodeBuilder, parameters); - final Class declaringClass = method.getDeclaringClass(); - blockCodeBuilder.invokespecial(declaringClass.describeConstable().orElseThrow(), + blockCodeBuilder.invokespecial(cd_targetClass, methodName, mtd_method, - declaringClass.isInterface() + targetClass.isInterface() ).returnInstruction(returnTypeKind); } ).nop(); @@ -1049,7 +1048,7 @@ private static T loadBytecode(Class callerClass, SymbolLookup lookup, Map }); try { - final MethodHandles.Lookup hiddenClass = MethodHandles.privateLookupIn(callerClass, MethodHandles.lookup()) + final MethodHandles.Lookup hiddenClass = MethodHandles.privateLookupIn(targetClass, MethodHandles.lookup()) .defineHiddenClassWithClassData(bytes, Map.copyOf(descriptorMap), true, MethodHandles.Lookup.ClassOption.STRONG); return (T) hiddenClass.findConstructor(hiddenClass.lookupClass(), MethodType.methodType(void.class, SymbolLookup.class)) .invoke(lookup); diff --git a/src/test/java/overrun/marshal/test/IndirectInterfaceTest.java b/src/test/java/overrun/marshal/test/IndirectInterfaceTest.java new file mode 100644 index 0000000..621fc1d --- /dev/null +++ b/src/test/java/overrun/marshal/test/IndirectInterfaceTest.java @@ -0,0 +1,47 @@ +/* + * MIT License + * + * Copyright (c) 2024 Overrun Organization + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + */ + +package overrun.marshal.test; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import overrun.marshal.Downcall; + +import java.lang.foreign.SymbolLookup; + +/** + * Test indirect interface + * + * @author squid233 + * @since 0.1.0 + */ +public final class IndirectInterfaceTest { + interface I1 { + default int fun1() { + return 1; + } + } + + interface I2 extends I1 { + } + + I2 INSTANCE = Downcall.load(I2.class, SymbolLookup.loaderLookup()); + + @Test + void testIndirectInterface() { + Assertions.assertEquals(1, INSTANCE.fun1()); + } +}