From duke at openjdk.java.net Sun Apr 17 16:24:13 2022 From: duke at openjdk.java.net (liach) Date: Sun, 17 Apr 2022 16:24:13 GMT Subject: RFR: JDK-8242888: Convert dynamic proxy to hidden classes Message-ID: <-NKQ4V2UzhsLM3cxc-KtBk7Po9HfBKM5xgc-IxlMjWg=.cac6bf36-b71e-415f-b7d2-fb1d481a5490@github.com> 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. ------------- Commit messages: - Change proxy serialization to work with hidden classes (require spec update) - Formatting - Move to hidden class and methods in class data - Implement anchors and remove proxyClassLookup factory Changes: https://git.openjdk.java.net/jdk/pull/8278/files Webrev: https://webrevs.openjdk.java.net/?repo=jdk&pr=8278&range=00 Issue: https://bugs.openjdk.java.net/browse/JDK-8242888 Stats: 400 lines in 6 files changed: 122 ins; 222 del; 56 mod Patch: https://git.openjdk.java.net/jdk/pull/8278.diff Fetch: git fetch https://git.openjdk.java.net/jdk pull/8278/head:pull/8278 PR: https://git.openjdk.java.net/jdk/pull/8278 From prappo at openjdk.java.net Thu Apr 21 19:35:56 2022 From: prappo at openjdk.java.net (Pavel Rappo) Date: Thu, 21 Apr 2022 19:35:56 GMT Subject: RFR: 8285396: Do not fill in the stacktrace of an internal exception Message-ID: Sometimes an exception is retrofitted into control flow to interrupt it in a way that it wasn't originally designed to be interrupted. Such an exception is an implementation detail. Once the exception is caught internally, it is discarded. An exception has a stacktrace. Filling in a stacktrace is not free. Filling in a stacktrace that won't be used seems like a waste. ------------- Commit messages: - Update copyright years - Initial commit Changes: https://git.openjdk.java.net/jdk/pull/8347/files Webrev: https://webrevs.openjdk.java.net/?repo=jdk&pr=8347&range=00 Issue: https://bugs.openjdk.java.net/browse/JDK-8285396 Stats: 15 lines in 6 files changed: 4 ins; 0 del; 11 mod Patch: https://git.openjdk.java.net/jdk/pull/8347.diff Fetch: git fetch https://git.openjdk.java.net/jdk pull/8347/head:pull/8347 PR: https://git.openjdk.java.net/jdk/pull/8347 From jjg at openjdk.java.net Thu Apr 21 20:37:24 2022 From: jjg at openjdk.java.net (Jonathan Gibbons) Date: Thu, 21 Apr 2022 20:37:24 GMT Subject: RFR: 8285396: Do not fill in the stacktrace of an internal exception In-Reply-To: References: Message-ID: On Thu, 21 Apr 2022 19:28:08 GMT, Pavel Rappo wrote: > Sometimes an exception is retrofitted into control flow to interrupt it in a way that it wasn't originally designed to be interrupted. Such an exception is an implementation detail. Once the exception is caught internally, it is discarded. > > An exception has a stacktrace. Filling in a stacktrace is not free. Filling in a stacktrace that won't be used seems like a waste. The changes for the `UncheckedIOException` wrappers look OK, but might be even better if the code properly unwrapped the wrapper and simply rethrew the underlying cause. For example, replace } catch (UncheckedIOException ex) { throw new IOException(ex.getMessage(), ex); with } catch (UncheckedIOException ex) { throw ex.getCause(); ``` For the `TreePath` and `DocTreePath` `Result` exceptions, a better solution would be to add an opt-in short-circuiting mechanism info the scanner's `scanAndReduce` method, to avoid calling additional calls of `scan` once some condition has been met, like a non-null result. This would completely avoid the need to throw an exception. ------------- Changes requested by jjg (Reviewer). PR: https://git.openjdk.java.net/jdk/pull/8347 From prappo at openjdk.java.net Thu Apr 21 22:14:27 2022 From: prappo at openjdk.java.net (Pavel Rappo) Date: Thu, 21 Apr 2022 22:14:27 GMT Subject: RFR: 8285396: Do not fill in the stacktrace of an internal exception In-Reply-To: References: Message-ID: <_9K5xdhsNavR4L-fOFRWim_ve_KQOivBOFz4Me09U1A=.e451940a-4c6c-4ace-9974-6c82c46157c1@github.com> On Thu, 21 Apr 2022 20:34:31 GMT, Jonathan Gibbons wrote: > The changes for the `UncheckedIOException` wrappers look OK, but might be even better if the code properly unwrapped the wrapper and simply rethrew the underlying cause. For example, > > replace > > ``` > } catch (UncheckedIOException ex) { > throw new IOException(ex.getMessage(), ex); > ``` > > with > > ``` > } catch (UncheckedIOException ex) { > throw ex.getCause(); > ``` > Sounds reasonable; I'll have a look at it. > For the `TreePath` and `DocTreePath` `Result` exceptions, a better solution would be to add an opt-in short-circuiting mechanism info the scanner's `scanAndReduce` method, to avoid calling additional calls of `scan` once some condition has been met, like a non-null result. This would completely avoid the need to throw an exception. I think that we discussed (some of) that before in the comment section of another issue: JDK-8267690. You might want to re-read it. What this PR proposes is to apply a band-aid until we're ready to treat the issue properly. The treatment you are suggesting is proper, but heavyweight in terms of the process: it involves an API change, which requires a CSR. ------------- PR: https://git.openjdk.java.net/jdk/pull/8347 From prappo at openjdk.java.net Thu Apr 21 23:28:16 2022 From: prappo at openjdk.java.net (Pavel Rappo) Date: Thu, 21 Apr 2022 23:28:16 GMT Subject: RFR: 8285396: Do not fill in the stacktrace of an internal exception [v2] In-Reply-To: References: Message-ID: > Sometimes an exception is retrofitted into control flow to interrupt it in a way that it wasn't originally designed to be interrupted. Such an exception is an implementation detail. Once the exception is caught internally, it is discarded. > > An exception has a stacktrace. Filling in a stacktrace is not free. Filling in a stacktrace that won't be used seems like a waste. Pavel Rappo has updated the pull request incrementally with one additional commit since the last revision: Address feedback ------------- Changes: - all: https://git.openjdk.java.net/jdk/pull/8347/files - new: https://git.openjdk.java.net/jdk/pull/8347/files/1c69f0aa..a42a6626 Webrevs: - full: https://webrevs.openjdk.java.net/?repo=jdk&pr=8347&range=01 - incr: https://webrevs.openjdk.java.net/?repo=jdk&pr=8347&range=00-01 Stats: 17 lines in 2 files changed: 1 ins; 16 del; 0 mod Patch: https://git.openjdk.java.net/jdk/pull/8347.diff Fetch: git fetch https://git.openjdk.java.net/jdk pull/8347/head:pull/8347 PR: https://git.openjdk.java.net/jdk/pull/8347 From prappo at openjdk.java.net Thu Apr 21 23:28:16 2022 From: prappo at openjdk.java.net (Pavel Rappo) Date: Thu, 21 Apr 2022 23:28:16 GMT Subject: RFR: 8285396: Do not fill in the stacktrace of an internal exception [v2] In-Reply-To: <_9K5xdhsNavR4L-fOFRWim_ve_KQOivBOFz4Me09U1A=.e451940a-4c6c-4ace-9974-6c82c46157c1@github.com> References: <_9K5xdhsNavR4L-fOFRWim_ve_KQOivBOFz4Me09U1A=.e451940a-4c6c-4ace-9974-6c82c46157c1@github.com> Message-ID: On Thu, 21 Apr 2022 22:10:36 GMT, Pavel Rappo wrote: > The changes for the `UncheckedIOException` wrappers look OK, but might be even better if the code properly unwrapped the wrapper and simply rethrew the underlying cause. For example, > > replace > > ``` > } catch (UncheckedIOException ex) { > throw new IOException(ex.getMessage(), ex); > ``` > > with > > ``` > } catch (UncheckedIOException ex) { > throw ex.getCause(); > ``` Thanks for directing my attention to these two exceptions! I think I lost my marbles for a good few minutes when decided to change them like that. I must've been thinking about something else. Those two exceptions are used as intended: for exceptional circumstances. So their stacktraces have diagnostic value. I don't think we should re-throw the cause, because the stacktrace might look confusing. The only thing we could improve here is to replace ad-hoc `UncheckedIOException` with standard `java.io.UncheckedIOException`, which appeared much later in the codebase. Please have a look at a42a66268f9d2175d212e6a5cba52fd11ec5332b and tell me what you think. ------------- PR: https://git.openjdk.java.net/jdk/pull/8347 From prappo at openjdk.java.net Mon Apr 25 20:45:57 2022 From: prappo at openjdk.java.net (Pavel Rappo) Date: Mon, 25 Apr 2022 20:45:57 GMT Subject: RFR: 8285396: Do not fill in the stacktrace of an internal exception [v2] In-Reply-To: References: Message-ID: <2WpSRxB0LRATLpvvrHT5McWaHa2e19_wxeDccoemlYA=.6a03b909-eab2-4e30-bb60-bbfb520f78fb@github.com> On Thu, 21 Apr 2022 23:28:16 GMT, Pavel Rappo wrote: >> Sometimes an exception is retrofitted into control flow to interrupt it in a way that it wasn't originally designed to be interrupted. Such an exception is an implementation detail. Once the exception is caught internally, it is discarded. >> >> An exception has a stacktrace. Filling in a stacktrace is not free. Filling in a stacktrace that won't be used seems like a waste. > > Pavel Rappo has updated the pull request incrementally with one additional commit since the last revision: > > Address feedback I'm closing this PR because we decided to address the stacktrace issue by getting rid of exceptions altogether in another PR: https://github.com/openjdk/jdk/pull/8369. However, I will file an issue to retrofit `(Doc)Pretty` with `java.io.UncheckedIOException`. ------------- PR: https://git.openjdk.java.net/jdk/pull/8347 From prappo at openjdk.java.net Mon Apr 25 20:45:58 2022 From: prappo at openjdk.java.net (Pavel Rappo) Date: Mon, 25 Apr 2022 20:45:58 GMT Subject: Withdrawn: 8285396: Do not fill in the stacktrace of an internal exception In-Reply-To: References: Message-ID: On Thu, 21 Apr 2022 19:28:08 GMT, Pavel Rappo wrote: > Sometimes an exception is retrofitted into control flow to interrupt it in a way that it wasn't originally designed to be interrupted. Such an exception is an implementation detail. Once the exception is caught internally, it is discarded. > > An exception has a stacktrace. Filling in a stacktrace is not free. Filling in a stacktrace that won't be used seems like a waste. This pull request has been closed without being integrated. ------------- PR: https://git.openjdk.java.net/jdk/pull/8347 From duke at openjdk.java.net Tue Apr 26 03:12:55 2022 From: duke at openjdk.java.net (duke) Date: Tue, 26 Apr 2022 03:12:55 GMT Subject: Withdrawn: 8282160: JShell circularly-required classes cannot be defined In-Reply-To: References: Message-ID: On Mon, 28 Feb 2022 16:08:29 GMT, Jan Lahoda wrote: > Consider JShell snippets like: > > jshell> class B { > C c; > public void run() { > } > } > jshell> class C extends B { > public void run() { > } > } > > > When the first snippet is processed, it cannot be fully compiled, because `C` is missing. When the second snippet is processed, it is first processed separately, but it will turn out it needs `B` to be defined, and that there are no errors in `C` except resolution errors, and JShell will process both the snippets together, which will pass. > > If the second snippet is changed to: > > jshell> class C extends B { > @Override > public void run() { > } > } > > > then when processing `C`, there will be error: "method does not override or implement a method from a supertype" (in addition to the "`B` does not exist"). But that error is not considered a resolution error by JShell. > > The proposal here is to ignore the "does not override" errors and join the `C` and `B` snippet processing. An alternative would be to not produce the error when there are erroneous supertypes, but that turns out to be tricky when the error is not in the direct supertype. So the proposal is to tweak JShell for now. This pull request has been closed without being integrated. ------------- PR: https://git.openjdk.java.net/jdk/pull/7635 From vromero at openjdk.java.net Tue Apr 26 17:14:05 2022 From: vromero at openjdk.java.net (Vicente Romero) Date: Tue, 26 Apr 2022 17:14:05 GMT Subject: RFR: 8282160: JShell circularly-required classes cannot be defined In-Reply-To: References: Message-ID: On Mon, 28 Feb 2022 16:08:29 GMT, Jan Lahoda wrote: > Consider JShell snippets like: > > jshell> class B { > C c; > public void run() { > } > } > jshell> class C extends B { > public void run() { > } > } > > > When the first snippet is processed, it cannot be fully compiled, because `C` is missing. When the second snippet is processed, it is first processed separately, but it will turn out it needs `B` to be defined, and that there are no errors in `C` except resolution errors, and JShell will process both the snippets together, which will pass. > > If the second snippet is changed to: > > jshell> class C extends B { > @Override > public void run() { > } > } > > > then when processing `C`, there will be error: "method does not override or implement a method from a supertype" (in addition to the "`B` does not exist"). But that error is not considered a resolution error by JShell. > > The proposal here is to ignore the "does not override" errors and join the `C` and `B` snippet processing. An alternative would be to not produce the error when there are erroneous supertypes, but that turns out to be tricky when the error is not in the direct supertype. So the proposal is to tweak JShell for now. lgtm ------------- PR: https://git.openjdk.java.net/jdk/pull/7635 From vromero at openjdk.java.net Tue Apr 26 17:27:14 2022 From: vromero at openjdk.java.net (Vicente Romero) Date: Tue, 26 Apr 2022 17:27:14 GMT Subject: RFR: 8282160: JShell circularly-required classes cannot be defined In-Reply-To: References: Message-ID: On Mon, 28 Feb 2022 16:08:29 GMT, Jan Lahoda wrote: > Consider JShell snippets like: > > jshell> class B { > C c; > public void run() { > } > } > jshell> class C extends B { > public void run() { > } > } > > > When the first snippet is processed, it cannot be fully compiled, because `C` is missing. When the second snippet is processed, it is first processed separately, but it will turn out it needs `B` to be defined, and that there are no errors in `C` except resolution errors, and JShell will process both the snippets together, which will pass. > > If the second snippet is changed to: > > jshell> class C extends B { > @Override > public void run() { > } > } > > > then when processing `C`, there will be error: "method does not override or implement a method from a supertype" (in addition to the "`B` does not exist"). But that error is not considered a resolution error by JShell. > > The proposal here is to ignore the "does not override" errors and join the `C` and `B` snippet processing. An alternative would be to not produce the error when there are erroneous supertypes, but that turns out to be tricky when the error is not in the direct supertype. So the proposal is to tweak JShell for now. looks good ------------- Marked as reviewed by vromero (Reviewer). PR: https://git.openjdk.java.net/jdk/pull/7635