Skip to content

Commit

Permalink
Fixed abstract methods crashing on init
Browse files Browse the repository at this point in the history
  • Loading branch information
Lenni0451 committed Jun 19, 2024
1 parent c37e2d0 commit d4ce6e9
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 5 deletions.
24 changes: 20 additions & 4 deletions src/main/java/net/lenni0451/reflect/proxy/impl/ProxyRuntime.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import net.lenni0451.reflect.bytecode.builder.BytecodeBuilder;
import net.lenni0451.reflect.bytecode.wrapper.BuiltClass;
import net.lenni0451.reflect.bytecode.wrapper.BytecodeLabel;
import org.jetbrains.annotations.ApiStatus;

import java.lang.invoke.MethodHandle;
Expand Down Expand Up @@ -109,6 +110,18 @@ public static ProxyMethod makeProxyMethod(final Object instance, final Method me
for (Class<?> parameter : method.getParameterTypes()) polymorphicSignature += desc(parameter);
polymorphicSignature += ")" + desc(method.getReturnType());

BytecodeLabel elseLabel = BUILDER.label();
mb
.var(BUILDER.opcode("ALOAD"), 0)
.field(BUILDER.opcode("GETSTATIC"), className, "INVOKE_SUPER", desc(MethodHandle.class))
.jump(BUILDER.opcode("IFNONNULL"), elseLabel)
.type(BUILDER.opcode("NEW"), slash(UnsupportedOperationException.class))
.insn(BUILDER.opcode("DUP"))
.ldc("Can't invoke abstract super method")
.method(BUILDER.opcode("INVOKESPECIAL"), slash(UnsupportedOperationException.class), "<init>", mdesc(void.class, String.class), false)
.insn(BUILDER.opcode("ATHROW"))
.label(elseLabel);

mb.field(BUILDER.opcode("GETSTATIC"), className, "INVOKE_SUPER", desc(MethodHandle.class));
mb //Cast instance to owner class
.var(BUILDER.opcode("ALOAD"), 0)
Expand Down Expand Up @@ -168,10 +181,13 @@ public static ProxyMethod makeProxyMethod(final Object instance, final Method me
}

public static MethodHandle[] getMethodHandles(final Class<?> owner, final String name, final Class<?>[] parameters, final Class<?> returnType) throws NoSuchMethodException, IllegalAccessException {
return new MethodHandle[]{
TRUSTED_LOOKUP.findVirtual(owner, name, MethodType.methodType(returnType, parameters)),
TRUSTED_LOOKUP.findSpecial(owner, name, MethodType.methodType(returnType, parameters), owner)
};
MethodHandle invokeOther = TRUSTED_LOOKUP.findVirtual(owner, name, MethodType.methodType(returnType, parameters));
MethodHandle invokeSuper = null;
try {
invokeSuper = TRUSTED_LOOKUP.findSpecial(owner, name, MethodType.methodType(returnType, parameters), owner);
} catch (Throwable ignored) {
}
return new MethodHandle[]{invokeOther, invokeSuper};
}

}
15 changes: 15 additions & 0 deletions src/test/java/net/lenni0451/reflect/proxy/ProxyTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import net.lenni0451.reflect.proxy.impl.Proxy;
import net.lenni0451.reflect.proxy.test.Class1;
import net.lenni0451.reflect.proxy.test.Class2;
import net.lenni0451.reflect.proxy.test.Interface1;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

Expand All @@ -16,6 +17,7 @@ class ProxyTest {
void init() {
ProxyBuilder proxyBuilder = new ProxyBuilder();
proxyBuilder.setSuperClass(Class1.class);
proxyBuilder.addInterface(Interface1.class);
this.proxy = proxyBuilder.build().allocateInstance();
}

Expand Down Expand Up @@ -58,4 +60,17 @@ void testCancel() {
assertNull(this.proxy.getString());
}

@Test
void testInterface() {
Class2 other = new Class2();
((Proxy) this.proxy).setInvocationHandler((thiz, proxyMethod, args) -> proxyMethod.invokeWith(other, args));
assertEquals(12, ((Interface1) this.proxy).interfaceTest());
}

@Test
void testInvokeAbstractSuper() {
((Proxy) this.proxy).setInvocationHandler((thiz, proxyMethod, args) -> proxyMethod.invokeSuper(args));
assertThrows(UnsupportedOperationException.class, () -> ((Interface1) this.proxy).interfaceTest());
}

}
7 changes: 6 additions & 1 deletion src/test/java/net/lenni0451/reflect/proxy/test/Class2.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
package net.lenni0451.reflect.proxy.test;

public class Class2 extends Class1 {
public class Class2 extends Class1 implements Interface1 {

@Override
public int test() {
return 2;
}

@Override
public int interfaceTest() {
return 12;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package net.lenni0451.reflect.proxy.test;

public interface Interface1 {

int interfaceTest();

}

0 comments on commit d4ce6e9

Please sign in to comment.