Since Java 8 interfaces could have default methods. I know how to invoke the method explicitly from the implementing method, i.e. (see Explicitly calling a default method in Java)
But how do I explicitly invoke the default method using reflection for example on a proxy?
Example:
interface ExampleMixin {
  String getText();
  default void printInfo(){
    System.out.println(getText());
  }
}
class Example {
  public static void main(String... args) throws Exception {
    Object target = new Object();
    Map<String, BiFunction<Object, Object[], Object>> behavior = new HashMap<>();
    ExampleMixin dynamic =
            (ExampleMixin) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),new Class[]{ExampleMixin.class}, (Object proxy, Method method, Object[] arguments) -> {
                //custom mixin behavior
                if(behavior.containsKey(method.getName())) {
                    return behavior.get(method.getName()).apply(target, arguments);
                //default mixin behavior
                } else if (method.isDefault()) {
                    //this block throws java.lang.IllegalAccessException: no private access for invokespecial
                    return MethodHandles.lookup()
                                        .in(method.getDeclaringClass())
                                        .unreflectSpecial(method, method.getDeclaringClass())
                                        .bindTo(target)
                                        .invokeWithArguments();
                //no mixin behavior
                } else if (ExampleMixin.class == method.getDeclaringClass()) {
                    throw new UnsupportedOperationException(method.getName() + " is not supported");
                //base class behavior
                } else{
                    return method.invoke(target, arguments);
                }
            });
    //define behavior for abstract method getText()
    behavior.put("getText", (o, a) -> o.toString() + " myText");
    System.out.println(dynamic.getClass());
    System.out.println(dynamic.toString());
    System.out.println(dynamic.getText());
    //print info should by default implementation
    dynamic.printInfo();
  }
}
Edit: I know a similar question has been asked in How do I invoke Java 8 default methods refletively, but this has not solved my problem for two reasons:
- the problem described in that question aimed on how to invoked it via reflection in general - so no distinction between default and overriden method was made - and this is simple, you only need an instance.
- one of the answers - using method handles - does only work with nasty hack (imho) like changing access modifiers to fields of the lookup class, which is the same category of "solutions" like this: Change private static final field using Java reflection: it's good to know it's possible, but I wouldn't use it in production - I'm looking for an "official" way to do it.
The IllegalAccessException is thrown in unreflectSpecial
Caused by: java.lang.IllegalAccessException: no private access for invokespecial: interface example.ExampleMixin, from example.ExampleMixin/package
at java.lang.invoke.MemberName.makeAccessException(MemberName.java:852)
at java.lang.invoke.MethodHandles$Lookup.checkSpecialCaller(MethodHandles.java:1568)
at java.lang.invoke.MethodHandles$Lookup.unreflectSpecial(MethodHandles.java:1227)
at example.Example.lambda$main$0(Example.java:30)
at example.Example$$Lambda$1/1342443276.invoke(Unknown Source)
 
     
     
     
     
     
     
     
     
    