----- Original Message ----- > From: "Johannes Kuhn" <i...@j-kuhn.de> > To: "Alan Bateman" <alan.bate...@oracle.com>, "core-libs-dev" > <core-libs-dev@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