----- Original Message ----- > From: "liach" <d...@openjdk.java.net> > To: "core-libs-dev" <core-libs-...@openjdk.java.net>, "security-dev" > <security-dev@openjdk.java.net> > Sent: Monday, April 18, 2022 10:01:39 PM > Subject: Re: RFR: JDK-8242888: Convert dynamic proxy to hidden classes
> On Sun, 17 Apr 2022 16:17:30 GMT, liach <d...@openjdk.java.net> 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. >> >> A summary of the rest of the changes: >> 1. Merged the two passes of determining module and package of the proxy into >> one. This reduced a lot of code and allowed anchor class (for hidden class >> creation) selection be done together as well. >> 2. Exposed internal API for obtaining a full-privileged lookup to the rest of >> `java.base`. This API is intended for implementation of legacy (pre >> `MethodHandles.Lookup`) caller sensitive public APIs so they don't need more >> complex tricks to obtain proper permissions as lookups. >> 3. Implements [8229959](https://bugs.openjdk.java.net/browse/JDK-8229959): >> passes methods computed by proxy generator as class data to the hidden proxy >> class to reduce generated proxy class size and improve performance. >> >> In addition, since this change is somewhat large, should we keep the old >> proxy >> generator as well and have it toggled through a command-line flag (like the >> old >> v49 proxy generator or the old reflection implementation)? >> >> Please feel free to comment or review. This change definitely requires a CSR, >> but I have yet to determine what specifications should be changed. > > I strongly recommend a new API over revamping `Proxy` itself. > https://github.com/forax/hidden_proxy would be a good prototype that serves > most needs of the current Proxy API (except a few, like invoking default > superinterface method). The third parameter of defineProxy() is a lambda which is called for each method that can be overriden, either toString/equals/hashCode but also any default methods, if the lambda return true, the method is overriden, otherwise the default implementation is used. > With hidden classes, I don't see much value in leaving > the new API's produced instance in separate modules; what we have for hidden > classes should be fine for the most part. > > Imo the main obstacle is still the handling of serialization. The annotations > are serializable, but currently hidden classes do not work with serialization > at all and must use `writeReplace` and `readResolve`. And how to migrate > annotations off proxies without breaking serialization is still a question as > well. Maybe we can upgrade invocation handlers to allow them to declare custom > `readResolve` logic for the proxy to facilitate migration away. How the new > API > will treat serialization is still undetermined. yes, i suppose that like with lambdas, we need a special overload of defineProxy that automatically implements writeReplace() and use a specific class SerializableProxy (mirroring how SerializableLambda works). > > ------------- > > PR: https://git.openjdk.java.net/jdk/pull/8278