Proposal: java.lang.reflect.Proxy and default methods

Peter Levart peter.levart at gmail.com
Fri Jun 3 14:58:10 UTC 2016


Hi,

Since Java SE 8 introduced default methods in interfaces there was a 
question what to do with java.lang.reflect.Proxy API. Nothing was done 
to the API at that time, so the default behavior is to proxy default 
methods too. InvocationHandler gets invoked for default methods, but it 
has not provision to forward such calls to the default implementations 
in the interfaces.

I propose a simple API addition that allows calling super default 
methods in proxy instances:

http://cr.openjdk.java.net/~plevart/jdk9-dev/Proxy.invokeSuperDefaults/webrev.02/

With this addition one can simply decide in the InvocationHandler what 
to do with invocations to default methods and can forward such 
invocation to the default implementation:

public class Test {

     interface I1 {
         default void m() {
             System.out.println("  default I1.m() called");
         }
     }

     interface I2 {
         default void m() {
             System.out.println("  default I2.m() called");
         }
     }

     interface I12 extends I1, I2 {
         @Override
         void m();

         default int sum(int a, int b) {
             return a + b;
         }

         default Object[] concat(Object first, Object... rest) {
             Object[] result = new Object[1 + rest.length];
             result[0] = first;
             System.arraycopy(rest, 0, result, 1, rest.length);
             return result;
         }
     }

     public static void main(String[] args) {

         InvocationHandler h = (proxy, method, params) -> {
             System.out.println("\nInvocationHandler called for: " + 
method +
                                " with parameters: " + 
Arrays.toString(params));
             if (method.isDefault()) {
                 try {
                     return Proxy.invokeSuper(proxy, method, params);
                 } catch (InvocationTargetException e) {
                     throw e.getCause();
                 }
             } else {
                 switch (method.getName()) {
                     case "m":
                         System.out.println("  abstract I12.m(): called");
                         return null;
                     default:
                         throw new UnsupportedOperationException(
                             "Unsupported method: " + method);
                 }
             }
         };

         I1 i1 = (I1) Proxy.newProxyInstance(
             I1.class.getClassLoader(), new Class<?>[]{I1.class}, h);
         i1.m();

         I2 i2 = (I2) Proxy.newProxyInstance(
             I2.class.getClassLoader(), new Class<?>[]{I2.class}, h);
         i2.m();

         I12 i12 = (I12) Proxy.newProxyInstance(
             I12.class.getClassLoader(), new Class<?>[]{I12.class}, h);
         i12.m();

         System.out.println("  1 + 2 = " + i12.sum(1, 2));
         System.out.println("  [1] concat [2, 3, 4] = " +
                            Arrays.toString(i12.concat(1, 2, 3, 4)));
     }
}


I know FC date is over, but this is really a small change and I have 
heard several people that such feature is missing from the Proxy API.

I'm prepared to create jtreg tests covering the specification if this 
proposal is accepted.

Regards, Peter





More information about the core-libs-dev mailing list