[code-reflection] RFR: Add isQuotable attribute to LambdaOp [v6]
Maurizio Cimadamore
mcimadamore at openjdk.org
Wed Sep 10 11:55:32 UTC 2025
On Wed, 10 Sep 2025 11:26:36 GMT, Maurizio Cimadamore <mcimadamore at openjdk.org> wrote:
> So, more generally, I think both `Interpreter` and `BytecodeGenerator` might have some issues in this area.
I tried something like this:
class Test {
public interface A<X> {
void m(X x);
}
public interface B<X extends Number> {
void m(X x);
}
public interface C extends A<Integer>, B<Integer> { }
@CodeReflection
static C getC() {
C c = i -> System.out.println(i);
return c;
}
public static void main(String[] args) throws Throwable {
var method = Test.class.getDeclaredMethod("getC");
var op = (CoreOp.FuncOp) Op.ofMethod(method).get();
A<?> a = (A<?>)Interpreter.invoke(MethodHandles.lookup(), op);
a.m(null);
}
}
This (surprisingly) seems to work. I believe the reason is that `Interpreter` uses `MethodHandleProxies::asInterfaceInstance` -- whose javadoc says:
* Because of the possibility of {@linkplain java.lang.reflect.Method#isBridge bridge methods}
* and other corner cases, the interface may also have several abstract methods
* with the same name but having distinct descriptors (types of returns and parameters).
* In this case, all the methods are bound in common to the one given target.
* The type check and effective {@code asType} conversion is applied to each
* method type descriptor, and all abstract methods are bound to the target in common.
* Beyond this type check, no further checks are made to determine that the
* abstract methods are related in any way.
So, this special "fallback overrides" end up saving the day in this case.
However, a similar example using `BytecodeGenerator` fails:
class Test {
public interface A<X> {
void m(X x);
}
public interface B<X extends Number> {
void m(X x);
}
public interface C extends A<Integer>, B<Integer> { }
@CodeReflection
static void run() {
C c = i -> System.out.println(i);
A<?> a = (A<?>)c;
a.m(null);
}
public static void main(String[] args) throws Throwable {
var method = Test.class.getDeclaredMethod("run");
var op = (CoreOp.FuncOp) Op.ofMethod(method).get();
var handle = BytecodeGenerator.generate(MethodHandles.lookup(), op);
handle.invokeExact();
}
}
The error I see is:
WARNING: Using incubator modules: jdk.incubator.code
Exception in thread "main" java.lang.AbstractMethodError: Receiver class run_0x0000000097069000$$Lambda/0x000000009706dbb0 does not define or inherit an implementation of the resolved method 'abstract void m(java.lang.Object)' of interface Test$A.
at Test.main(Test.java:33)
Which is kind of expected: the generated instance is missing a bridge (as it's generated via regular metafactory).
-------------
PR Comment: https://git.openjdk.org/babylon/pull/545#issuecomment-3274613153
More information about the babylon-dev
mailing list