Object invoke(Object obj, Object... args) { // there are some security checks here !! MethodAccessor ma = this.methodAccessor ; if (ma == null) { ma = acquireMethodAccessor() ; } return ma.invoke(obj, args); }
if there are few (<= 2) impls, the JIT generate as cascade of if … else Object invoke(Object obj, Object... args) { ... if (ma.getClass() == MethodAccessor$1.class) { ((MethodAccessor$1)ma).invoke(obj, args); } else ... }
MethodAccessor Too many MethodAccessor implementations, the VM don't inline them :( String foo() int bar() void baz(int value) Object invoke(...) { ... ma.invoke(impl, args); String foo() { ... } int bar() { … } int baz(int value) { ... } Proxy InvocationHandler Real Implementation
not work – 2 objects (proxy + handler) instead of one j.l.r.Proxy API is outdated – No support for default method (1.8) – Funky support of j.l.Object public methods
Caller and callee are fully inlined ! Stacktrace ! – Interceptors are called by tailcall – The proxy hide itself (these stacktraces are not the ones you are looking for)
Proxy\123455 implements Logger { private final Logger arg0; public Proxy\123455(Logger arg0) { this.arg0 = arg0; } public void log(String message) { return invokedynamic(this, arg0, message); [proxyhandler-placeholder, context-placeholder] } } These constants are patched when defining the class !
java.lang.invoke Can use two internal annotations @Hidden (LambdaForm$Hidden) the method will not be visible in the stacktrace @ForceInline the method will always be inlined !
of Java8 lambdas :( Need to retrofit Proxy2 lib to be Java7 compatible Easy part : rewrite class version 1.8 → 1.7 using ASM Not that easy part : support lambda on Java 7 ??
is created using invokedynamic using j.l.i.LambdaMetaFactory bootstrap method At runtime, a lambda is an instance of a class that implements an interface thus a Proxy