RFR: JDK-8242888: Convert dynamic proxy to hidden classes
Remi Forax
forax at univ-mlv.fr
Mon Apr 18 11:09:30 UTC 2022
----- Original Message -----
> From: "Johannes Kuhn" <info at j-kuhn.de>
> To: "Alan Bateman" <Alan.Bateman at oracle.com>, "core-libs-dev" <core-libs-dev at openjdk.java.net>
> Sent: Monday, April 18, 2022 12:53:45 PM
> Subject: Re: RFR: JDK-8242888: Convert dynamic proxy to hidden classes
> On 18-Apr-22 9:36, Alan Bateman wrote:
>> On 17/04/2022 17:24, liach wrote:
>>> Convert dynamic proxies to hidden classes. Modifies the serialization
>>> of proxies (requires change in "Java Object Serialization
>>> Specification"). Makes the proxies hidden in stack traces. Removes
>>> duplicate logic in proxy building.
>>>
>>> The main compatibility changes and their rationales are:
>>> 1. Modification to the serialization specification: In the "An
>>> instance of the class is allocated... The contents restored
>>> appropriately" section, I propose explicitly state that handling of
>>> proxies are unspecified as to allow implementation freedom, though
>>> I've seen deliberate attempts for proxies to implement interfaces with
>>> `readResolve` in order to control their serialization behavior.
>>> - This is for the existing generated constructor accessor is
>>> bytecode-based, which cannot refer to hidden classes.
>>> - An alternative is to preserve the behavior, where the
>>> serialization constructor calls `invokespecial` on the closest
>>> serializable superclass' no-arg constructor, like in #1830 by @DasBrain.
>>> - My rationale against preservation is such super calls are unsafe
>>> and should be discouraged in the long term. Calling the existing
>>> constructor with a dummy argument, as in my implementation, would be
>>> more safe.
>>> 2. The disappearance of proxies in stack traces.
>>> - Same behavior exists in lambda expressions: For instance, in
>>> `((Runnable) () -> { throw new Error(); }).run();`, the `run` method,
>>> implemented by the lambda, will not appear in the stack trace, and
>>> isn't too problematic.
>>
>> It's great that you have time to experiment in this area but just to set
>> expectations that it will likely require significant discussion and
>> maybe prototyping of alternatives. It suspect the Reviewer effort will
>> end up being many times the effort required to do the actual work
>> because of the compatibility and security issues that will need to be
>> worked through.
>>
>> I think you need to add non-discoverability to the list of compatibility
>> issues. Do we know for sure that there aren't frameworks and libraries
>> that use Class.forName on proxy classes? We've had issues in the past
>> with changes in this area.
>>
>> It's too early to say but it might be that the compatibility risks may
>> nudge this one into creating a new API.
>>
>> -Alan.
>>
>>
>>
>
> Proxies will have to be rethought at some future point - wrt Valhalla.
>
> The current specification says:
>
> > A proxy class implements exactly the interfaces specified at its
> creation, in the same order. Invoking getInterfaces on its Class object
> will return an array containing the same list of interfaces (in the
> order specified at its creation), [...]
>
> In the current design Valhalla will add two interfaces - IdentityObject
> and ValueObject (afaik). One of them have to be implemented as well.
> Also, because the superclass is java.lang.reflect.Proxy, and that class
> has a protected final field, it can currently not implement ValueObject.
Recently, we (the Valhalla EG) have decided that IdentityObject/ValueObject were not the right way to represent identity and value class.
So no problem anymore on that side.
>
> An other thing are annotations - currently they are implemented using
> Proxies. This implementation detail surfaces when serializing an
> annotation. Other implementation strategies are possible - for example
> spinning a record at runtime.
> But this leads to the question - how can one migrate away from
> serialized proxies in a compatible way?
>
> In the end - a lot of stuff in the JDK depends on Proxies, and their
> limitations now begins to surface.
>
> A new API may not be a bad idea. :)
Yes !
And we can leverage invokedynamic/method handles to avoid boxing/ bad perf.
The idea is that first time an implementation of an abstract method is required, an object (implementing an interface similar to InvocationHandler) acting as a bootstrap method is called to provide a method handle that will be used as implementation.
see https://github.com/forax/hidden_proxy for a prototype of that idea.
>
> - Johannes
Rémi
More information about the core-libs-dev
mailing list