RFR: 8159746: (proxy) Support for default methods

Mandy Chung mchung at openjdk.java.net
Thu Oct 8 06:52:28 UTC 2020


On Wed, 7 Oct 2020 21:04:36 GMT, Mandy Chung <mchung at openjdk.org> wrote:

>>> Joe has given some feedback in the CSR review.
>>> 
>>> >    should this functionality be housed in the InvocationHandler interface rather than the Proxy class? If I understand the
>>> >    intended usage of the new method, it should only be done in an InvocationHandler.
>>> 
>>> The primary usage of this new method is InvocationHandler. I agree that the new API should be defined in
>>> InvocationHandler.
>> 
>> If it is a public static method, then Proxy or InvocationHandler are just a namespace for it. From discoverability
>> perspective, either one is a good place I think. One point for moving the method into the InvocationHandler is the fact
>> that Proxy is a class and classes "inherit" static methods too while interfaces don't. It would be impossible to create
>> a dynamic proxy for an interface with a method having the same signature as the Proxy.invokeDefaultMethod static method
>> since such proxy class would need to implement an instance method having the same signature as its superclass static
>> method.  If interfaces supported protected default methods, then it would make sense to be a protected default method
>> in InvocationHandler. Such instance method could additionally enforce two things:
>> - that it is called from code comprising InvocationHandler
>> - that the proxy instance passed to that method is in fact backed by the invocation handler instance that is the target
>>   of that call by checking that in the method.
>> 
>> But we don't have protected default methods in interfaces (yet). So a static method it must be.
>> 
>> I was thinking about what such public static method allows and whether that presents a problem (perhaps security
>> related) and came to the conclusion that it does not allow anything that normal Java code would not allow except for
>> one thing (see below). From the 1st glance it would seem that it allows any code to call super default method on any
>> Proxy instance, but what does that mean exactly? The same effect can be achieved by creating a special hand-made proxy
>> class implementing all the interfaces that the dynamic Proxy class implements:  class HandmadeProxy implements I1, I2,
>> ... {
>>     private final Proxy targetProxy;
>>     HandmadeProxy(Proxy targetProxy) { this.targetProxy = targetProxy }
>>     // implement all non-default methods of I1, I2, ... by delegating to targetProxy
>>     // example for I1.m()
>>     public void m() {
>>         ((I1)targetProxy).m();
>>     }
>> }
>> 
>> ...and then using such class to invoke some default method on an instance of the Proxy:
>> 
>> Proxy proxy = ...
>> new HandmadeProxy(proxy).someDefaultMethod();
>> 
>> So such apparently powerful capability does not represent a problem. One additional thing is possible though:
>> 
>>>> Does the current spec handle a case like interface A declares a default method m, interface B extends A and separately
>>>> interface B declare a default method m.
>>>
>>> If a proxy instance implements both A and B, `invokeDefaultMethod(o, A.class.getMethod("m"), params)` will invoke
>>> `A::m`.
>> 
>> This is true since lookup.findSpecial() allows such thing (and I assume equivalent bytecode does too). The Java
>> language (compiler) OTOH does not allow calling A.super.m() from a class implementing both A and B when B extends A and
>> both A and B declare default method m():
>>     interface A {
>>         default void m() { }
>>     }
>> 
>>     interface B extends A {
>>         default void m() { }
>>     }
>> 
>>     static class C implements A, B {
>>         public void m() {
>>             A.super.m();
>>         }
>>     }
>> 
>> java: bad type qualifier A in default super call
>>   redundant interface A is extended by B
>> 
>> I'm in favour of following the bytecode (method handles) behaviour here even though it allows more than Java language
>> allows.
>
> I'm thinking a static method `InvocationHandler::invokeDefaultMethod` and no new method in `Proxy` class.   Proxy class
> will still have the package-private methods for `InvocationHandler::invokeDefaultMethod` implementation to use.
> It may seem to be cleaner to be a default method at the use site called from InvocationHandler.  However, it's not
> really a method meant to be overridden.

Thanks for the input Peter.

> I'm in favour of following the bytecode (method handles) behaviour here even though it allows more than Java language
> allows.

The proposal intends to follow the bytecode behavior.   I can clarify in the javadoc.

-------------

PR: https://git.openjdk.java.net/jdk/pull/313


More information about the core-libs-dev mailing list