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