From asotona at openjdk.org Mon Jan 2 17:06:18 2023 From: asotona at openjdk.org (Adam Sotona) Date: Mon, 2 Jan 2023 17:06:18 GMT Subject: RFR: 8296789: -completion in jshell fails to expose synthetic bridge methods Message-ID: Jshell does not propose completion for members declared in inaccessible parent classes (for example AbstractStringBuilder). This patch fixes the completion in SourceCodeAnalysisImpl using MethodSymbols and VarSymbols clones with altered enclosing elements. For documentation purpose (print of the enclosing classes) the original enclosing element is restored. The patch also includes new CompletionSuggestionTest::testPerentMembers Please review. Thanks, Adam ------------- Commit messages: - 8296789: -completion in jshell fails to expose synthetic bridge methods Changes: https://git.openjdk.org/jdk/pull/11814/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=11814&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8296789 Stats: 24 lines in 2 files changed: 19 ins; 0 del; 5 mod Patch: https://git.openjdk.org/jdk/pull/11814.diff Fetch: git fetch https://git.openjdk.org/jdk pull/11814/head:pull/11814 PR: https://git.openjdk.org/jdk/pull/11814 From duke at openjdk.org Fri Jan 6 02:45:18 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Fri, 6 Jan 2023 02:45:18 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor Message-ID: This PR adds a new lint warning category `this-escape`. It also adds `@SuppressWarnings` annotations as needed to the JDK itself to allow the JDK to continue to compile with `-Xlint:all`. A 'this' escape warning is generated for a constructor `A()` in a class `A` when the compiler detects that the following situation is _in theory possible:_ * Some subclass `B extends A` exists, and `B` is defined in a separate source file (i.e., compilation unit) * Some constructor `B()` of `B` invokes `A()` as its superclass constructor * During the execution of `A()`, some non-static method of `B.foo()` could get invoked, perhaps indirectly In the above scenario, `B.foo()` would execute before `A()` has returned and before `B()` has performed any initialization. To the extent `B.foo()` accesses any fields of `B` - all of which are still uninitialized - it is likely to function incorrectly. Note, when determining if a 'this' escape is possible, the compiler makes no assumptions about code outside of the current compilation unit. It doesn't look outside of the current source file to see what might actually happen when a method is invoked. It does follow method and constructors within the current compilation unit, and applies a simplified union-of-all-possible-branches data flow analysis to see where 'this' could end up. >From my review, virtually all of the warnings generated in the various JDK modules are valid warnings in the sense that a 'this' escape, as defined above, is really and truly possible. However, that doesn't imply that any bugs were found within the JDK - only that the possibility of a certain type of bug exists if certain superclass constructors are used by someone, somewhere, someday. For several "popular" classes, this PR also adds `@implNote`'s to the offending constructors so that subclass implementors are made aware of the threat. For one example, `TreeMap(Map)` invokes `putAll()` and `put()`. More details and a couple of motivating examples are given in an included [doc file](https://github.com/archiecobbs/jdk/blob/ThisEscape/src/java.base/share/classes/java/lang/doc-files/ThisEscape.html) that these `@implNote`'s link to. See also the recent thread on `amber-dev` for some background. Ideally, over time the owners of the various modules would review their `@SuppressWarnings("this-escape")` annotations and determine which other constructors also warranted such an `@implNote`. Because of all the`@SuppressWarnings` annotations, this PR touches a bunch of different JDK modules. My apologies for that. Adding these annotations was determined to be the more conservative approach, as compared to just excepting `this-escape` from various module builds globally. **Patch Navigation Guide** * Non-trivial compiler changes: * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java` * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java` * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java` * `src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java` * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java` * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties` * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties` * Javadoc additions of `@implNote`: * `src/java.base/share/classes/java/io/PipedReader.java` * `src/java.base/share/classes/java/io/PipedWriter.java` * `src/java.base/share/classes/java/lang/Throwable.java` * `src/java.base/share/classes/java/util/ArrayDeque.java` * `src/java.base/share/classes/java/util/EnumMap.java` * `src/java.base/share/classes/java/util/HashSet.java` * `src/java.base/share/classes/java/util/Hashtable.java` * `src/java.base/share/classes/java/util/LinkedList.java` * `src/java.base/share/classes/java/util/TreeMap.java` * `src/java.base/share/classes/java/util/TreeSet.java` * New unit tests * `test/langtools/tools/javac/warnings/ThisEscape/*.java` * **Everything else** is just adding `@SuppressWarnings("this-escape")` ------------- Commit messages: - Remove trailing whitespace. - Some documentation tweaks. - Treat method references like the equivalent lambda. - Fix bug where initializers could generate duplicate warnings. - Javadoc fix. - Add ThisEscape.html doc note and link the new @implNote's to it. - Add more @SuppressWarnings("this-escape") annotations. - Add more @SuppressWarnings("this-escape") annotations. - Add more @SuppressWarnings("this-escape") annotations. - Add more @SuppressWarnings("this-escape") annotations. - ... and 38 more: https://git.openjdk.org/jdk/compare/c6588d5b...9c162283 Changes: https://git.openjdk.org/jdk/pull/11874/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=11874&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8015831 Stats: 4326 lines in 1285 files changed: 4259 ins; 3 del; 64 mod Patch: https://git.openjdk.org/jdk/pull/11874.diff Fetch: git fetch https://git.openjdk.org/jdk pull/11874/head:pull/11874 PR: https://git.openjdk.org/jdk/pull/11874 From dholmes at openjdk.org Fri Jan 6 04:51:00 2023 From: dholmes at openjdk.org (David Holmes) Date: Fri, 6 Jan 2023 04:51:00 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor In-Reply-To: References: Message-ID: On Fri, 6 Jan 2023 02:20:53 GMT, Archie L. Cobbs wrote: > This PR adds a new lint warning category `this-escape`. > > It also adds `@SuppressWarnings` annotations as needed to the JDK itself to allow the JDK to continue to compile with `-Xlint:all`. > > A 'this' escape warning is generated for a constructor `A()` in a class `A` when the compiler detects that the following situation is _in theory possible:_ > * Some subclass `B extends A` exists, and `B` is defined in a separate source file (i.e., compilation unit) > * Some constructor `B()` of `B` invokes `A()` as its superclass constructor > * During the execution of `A()`, some non-static method of `B.foo()` could get invoked, perhaps indirectly > > In the above scenario, `B.foo()` would execute before `A()` has returned and before `B()` has performed any initialization. To the extent `B.foo()` accesses any fields of `B` - all of which are still uninitialized - it is likely to function incorrectly. > > Note, when determining if a 'this' escape is possible, the compiler makes no assumptions about code outside of the current compilation unit. It doesn't look outside of the current source file to see what might actually happen when a method is invoked. It does follow method and constructors within the current compilation unit, and applies a simplified union-of-all-possible-branches data flow analysis to see where 'this' could end up. > > From my review, virtually all of the warnings generated in the various JDK modules are valid warnings in the sense that a 'this' escape, as defined above, is really and truly possible. However, that doesn't imply that any bugs were found within the JDK - only that the possibility of a certain type of bug exists if certain superclass constructors are used by someone, somewhere, someday. > > For several "popular" classes, this PR also adds `@implNote`'s to the offending constructors so that subclass implementors are made aware of the threat. For one example, `TreeMap(Map)` invokes `putAll()` and `put()`. > > More details and a couple of motivating examples are given in an included [doc file](https://github.com/archiecobbs/jdk/blob/ThisEscape/src/java.base/share/classes/java/lang/doc-files/ThisEscape.html) that these `@implNote`'s link to. See also the recent thread on `amber-dev` for some background. > > Ideally, over time the owners of the various modules would review their `@SuppressWarnings("this-escape")` annotations and determine which other constructors also warranted such an `@implNote`. > > Because of all the`@SuppressWarnings` annotations, this PR touches a bunch of different JDK modules. My apologies for that. Adding these annotations was determined to be the more conservative approach, as compared to just excepting `this-escape` from various module builds globally. > > **Patch Navigation Guide** > > * Non-trivial compiler changes: > * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties` > > * Javadoc additions of `@implNote`: > > * `src/java.base/share/classes/java/io/PipedReader.java` > * `src/java.base/share/classes/java/io/PipedWriter.java` > * `src/java.base/share/classes/java/lang/Throwable.java` > * `src/java.base/share/classes/java/util/ArrayDeque.java` > * `src/java.base/share/classes/java/util/EnumMap.java` > * `src/java.base/share/classes/java/util/HashSet.java` > * `src/java.base/share/classes/java/util/Hashtable.java` > * `src/java.base/share/classes/java/util/LinkedList.java` > * `src/java.base/share/classes/java/util/TreeMap.java` > * `src/java.base/share/classes/java/util/TreeSet.java` > > * New unit tests > * `test/langtools/tools/javac/warnings/ThisEscape/*.java` > > * **Everything else** is just adding `@SuppressWarnings("this-escape")` Hi Archie, The associated JBS issue has been dormant for 6+ years and this is a very intrusive change affecting many, many files. Has the resurrection of this project previously been discussed somewhere? ------------- PR: https://git.openjdk.org/jdk/pull/11874 From alanb at openjdk.org Fri Jan 6 07:53:54 2023 From: alanb at openjdk.org (Alan Bateman) Date: Fri, 6 Jan 2023 07:53:54 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor In-Reply-To: References: Message-ID: On Fri, 6 Jan 2023 02:20:53 GMT, Archie L. Cobbs wrote: > This PR adds a new lint warning category `this-escape`. > > It also adds `@SuppressWarnings` annotations as needed to the JDK itself to allow the JDK to continue to compile with `-Xlint:all`. > > A 'this' escape warning is generated for a constructor `A()` in a class `A` when the compiler detects that the following situation is _in theory possible:_ > * Some subclass `B extends A` exists, and `B` is defined in a separate source file (i.e., compilation unit) > * Some constructor `B()` of `B` invokes `A()` as its superclass constructor > * During the execution of `A()`, some non-static method of `B.foo()` could get invoked, perhaps indirectly > > In the above scenario, `B.foo()` would execute before `A()` has returned and before `B()` has performed any initialization. To the extent `B.foo()` accesses any fields of `B` - all of which are still uninitialized - it is likely to function incorrectly. > > Note, when determining if a 'this' escape is possible, the compiler makes no assumptions about code outside of the current compilation unit. It doesn't look outside of the current source file to see what might actually happen when a method is invoked. It does follow method and constructors within the current compilation unit, and applies a simplified union-of-all-possible-branches data flow analysis to see where 'this' could end up. > > From my review, virtually all of the warnings generated in the various JDK modules are valid warnings in the sense that a 'this' escape, as defined above, is really and truly possible. However, that doesn't imply that any bugs were found within the JDK - only that the possibility of a certain type of bug exists if certain superclass constructors are used by someone, somewhere, someday. > > For several "popular" classes, this PR also adds `@implNote`'s to the offending constructors so that subclass implementors are made aware of the threat. For one example, `TreeMap(Map)` invokes `putAll()` and `put()`. > > More details and a couple of motivating examples are given in an included [doc file](https://github.com/archiecobbs/jdk/blob/ThisEscape/src/java.base/share/classes/java/lang/doc-files/ThisEscape.html) that these `@implNote`'s link to. See also the recent thread on `amber-dev` for some background. > > Ideally, over time the owners of the various modules would review their `@SuppressWarnings("this-escape")` annotations and determine which other constructors also warranted such an `@implNote`. > > Because of all the`@SuppressWarnings` annotations, this PR touches a bunch of different JDK modules. My apologies for that. Adding these annotations was determined to be the more conservative approach, as compared to just excepting `this-escape` from various module builds globally. > > **Patch Navigation Guide** > > * Non-trivial compiler changes: > * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties` > > * Javadoc additions of `@implNote`: > > * `src/java.base/share/classes/java/io/PipedReader.java` > * `src/java.base/share/classes/java/io/PipedWriter.java` > * `src/java.base/share/classes/java/lang/Throwable.java` > * `src/java.base/share/classes/java/util/ArrayDeque.java` > * `src/java.base/share/classes/java/util/EnumMap.java` > * `src/java.base/share/classes/java/util/HashSet.java` > * `src/java.base/share/classes/java/util/Hashtable.java` > * `src/java.base/share/classes/java/util/LinkedList.java` > * `src/java.base/share/classes/java/util/TreeMap.java` > * `src/java.base/share/classes/java/util/TreeSet.java` > > * New unit tests > * `test/langtools/tools/javac/warnings/ThisEscape/*.java` > > * **Everything else** is just adding `@SuppressWarnings("this-escape")` This looks like a very useful lint warning to have but this PR is unwieldy. If you haven't done so already then you probably should socialize on compiler-dev and get agreement on the semantics and other details. I think you will also need to separate the addition of the lint warning from the changes to the wider JDK. It might be okay to add the feature but have it disabled for the JDK build initially. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From jlahoda at openjdk.org Fri Jan 6 09:21:00 2023 From: jlahoda at openjdk.org (Jan Lahoda) Date: Fri, 6 Jan 2023 09:21:00 GMT Subject: RFR: 8296454: System.console() shouldn't return null in jshell Message-ID: Implements `System.console()` for JShell, based on JDK-8295803. It is only supported for (supported) remote agents. When a snippet calls a Console method in the remote agent, a request to perform the task is sent to the main process, performed, and the outcomes are sent back to the remote agent, and returned from the Console method. Please also review the CSR for the newly added API: https://bugs.openjdk.org/browse/JDK-8299680 ------------- Commit messages: - Cleanup. - Cleanup. - Fixing test. - Adding support for Charset. - Test when there's no JShellConsole. - Buffering output. - Improving synchronizations and fixing sending of many requests from the agent into the main process. - Merge branch 'master' into JDK-8296454b - 8296454: System.console() shouldn't return null in jshell Changes: https://git.openjdk.org/jdk/pull/11695/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=11695&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8296454 Stats: 1001 lines in 15 files changed: 954 ins; 0 del; 47 mod Patch: https://git.openjdk.org/jdk/pull/11695.diff Fetch: git fetch https://git.openjdk.org/jdk pull/11695/head:pull/11695 PR: https://git.openjdk.org/jdk/pull/11695 From duke at openjdk.org Fri Jan 6 14:51:54 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Fri, 6 Jan 2023 14:51:54 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor In-Reply-To: References: Message-ID: On Fri, 6 Jan 2023 04:48:27 GMT, David Holmes wrote: > The associated JBS issue has been dormant for 6+ years and this is a very intrusive change affecting many, many files. Has the resurrection of this project previously been discussed somewhere? Hi @dholmes-ora, The work to add this warning has been guided by @briangoetz in discussions on the amber-dev mailing list. See that thread for how we came up with the current design, underlying motivation, etc. Regarding intrusiveness (assuming you're referring simply to the number of files touched), as mentioned this was one of two options. The other option would be to patch to about ~30 `Java.gmk` files in `make/modules` to exclude `this-escape` from `-Xlint` during the various module builds. Going this route is fine with me, but it has the downside that any new code being developed would not benefit from the new warning. This was in fact my original approach (and it was a lot easier :) but Brian rightly pointed out that adding `@SuppressWarnings` annotations was the the safer (i.e, more conservative) approach. > If you haven't done so already then you probably should socialize on compiler-dev and get agreement on the semantics and other details. Hi @AlanBateman, As mentioned this has been under discussion on amber-dev for a while. Happy to continue that discussion here as well. > I think you will also need to separate the addition of the lint warning from the changes to the wider JDK. It might be okay to add the feature but have it disabled for the JDK build initially. Sounds reasonable... so I take it you would also be in favor of patching `make/modules` instead of adding `@SuppressWarnings` annotations everywhere... is that correct? If this is generally agreed as a better route then let me know and I'll update the patch. Thanks for both of your comments. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From alanb at openjdk.org Fri Jan 6 15:41:16 2023 From: alanb at openjdk.org (Alan Bateman) Date: Fri, 6 Jan 2023 15:41:16 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor In-Reply-To: References: Message-ID: On Fri, 6 Jan 2023 14:49:16 GMT, Archie L. Cobbs wrote: > Sounds reasonable... so I take it you would also be in favor of patching `make/modules` instead of adding `@SuppressWarnings` annotations everywhere... is that correct? > > If this is generally agreed as a better route then let me know and I'll update the patch. Yes, I think that would be better. It would remove most of the noise, 1200+ files, and 10+ mailing lists from this PR. I assume there will be at least some iteration on compiler-dev about the details and changes to javac. Once you get to the JDK changes then I suspect that some areas may want to fix issues rather than adding SW. Sadly, I see a few examples in your list where there have been attempts to avoid leaking "this" but where we backed away out of concern that 3rd party code was extending some class and overriding a method known to be invoked by the constructor. Also we have places that register themselves to cleaners. I suspect some of the suggestions to document leaking this in implNotes will need discussion too because they amount to documenting "hooks" that people will rely on, e.g. documenting in ArrayDeque that its constructor invokes addList could be read as an invite to override it. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From mcimadamore at openjdk.org Fri Jan 6 15:57:50 2023 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 6 Jan 2023 15:57:50 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor In-Reply-To: References: Message-ID: On Fri, 6 Jan 2023 15:38:31 GMT, Alan Bateman wrote: >>> The associated JBS issue has been dormant for 6+ years and this is a very intrusive change affecting many, many files. Has the resurrection of this project previously been discussed somewhere? >> >> Hi @dholmes-ora, >> >> The work to add this warning has been guided by @briangoetz in discussions on the amber-dev mailing list. See that thread for how we came up with the current design, underlying motivation, etc. >> >> Regarding intrusiveness (assuming you're referring simply to the number of files touched), as mentioned this was one of two options. The other option would be to patch to about ~30 `Java.gmk` files in `make/modules` to exclude `this-escape` from `-Xlint` during the various module builds. >> >> Going this route is fine with me, but it has the downside that any new code being developed would not benefit from the new warning. This was in fact my original approach (and it was a lot easier :) but Brian rightly pointed out that adding `@SuppressWarnings` annotations was the the safer (i.e, more conservative) approach. >> >>> If you haven't done so already then you probably should socialize on compiler-dev and get agreement on the semantics and other details. >> >> Hi @AlanBateman, >> >> As mentioned this has been under discussion on amber-dev for a while. Happy to continue that discussion here as well. >> >>> I think you will also need to separate the addition of the lint warning from the changes to the wider JDK. It might be okay to add the feature but have it disabled for the JDK build initially. >> >> Sounds reasonable... so I take it you would also be in favor of patching `make/modules` instead of adding `@SuppressWarnings` annotations everywhere... is that correct? >> >> If this is generally agreed as a better route then let me know and I'll update the patch. >> >> Thanks for both of your comments. > >> Sounds reasonable... so I take it you would also be in favor of patching `make/modules` instead of adding `@SuppressWarnings` annotations everywhere... is that correct? >> >> If this is generally agreed as a better route then let me know and I'll update the patch. > > Yes, I think that would be better. It would remove most of the noise, 1200+ files, and 10+ mailing lists from this PR. I assume there will be at least some iteration on compiler-dev about the details and changes to javac. Once you get to the JDK changes then I suspect that some areas may want to fix issues rather than adding SW. Sadly, I see a few examples in your list where there have been attempts to avoid leaking "this" but where we backed away out of concern that 3rd party code was extending some class and overriding a method known to be invoked by the constructor. Also we have places that register themselves to cleaners. I suspect some of the suggestions to document leaking this in implNotes will need discussion too because they amount to documenting "hooks" that people will rely on, e.g. documenting in ArrayDeque that its constructor invokes addList could be read as an invite to override it. I agree with @AlanBateman. When we introduced similar warnings in the past, we have enabled support in javac (with some test) in a separate PR, and then followed up with small dedicated PR for each of the various areas (enabling new warnings one by one). See this great umbrella JBS issue (created by @asotona) which has details on all the issues that were filed when we added an extra Lint warning for lossy conversions: https://bugs.openjdk.org/browse/JDK-8286374 They all refer to this: https://bugs.openjdk.org/browse/JDK-8244681 Which was submitted as a separate javac-only PR: https://github.com/openjdk/jdk/pull/8599 ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Fri Jan 6 23:13:09 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Fri, 6 Jan 2023 23:13:09 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v2] In-Reply-To: References: Message-ID: > This PR adds a new lint warning category `this-escape`. > > It also adds `@SuppressWarnings` annotations as needed to the JDK itself to allow the JDK to continue to compile with `-Xlint:all`. > > A 'this' escape warning is generated for a constructor `A()` in a class `A` when the compiler detects that the following situation is _in theory possible:_ > * Some subclass `B extends A` exists, and `B` is defined in a separate source file (i.e., compilation unit) > * Some constructor `B()` of `B` invokes `A()` as its superclass constructor > * During the execution of `A()`, some non-static method of `B.foo()` could get invoked, perhaps indirectly > > In the above scenario, `B.foo()` would execute before `A()` has returned and before `B()` has performed any initialization. To the extent `B.foo()` accesses any fields of `B` - all of which are still uninitialized - it is likely to function incorrectly. > > Note, when determining if a 'this' escape is possible, the compiler makes no assumptions about code outside of the current compilation unit. It doesn't look outside of the current source file to see what might actually happen when a method is invoked. It does follow method and constructors within the current compilation unit, and applies a simplified union-of-all-possible-branches data flow analysis to see where 'this' could end up. > > From my review, virtually all of the warnings generated in the various JDK modules are valid warnings in the sense that a 'this' escape, as defined above, is really and truly possible. However, that doesn't imply that any bugs were found within the JDK - only that the possibility of a certain type of bug exists if certain superclass constructors are used by someone, somewhere, someday. > > For several "popular" classes, this PR also adds `@implNote`'s to the offending constructors so that subclass implementors are made aware of the threat. For one example, `TreeMap(Map)` invokes `putAll()` and `put()`. > > More details and a couple of motivating examples are given in an included [doc file](https://github.com/archiecobbs/jdk/blob/ThisEscape/src/java.base/share/classes/java/lang/doc-files/ThisEscape.html) that these `@implNote`'s link to. See also the recent thread on `amber-dev` for some background. > > Ideally, over time the owners of the various modules would review their `@SuppressWarnings("this-escape")` annotations and determine which other constructors also warranted such an `@implNote`. > > Because of all the`@SuppressWarnings` annotations, this PR touches a bunch of different JDK modules. My apologies for that. Adding these annotations was determined to be the more conservative approach, as compared to just excepting `this-escape` from various module builds globally. > > **Patch Navigation Guide** > > * Non-trivial compiler changes: > * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties` > > * Javadoc additions of `@implNote`: > > * `src/java.base/share/classes/java/io/PipedReader.java` > * `src/java.base/share/classes/java/io/PipedWriter.java` > * `src/java.base/share/classes/java/lang/Throwable.java` > * `src/java.base/share/classes/java/util/ArrayDeque.java` > * `src/java.base/share/classes/java/util/EnumMap.java` > * `src/java.base/share/classes/java/util/HashSet.java` > * `src/java.base/share/classes/java/util/Hashtable.java` > * `src/java.base/share/classes/java/util/LinkedList.java` > * `src/java.base/share/classes/java/util/TreeMap.java` > * `src/java.base/share/classes/java/util/TreeSet.java` > > * New unit tests > * `test/langtools/tools/javac/warnings/ThisEscape/*.java` > > * **Everything else** is just adding `@SuppressWarnings("this-escape")` Archie L. Cobbs has updated the pull request incrementally with two additional commits since the last revision: - Update copyright year for newly added files to 2023. - Suppress "this-escape" warnings using build flags instead of @SuppressAnnotations annotations. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/11874/files - new: https://git.openjdk.org/jdk/pull/11874/files/9c162283..f667cd56 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=11874&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=11874&range=00-01 Stats: 1935 lines in 1303 files changed: 60 ins; 1770 del; 105 mod Patch: https://git.openjdk.org/jdk/pull/11874.diff Fetch: git fetch https://git.openjdk.org/jdk pull/11874/head:pull/11874 PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Fri Jan 6 23:13:09 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Fri, 6 Jan 2023 23:13:09 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor In-Reply-To: References: Message-ID: On Fri, 6 Jan 2023 15:38:31 GMT, Alan Bateman wrote: >>> The associated JBS issue has been dormant for 6+ years and this is a very intrusive change affecting many, many files. Has the resurrection of this project previously been discussed somewhere? >> >> Hi @dholmes-ora, >> >> The work to add this warning has been guided by @briangoetz in discussions on the amber-dev mailing list. See that thread for how we came up with the current design, underlying motivation, etc. >> >> Regarding intrusiveness (assuming you're referring simply to the number of files touched), as mentioned this was one of two options. The other option would be to patch to about ~30 `Java.gmk` files in `make/modules` to exclude `this-escape` from `-Xlint` during the various module builds. >> >> Going this route is fine with me, but it has the downside that any new code being developed would not benefit from the new warning. This was in fact my original approach (and it was a lot easier :) but Brian rightly pointed out that adding `@SuppressWarnings` annotations was the the safer (i.e, more conservative) approach. >> >>> If you haven't done so already then you probably should socialize on compiler-dev and get agreement on the semantics and other details. >> >> Hi @AlanBateman, >> >> As mentioned this has been under discussion on amber-dev for a while. Happy to continue that discussion here as well. >> >>> I think you will also need to separate the addition of the lint warning from the changes to the wider JDK. It might be okay to add the feature but have it disabled for the JDK build initially. >> >> Sounds reasonable... so I take it you would also be in favor of patching `make/modules` instead of adding `@SuppressWarnings` annotations everywhere... is that correct? >> >> If this is generally agreed as a better route then let me know and I'll update the patch. >> >> Thanks for both of your comments. > >> Sounds reasonable... so I take it you would also be in favor of patching `make/modules` instead of adding `@SuppressWarnings` annotations everywhere... is that correct? >> >> If this is generally agreed as a better route then let me know and I'll update the patch. > > Yes, I think that would be better. It would remove most of the noise, 1200+ files, and 10+ mailing lists from this PR. I assume there will be at least some iteration on compiler-dev about the details and changes to javac. Once you get to the JDK changes then I suspect that some areas may want to fix issues rather than adding SW. Sadly, I see a few examples in your list where there have been attempts to avoid leaking "this" but where we backed away out of concern that 3rd party code was extending some class and overriding a method known to be invoked by the constructor. Also we have places that register themselves to cleaners. I suspect some of the suggestions to document leaking this in implNotes will need discussion too because they amount to documenting "hooks" that people will rely on, e.g. documenting in ArrayDeque that its constructor invokes addList could be read as an invite to override it. Hi @AlanBateman, OK that sounds like a plan. I've pushed a new commit to the `ThisEscape` branch that removes all the`@SuppressWarnings` annotations and replaces them with adjustments to build flags. I've moved the `@SuppressWarnings` annotations onto a new branch `ThisEscapeAnnotations`. This is just for future reference in case somebody wants to add them back someday and doesn't want to start from scratch. > I suspect some of the suggestions to document leaking this in implNotes will need discussion too because they amount to documenting "hooks" that people will rely on, e.g. documenting in ArrayDeque that its constructor invokes addList could be read as an invite to override it. Hmm. Hasn't that horse already left the barn? You kind of implied that when you said: > I see a few examples in your list where there have been attempts to avoid leaking "this" but where we backed away out of concern that 3rd party code was extending some class and overriding a method known to be invoked by the constructor. In other words, it doesn't sound like changing the behavior of these constructors is viable option at this point. And if that's the case, we might as well document and warn about the current behavior. Of course I'd love to be wrong... in which case, we can fix these constructors. Or, the third option - just do nothing yet. That would mean removing the warnings, which is fine. But then the `ThisEscape.html` document is orphaned. What should we do with it? I can remove it, just leave it there, or put it somewhere else (where?). It seems like having some documentation of the meaning of "this escape" would be helpful, because it's a subtle concept and there are multiple ways to define "escape". Thanks. @mcimadamore thanks for the bugs suggestion, I'll put that on the to-do list. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Sat Jan 7 16:24:56 2023 From: duke at openjdk.org (ExE Boss) Date: Sat, 7 Jan 2023 16:24:56 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v2] In-Reply-To: References: Message-ID: On Fri, 6 Jan 2023 23:13:09 GMT, Archie L. Cobbs wrote: >> This PR adds a new lint warning category `this-escape`. >> >> It also adds `@SuppressWarnings` annotations as needed to the JDK itself to allow the JDK to continue to compile with `-Xlint:all`. >> >> A 'this' escape warning is generated for a constructor `A()` in a class `A` when the compiler detects that the following situation is _in theory possible:_ >> * Some subclass `B extends A` exists, and `B` is defined in a separate source file (i.e., compilation unit) >> * Some constructor `B()` of `B` invokes `A()` as its superclass constructor >> * During the execution of `A()`, some non-static method of `B.foo()` could get invoked, perhaps indirectly >> >> In the above scenario, `B.foo()` would execute before `A()` has returned and before `B()` has performed any initialization. To the extent `B.foo()` accesses any fields of `B` - all of which are still uninitialized - it is likely to function incorrectly. >> >> Note, when determining if a 'this' escape is possible, the compiler makes no assumptions about code outside of the current compilation unit. It doesn't look outside of the current source file to see what might actually happen when a method is invoked. It does follow method and constructors within the current compilation unit, and applies a simplified union-of-all-possible-branches data flow analysis to see where 'this' could end up. >> >> From my review, virtually all of the warnings generated in the various JDK modules are valid warnings in the sense that a 'this' escape, as defined above, is really and truly possible. However, that doesn't imply that any bugs were found within the JDK - only that the possibility of a certain type of bug exists if certain superclass constructors are used by someone, somewhere, someday. >> >> For several "popular" classes, this PR also adds `@implNote`'s to the offending constructors so that subclass implementors are made aware of the threat. For one example, `TreeMap(Map)` invokes `putAll()` and `put()`. >> >> More details and a couple of motivating examples are given in an included [doc file](https://github.com/archiecobbs/jdk/blob/ThisEscape/src/java.base/share/classes/java/lang/doc-files/ThisEscape.html) that these `@implNote`'s link to. See also the recent thread on `amber-dev` for some background. >> >> Ideally, over time the owners of the various modules would review their `@SuppressWarnings("this-escape")` annotations and determine which other constructors also warranted such an `@implNote`. >> >> Because of all the`@SuppressWarnings` annotations, this PR touches a bunch of different JDK modules. My apologies for that. Adding these annotations was determined to be the more conservative approach, as compared to just excepting `this-escape` from various module builds globally. >> >> **Patch Navigation Guide** >> >> * Non-trivial compiler changes: >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties` >> >> * Javadoc additions of `@implNote`: >> >> * `src/java.base/share/classes/java/io/PipedReader.java` >> * `src/java.base/share/classes/java/io/PipedWriter.java` >> * `src/java.base/share/classes/java/lang/Throwable.java` >> * `src/java.base/share/classes/java/util/ArrayDeque.java` >> * `src/java.base/share/classes/java/util/EnumMap.java` >> * `src/java.base/share/classes/java/util/HashSet.java` >> * `src/java.base/share/classes/java/util/Hashtable.java` >> * `src/java.base/share/classes/java/util/LinkedList.java` >> * `src/java.base/share/classes/java/util/TreeMap.java` >> * `src/java.base/share/classes/java/util/TreeSet.java` >> >> * New unit tests >> * `test/langtools/tools/javac/warnings/ThisEscape/*.java` >> >> * **Everything else** is just adding `@SuppressWarnings("this-escape")` > > Archie L. Cobbs has updated the pull request incrementally with two additional commits since the last revision: > > - Update copyright year for newly added files to 2023. > - Suppress "this-escape" warnings using build flags instead of @SuppressAnnotations annotations. src/java.base/share/classes/java/lang/AssertionError.java line 75: > 73: */ > 74: @SuppressWarnings("this-escape") > 75: public AssertionError(Object detailMessage) { The?Javadoc of?this?constructor should?probably?mention that?it?calls `initCause(?)` when?`detailMessage` is?a?`Throwable`. src/java.base/share/classes/java/lang/BootstrapMethodError.java line 77: > 75: * Constructs a {@code BootstrapMethodError} with the specified > 76: * cause. > 77: * Suggestion: * * @implNote This constructor invokes {@link #initCause initCause()}; see * This Escape. * src/java.base/share/classes/java/lang/ExceptionInInitializerError.java line 54: > 52: * throwable object. > 53: * A detail message is a String that describes this particular exception. > 54: */ Suggestion: * * @implNote This constructor invokes {@link #initCause initCause()}; see * This Escape. */ ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Sat Jan 7 16:58:58 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Sat, 7 Jan 2023 16:58:58 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v3] In-Reply-To: References: Message-ID: > This PR adds a new lint warning category `this-escape`. > > It also adds `@SuppressWarnings` annotations as needed to the JDK itself to allow the JDK to continue to compile with `-Xlint:all`. > > A 'this' escape warning is generated for a constructor `A()` in a class `A` when the compiler detects that the following situation is _in theory possible:_ > * Some subclass `B extends A` exists, and `B` is defined in a separate source file (i.e., compilation unit) > * Some constructor `B()` of `B` invokes `A()` as its superclass constructor > * During the execution of `A()`, some non-static method of `B.foo()` could get invoked, perhaps indirectly > > In the above scenario, `B.foo()` would execute before `A()` has returned and before `B()` has performed any initialization. To the extent `B.foo()` accesses any fields of `B` - all of which are still uninitialized - it is likely to function incorrectly. > > Note, when determining if a 'this' escape is possible, the compiler makes no assumptions about code outside of the current compilation unit. It doesn't look outside of the current source file to see what might actually happen when a method is invoked. It does follow method and constructors within the current compilation unit, and applies a simplified union-of-all-possible-branches data flow analysis to see where 'this' could end up. > > From my review, virtually all of the warnings generated in the various JDK modules are valid warnings in the sense that a 'this' escape, as defined above, is really and truly possible. However, that doesn't imply that any bugs were found within the JDK - only that the possibility of a certain type of bug exists if certain superclass constructors are used by someone, somewhere, someday. > > For several "popular" classes, this PR also adds `@implNote`'s to the offending constructors so that subclass implementors are made aware of the threat. For one example, `TreeMap(Map)` invokes `putAll()` and `put()`. > > More details and a couple of motivating examples are given in an included [doc file](https://github.com/archiecobbs/jdk/blob/ThisEscape/src/java.base/share/classes/java/lang/doc-files/ThisEscape.html) that these `@implNote`'s link to. See also the recent thread on `amber-dev` for some background. > > Ideally, over time the owners of the various modules would review their `@SuppressWarnings("this-escape")` annotations and determine which other constructors also warranted such an `@implNote`. > > Because of all the`@SuppressWarnings` annotations, this PR touches a bunch of different JDK modules. My apologies for that. Adding these annotations was determined to be the more conservative approach, as compared to just excepting `this-escape` from various module builds globally. > > **Patch Navigation Guide** > > * Non-trivial compiler changes: > * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties` > > * Javadoc additions of `@implNote`: > > * `src/java.base/share/classes/java/io/PipedReader.java` > * `src/java.base/share/classes/java/io/PipedWriter.java` > * `src/java.base/share/classes/java/lang/Throwable.java` > * `src/java.base/share/classes/java/util/ArrayDeque.java` > * `src/java.base/share/classes/java/util/EnumMap.java` > * `src/java.base/share/classes/java/util/HashSet.java` > * `src/java.base/share/classes/java/util/Hashtable.java` > * `src/java.base/share/classes/java/util/LinkedList.java` > * `src/java.base/share/classes/java/util/TreeMap.java` > * `src/java.base/share/classes/java/util/TreeSet.java` > > * New unit tests > * `test/langtools/tools/javac/warnings/ThisEscape/*.java` > > * **Everything else** is just adding `@SuppressWarnings("this-escape")` Archie L. Cobbs has updated the pull request incrementally with one additional commit since the last revision: Add a few more Javadoc warnings for 'this' escape via initCause(). ------------- Changes: - all: https://git.openjdk.org/jdk/pull/11874/files - new: https://git.openjdk.org/jdk/pull/11874/files/f667cd56..398737fa Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=11874&range=02 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=11874&range=01-02 Stats: 9 lines in 3 files changed: 9 ins; 0 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/11874.diff Fetch: git fetch https://git.openjdk.org/jdk pull/11874/head:pull/11874 PR: https://git.openjdk.org/jdk/pull/11874 From alanb at openjdk.org Sat Jan 7 18:05:50 2023 From: alanb at openjdk.org (Alan Bateman) Date: Sat, 7 Jan 2023 18:05:50 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor In-Reply-To: References: Message-ID: On Fri, 6 Jan 2023 23:08:27 GMT, Archie L. Cobbs wrote: > I've moved the `@SuppressWarnings` annotations onto a new branch `ThisEscapeAnnotations`. This is just for future reference in case somebody wants to add them back someday and doesn't want to start from scratch. > > > I suspect some of the suggestions to document leaking this in implNotes will need discussion too because they amount to documenting "hooks" that people will rely on, e.g. documenting in ArrayDeque that its constructor invokes addList could be read as an invite to override it. > > Hmm. Hasn't that horse already left the barn? You kind of implied that when you said: > > > I see a few examples in your list where there have been attempts to avoid leaking "this" but where we backed away out of concern that 3rd party code was extending some class and overriding a method known to be invoked by the constructor. > > In other words, it doesn't sound like changing the behavior of these constructors is viable option at this point. And if that's the case, we might as well document and warn about the current behavior. > > Of course I'd love to be wrong... in which case, we can fix these constructors. I hope at least some of these can be fixed as leaking a part initialized object to an untrusted subclass or some other code is problematic in many ways. Skimming through the original list, then some of these may be accidental and some may be fixable without any compatibility concerns, esp. in the JDK internal classes. Yes, some horses have left the barn. A horse that got out a long time ago is j.net.ServerSocket where 3 of its constructors call an overridable bind method. Recent re-implementation would have fixed this but there were concerns that subclasses may be relying on this long standing undocumented behavior. There are other cases in the list where the leaking may be necessary part of the contract for subclasses. So it will probably require working through them on a case by case basis. I don't think the implementation notes should be included as part of the adding the lint warning as I think it creates an attractive nuisance. Developers reading these implementation notes may c reate code that depends on these "hooks" and it will make it very hard for the JDK to ever change the behavior. Where the leaking is a necessary part of the contract for subclassing then it may be that it has to be documented as normative text rather than an implementation note. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Sat Jan 7 19:52:49 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Sat, 7 Jan 2023 19:52:49 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor In-Reply-To: References: Message-ID: On Sat, 7 Jan 2023 18:03:04 GMT, Alan Bateman wrote: > I don't think the implementation notes should be included as part of the adding the lint warning as I think it creates an attractive nuisance. I agree with you - not only for that reason, but also because as others have pointed out the addition of the warning is really a separate task from the evaluation and triage of any existing leaks. Moreover, this latter task is really multiple separate tasks that belong to the various module/functional groups. I'll remove all the Javadoc `@implNote`'s from the patch, and `src/java.base/share/classes/java/lang/doc-files/ThisEscape.html` as well - it will still be available in the git history if someone comes up with a better home for it. This will also further reduce the number of labels and therefore required reviewers. Thanks. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Sat Jan 7 19:59:59 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Sat, 7 Jan 2023 19:59:59 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v4] In-Reply-To: References: Message-ID: > This PR adds a new lint warning category `this-escape`. > > It also adds `@SuppressWarnings` annotations as needed to the JDK itself to allow the JDK to continue to compile with `-Xlint:all`. > > A 'this' escape warning is generated for a constructor `A()` in a class `A` when the compiler detects that the following situation is _in theory possible:_ > * Some subclass `B extends A` exists, and `B` is defined in a separate source file (i.e., compilation unit) > * Some constructor `B()` of `B` invokes `A()` as its superclass constructor > * During the execution of `A()`, some non-static method of `B.foo()` could get invoked, perhaps indirectly > > In the above scenario, `B.foo()` would execute before `A()` has returned and before `B()` has performed any initialization. To the extent `B.foo()` accesses any fields of `B` - all of which are still uninitialized - it is likely to function incorrectly. > > Note, when determining if a 'this' escape is possible, the compiler makes no assumptions about code outside of the current compilation unit. It doesn't look outside of the current source file to see what might actually happen when a method is invoked. It does follow method and constructors within the current compilation unit, and applies a simplified union-of-all-possible-branches data flow analysis to see where 'this' could end up. > > From my review, virtually all of the warnings generated in the various JDK modules are valid warnings in the sense that a 'this' escape, as defined above, is really and truly possible. However, that doesn't imply that any bugs were found within the JDK - only that the possibility of a certain type of bug exists if certain superclass constructors are used by someone, somewhere, someday. > > For several "popular" classes, this PR also adds `@implNote`'s to the offending constructors so that subclass implementors are made aware of the threat. For one example, `TreeMap(Map)` invokes `putAll()` and `put()`. > > More details and a couple of motivating examples are given in an included [doc file](https://github.com/archiecobbs/jdk/blob/ThisEscape/src/java.base/share/classes/java/lang/doc-files/ThisEscape.html) that these `@implNote`'s link to. See also the recent thread on `amber-dev` for some background. > > Ideally, over time the owners of the various modules would review their `@SuppressWarnings("this-escape")` annotations and determine which other constructors also warranted such an `@implNote`. > > Because of all the`@SuppressWarnings` annotations, this PR touches a bunch of different JDK modules. My apologies for that. Adding these annotations was determined to be the more conservative approach, as compared to just excepting `this-escape` from various module builds globally. > > **Patch Navigation Guide** > > * Non-trivial compiler changes: > * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties` > > * Javadoc additions of `@implNote`: > > * `src/java.base/share/classes/java/io/PipedReader.java` > * `src/java.base/share/classes/java/io/PipedWriter.java` > * `src/java.base/share/classes/java/lang/Throwable.java` > * `src/java.base/share/classes/java/util/ArrayDeque.java` > * `src/java.base/share/classes/java/util/EnumMap.java` > * `src/java.base/share/classes/java/util/HashSet.java` > * `src/java.base/share/classes/java/util/Hashtable.java` > * `src/java.base/share/classes/java/util/LinkedList.java` > * `src/java.base/share/classes/java/util/TreeMap.java` > * `src/java.base/share/classes/java/util/TreeSet.java` > > * New unit tests > * `test/langtools/tools/javac/warnings/ThisEscape/*.java` > > * **Everything else** is just adding `@SuppressWarnings("this-escape")` Archie L. Cobbs has updated the pull request incrementally with one additional commit since the last revision: Remove Javadoc @implNotes; plan to triage the various existing leaks separately. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/11874/files - new: https://git.openjdk.org/jdk/pull/11874/files/398737fa..537b3e3c Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=11874&range=03 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=11874&range=02-03 Stats: 255 lines in 29 files changed: 0 ins; 251 del; 4 mod Patch: https://git.openjdk.org/jdk/pull/11874.diff Fetch: git fetch https://git.openjdk.org/jdk pull/11874/head:pull/11874 PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Sat Jan 7 21:08:07 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Sat, 7 Jan 2023 21:08:07 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v5] In-Reply-To: References: Message-ID: <_GkLRl5VTNh8ToJ3cjF-_v9j6eWWQzbUCCKStOXKh4g=.5e9505f1-8182-47e6-a8ed-78982db36c94@github.com> > This PR adds a new lint warning category `this-escape`. > > It also adds `@SuppressWarnings` annotations as needed to the JDK itself to allow the JDK to continue to compile with `-Xlint:all`. > > A 'this' escape warning is generated for a constructor `A()` in a class `A` when the compiler detects that the following situation is _in theory possible:_ > * Some subclass `B extends A` exists, and `B` is defined in a separate source file (i.e., compilation unit) > * Some constructor `B()` of `B` invokes `A()` as its superclass constructor > * During the execution of `A()`, some non-static method of `B.foo()` could get invoked, perhaps indirectly > > In the above scenario, `B.foo()` would execute before `A()` has returned and before `B()` has performed any initialization. To the extent `B.foo()` accesses any fields of `B` - all of which are still uninitialized - it is likely to function incorrectly. > > Note, when determining if a 'this' escape is possible, the compiler makes no assumptions about code outside of the current compilation unit. It doesn't look outside of the current source file to see what might actually happen when a method is invoked. It does follow method and constructors within the current compilation unit, and applies a simplified union-of-all-possible-branches data flow analysis to see where 'this' could end up. > > From my review, virtually all of the warnings generated in the various JDK modules are valid warnings in the sense that a 'this' escape, as defined above, is really and truly possible. However, that doesn't imply that any bugs were found within the JDK - only that the possibility of a certain type of bug exists if certain superclass constructors are used by someone, somewhere, someday. > > For several "popular" classes, this PR also adds `@implNote`'s to the offending constructors so that subclass implementors are made aware of the threat. For one example, `TreeMap(Map)` invokes `putAll()` and `put()`. > > More details and a couple of motivating examples are given in an included [doc file](https://github.com/archiecobbs/jdk/blob/ThisEscape/src/java.base/share/classes/java/lang/doc-files/ThisEscape.html) that these `@implNote`'s link to. See also the recent thread on `amber-dev` for some background. > > Ideally, over time the owners of the various modules would review their `@SuppressWarnings("this-escape")` annotations and determine which other constructors also warranted such an `@implNote`. > > Because of all the`@SuppressWarnings` annotations, this PR touches a bunch of different JDK modules. My apologies for that. Adding these annotations was determined to be the more conservative approach, as compared to just excepting `this-escape` from various module builds globally. > > **Patch Navigation Guide** > > * Non-trivial compiler changes: > * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties` > > * Javadoc additions of `@implNote`: > > * `src/java.base/share/classes/java/io/PipedReader.java` > * `src/java.base/share/classes/java/io/PipedWriter.java` > * `src/java.base/share/classes/java/lang/Throwable.java` > * `src/java.base/share/classes/java/util/ArrayDeque.java` > * `src/java.base/share/classes/java/util/EnumMap.java` > * `src/java.base/share/classes/java/util/HashSet.java` > * `src/java.base/share/classes/java/util/Hashtable.java` > * `src/java.base/share/classes/java/util/LinkedList.java` > * `src/java.base/share/classes/java/util/TreeMap.java` > * `src/java.base/share/classes/java/util/TreeSet.java` > > * New unit tests > * `test/langtools/tools/javac/warnings/ThisEscape/*.java` > > * **Everything else** is just adding `@SuppressWarnings("this-escape")` Archie L. Cobbs has updated the pull request incrementally with one additional commit since the last revision: Fix incorrect @bug numbers in unit tests. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/11874/files - new: https://git.openjdk.org/jdk/pull/11874/files/537b3e3c..7e2fdb07 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=11874&range=04 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=11874&range=03-04 Stats: 15 lines in 15 files changed: 0 ins; 0 del; 15 mod Patch: https://git.openjdk.org/jdk/pull/11874.diff Fetch: git fetch https://git.openjdk.org/jdk pull/11874/head:pull/11874 PR: https://git.openjdk.org/jdk/pull/11874 From dholmes at openjdk.org Mon Jan 9 06:39:52 2023 From: dholmes at openjdk.org (David Holmes) Date: Mon, 9 Jan 2023 06:39:52 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v5] In-Reply-To: <_GkLRl5VTNh8ToJ3cjF-_v9j6eWWQzbUCCKStOXKh4g=.5e9505f1-8182-47e6-a8ed-78982db36c94@github.com> References: <_GkLRl5VTNh8ToJ3cjF-_v9j6eWWQzbUCCKStOXKh4g=.5e9505f1-8182-47e6-a8ed-78982db36c94@github.com> Message-ID: On Sat, 7 Jan 2023 21:08:07 GMT, Archie L. Cobbs wrote: >> This PR adds a new lint warning category `this-escape`. >> >> It also adds `@SuppressWarnings` annotations as needed to the JDK itself to allow the JDK to continue to compile with `-Xlint:all`. >> >> A 'this' escape warning is generated for a constructor `A()` in a class `A` when the compiler detects that the following situation is _in theory possible:_ >> * Some subclass `B extends A` exists, and `B` is defined in a separate source file (i.e., compilation unit) >> * Some constructor `B()` of `B` invokes `A()` as its superclass constructor >> * During the execution of `A()`, some non-static method of `B.foo()` could get invoked, perhaps indirectly >> >> In the above scenario, `B.foo()` would execute before `A()` has returned and before `B()` has performed any initialization. To the extent `B.foo()` accesses any fields of `B` - all of which are still uninitialized - it is likely to function incorrectly. >> >> Note, when determining if a 'this' escape is possible, the compiler makes no assumptions about code outside of the current compilation unit. It doesn't look outside of the current source file to see what might actually happen when a method is invoked. It does follow method and constructors within the current compilation unit, and applies a simplified union-of-all-possible-branches data flow analysis to see where 'this' could end up. >> >> From my review, virtually all of the warnings generated in the various JDK modules are valid warnings in the sense that a 'this' escape, as defined above, is really and truly possible. However, that doesn't imply that any bugs were found within the JDK - only that the possibility of a certain type of bug exists if certain superclass constructors are used by someone, somewhere, someday. >> >> For several "popular" classes, this PR also adds `@implNote`'s to the offending constructors so that subclass implementors are made aware of the threat. For one example, `TreeMap(Map)` invokes `putAll()` and `put()`. >> >> More details and a couple of motivating examples are given in an included [doc file](https://github.com/archiecobbs/jdk/blob/ThisEscape/src/java.base/share/classes/java/lang/doc-files/ThisEscape.html) that these `@implNote`'s link to. See also the recent thread on `amber-dev` for some background. >> >> Ideally, over time the owners of the various modules would review their `@SuppressWarnings("this-escape")` annotations and determine which other constructors also warranted such an `@implNote`. >> >> Because of all the`@SuppressWarnings` annotations, this PR touches a bunch of different JDK modules. My apologies for that. Adding these annotations was determined to be the more conservative approach, as compared to just excepting `this-escape` from various module builds globally. >> >> **Patch Navigation Guide** >> >> * Non-trivial compiler changes: >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties` >> >> * Javadoc additions of `@implNote`: >> >> * `src/java.base/share/classes/java/io/PipedReader.java` >> * `src/java.base/share/classes/java/io/PipedWriter.java` >> * `src/java.base/share/classes/java/lang/Throwable.java` >> * `src/java.base/share/classes/java/util/ArrayDeque.java` >> * `src/java.base/share/classes/java/util/EnumMap.java` >> * `src/java.base/share/classes/java/util/HashSet.java` >> * `src/java.base/share/classes/java/util/Hashtable.java` >> * `src/java.base/share/classes/java/util/LinkedList.java` >> * `src/java.base/share/classes/java/util/TreeMap.java` >> * `src/java.base/share/classes/java/util/TreeSet.java` >> >> * New unit tests >> * `test/langtools/tools/javac/warnings/ThisEscape/*.java` >> >> * **Everything else** is just adding `@SuppressWarnings("this-escape")` > > Archie L. Cobbs has updated the pull request incrementally with one additional commit since the last revision: > > Fix incorrect @bug numbers in unit tests. All your new files need a copyright and GPL header. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Mon Jan 9 14:03:54 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Mon, 9 Jan 2023 14:03:54 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v5] In-Reply-To: References: <_GkLRl5VTNh8ToJ3cjF-_v9j6eWWQzbUCCKStOXKh4g=.5e9505f1-8182-47e6-a8ed-78982db36c94@github.com> Message-ID: On Mon, 9 Jan 2023 06:37:22 GMT, David Holmes wrote: > All your new files need a copyright and GPL header. Sorry if I'm being blind but I'm not seeing it. Which file(s) are you referring to? The `@test /nodynamiccopyright/` files don't get one per [this](https://openjdk.org/groups/compiler/tests.html#gold). ------------- PR: https://git.openjdk.org/jdk/pull/11874 From asotona at openjdk.org Tue Jan 10 15:51:29 2023 From: asotona at openjdk.org (Adam Sotona) Date: Tue, 10 Jan 2023 15:51:29 GMT Subject: RFR: 8299829: In jshell, the output of "0".repeat(49999)+"2" ends with a '0' Message-ID: "0".repeat(49999)+"2" correctly evaluates to a string with a terminating '2'. However, jshell outputs it with a terminating '0'. Jshell provides double truncation of long Strings. One is performed in jdk.jshell.execution.ExecutionControlForwarder to fit into MAX_UTF_CHARS = 21844 (which is exactly the point where "2" disappears). Second truncation is performed in jdk.internal.jshell.tool.Feedback to fit presentation requirements. While ExecutionControlForwarder truncates right part of the String, Feedback truncated inner part in 2/3 and joins the parts with " ... ". Proposed patch fixes ExecutionControlForwarder to truncate long Strings the same way as Feedback, so the right part of any long String won't disappear and double or repeated truncation provides consistent results. Please review :) Thanks, Adam ------------- Commit messages: - 8299829: In jshell, the output of "0".repeat(49999)+"2" ends with a '0' Changes: https://git.openjdk.org/jdk/pull/11927/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=11927&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8299829 Stats: 5 lines in 1 file changed: 4 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/11927.diff Fetch: git fetch https://git.openjdk.org/jdk pull/11927/head:pull/11927 PR: https://git.openjdk.org/jdk/pull/11927 From asotona at openjdk.org Tue Jan 10 16:14:44 2023 From: asotona at openjdk.org (Adam Sotona) Date: Tue, 10 Jan 2023 16:14:44 GMT Subject: RFR: 8299829: In jshell, the output of "0".repeat(49999)+"2" ends with a '0' [v2] In-Reply-To: References: Message-ID: > "0".repeat(49999)+"2" correctly evaluates to a string with a terminating '2'. > However, jshell outputs it with a terminating '0'. > > Jshell provides double truncation of long Strings. > One is performed in jdk.jshell.execution.ExecutionControlForwarder to fit into MAX_UTF_CHARS = 21844 (which is exactly the point where "2" disappears). > Second truncation is performed in jdk.internal.jshell.tool.Feedback to fit presentation requirements. > While ExecutionControlForwarder truncates right part of the String, Feedback truncated inner part in 2/3 and joins the parts with " ... ". > > Proposed patch fixes ExecutionControlForwarder to truncate long Strings the same way as Feedback, so the right part of any long String won't disappear and double or repeated truncation provides consistent results. > > Please review :) > > Thanks, > Adam Adam Sotona has updated the pull request incrementally with one additional commit since the last revision: added test ------------- Changes: - all: https://git.openjdk.org/jdk/pull/11927/files - new: https://git.openjdk.org/jdk/pull/11927/files/d6ff2bf2..6f014b6c Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=11927&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=11927&range=00-01 Stats: 3 lines in 1 file changed: 1 ins; 0 del; 2 mod Patch: https://git.openjdk.org/jdk/pull/11927.diff Fetch: git fetch https://git.openjdk.org/jdk pull/11927/head:pull/11927 PR: https://git.openjdk.org/jdk/pull/11927 From jlahoda at openjdk.org Tue Jan 10 17:49:52 2023 From: jlahoda at openjdk.org (Jan Lahoda) Date: Tue, 10 Jan 2023 17:49:52 GMT Subject: RFR: 8299829: In jshell, the output of "0".repeat(49999)+"2" ends with a '0' [v2] In-Reply-To: References: Message-ID: <4YtrDmTcoYT3ydwjSgry4Pn6plYnWcQvsccxpLIPmLs=.8c338a9d-7728-43db-914e-823823443704@github.com> On Tue, 10 Jan 2023 16:14:44 GMT, Adam Sotona wrote: >> "0".repeat(49999)+"2" correctly evaluates to a string with a terminating '2'. >> However, jshell outputs it with a terminating '0'. >> >> Jshell provides double truncation of long Strings. >> One is performed in jdk.jshell.execution.ExecutionControlForwarder to fit into MAX_UTF_CHARS = 21844 (which is exactly the point where "2" disappears). >> Second truncation is performed in jdk.internal.jshell.tool.Feedback to fit presentation requirements. >> While ExecutionControlForwarder truncates right part of the String, Feedback truncated inner part in 2/3 and joins the parts with " ... ". >> >> Proposed patch fixes ExecutionControlForwarder to truncate long Strings the same way as Feedback, so the right part of any long String won't disappear and double or repeated truncation provides consistent results. >> >> Please review :) >> >> Thanks, >> Adam > > Adam Sotona has updated the pull request incrementally with one additional commit since the last revision: > > added test Looks good to me. Thanks! ------------- Marked as reviewed by jlahoda (Reviewer). PR: https://git.openjdk.org/jdk/pull/11927 From mcimadamore at openjdk.org Tue Jan 10 18:52:56 2023 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Tue, 10 Jan 2023 18:52:56 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v5] In-Reply-To: <_GkLRl5VTNh8ToJ3cjF-_v9j6eWWQzbUCCKStOXKh4g=.5e9505f1-8182-47e6-a8ed-78982db36c94@github.com> References: <_GkLRl5VTNh8ToJ3cjF-_v9j6eWWQzbUCCKStOXKh4g=.5e9505f1-8182-47e6-a8ed-78982db36c94@github.com> Message-ID: On Sat, 7 Jan 2023 21:08:07 GMT, Archie L. Cobbs wrote: >> This PR adds a new lint warning category `this-escape`. >> >> It also adds `@SuppressWarnings` annotations as needed to the JDK itself to allow the JDK to continue to compile with `-Xlint:all`. >> >> A 'this' escape warning is generated for a constructor `A()` in a class `A` when the compiler detects that the following situation is _in theory possible:_ >> * Some subclass `B extends A` exists, and `B` is defined in a separate source file (i.e., compilation unit) >> * Some constructor `B()` of `B` invokes `A()` as its superclass constructor >> * During the execution of `A()`, some non-static method of `B.foo()` could get invoked, perhaps indirectly >> >> In the above scenario, `B.foo()` would execute before `A()` has returned and before `B()` has performed any initialization. To the extent `B.foo()` accesses any fields of `B` - all of which are still uninitialized - it is likely to function incorrectly. >> >> Note, when determining if a 'this' escape is possible, the compiler makes no assumptions about code outside of the current compilation unit. It doesn't look outside of the current source file to see what might actually happen when a method is invoked. It does follow method and constructors within the current compilation unit, and applies a simplified union-of-all-possible-branches data flow analysis to see where 'this' could end up. >> >> From my review, virtually all of the warnings generated in the various JDK modules are valid warnings in the sense that a 'this' escape, as defined above, is really and truly possible. However, that doesn't imply that any bugs were found within the JDK - only that the possibility of a certain type of bug exists if certain superclass constructors are used by someone, somewhere, someday. >> >> For several "popular" classes, this PR also adds `@implNote`'s to the offending constructors so that subclass implementors are made aware of the threat. For one example, `TreeMap(Map)` invokes `putAll()` and `put()`. >> >> More details and a couple of motivating examples are given in an included [doc file](https://github.com/archiecobbs/jdk/blob/ThisEscape/src/java.base/share/classes/java/lang/doc-files/ThisEscape.html) that these `@implNote`'s link to. See also the recent thread on `amber-dev` for some background. >> >> Ideally, over time the owners of the various modules would review their `@SuppressWarnings("this-escape")` annotations and determine which other constructors also warranted such an `@implNote`. >> >> Because of all the`@SuppressWarnings` annotations, this PR touches a bunch of different JDK modules. My apologies for that. Adding these annotations was determined to be the more conservative approach, as compared to just excepting `this-escape` from various module builds globally. >> >> **Patch Navigation Guide** >> >> * Non-trivial compiler changes: >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties` >> >> * Javadoc additions of `@implNote`: >> >> * `src/java.base/share/classes/java/io/PipedReader.java` >> * `src/java.base/share/classes/java/io/PipedWriter.java` >> * `src/java.base/share/classes/java/lang/Throwable.java` >> * `src/java.base/share/classes/java/util/ArrayDeque.java` >> * `src/java.base/share/classes/java/util/EnumMap.java` >> * `src/java.base/share/classes/java/util/HashSet.java` >> * `src/java.base/share/classes/java/util/Hashtable.java` >> * `src/java.base/share/classes/java/util/LinkedList.java` >> * `src/java.base/share/classes/java/util/TreeMap.java` >> * `src/java.base/share/classes/java/util/TreeSet.java` >> >> * New unit tests >> * `test/langtools/tools/javac/warnings/ThisEscape/*.java` >> >> * **Everything else** is just adding `@SuppressWarnings("this-escape")` > > Archie L. Cobbs has updated the pull request incrementally with one additional commit since the last revision: > > Fix incorrect @bug numbers in unit tests. src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java line 2345: > 2343: if (!innerType.hasTag(CLASS) || !outerType.hasTag(CLASS)) > 2344: return false; > 2345: innerType = erasure(innerType); The javac way to write this would be either to compare types using `Types.isSameType` or to compare the underlying class symbols with == (as class symbols are shared across multiple type instances). src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 85: > 83: * > 84: *

> 85: * When tracking references, we distinguish between direct references and indirect references, I'm trying to understand the code and it's not obvious to me as to where this difference comes into play. I believe (but I'm not sure) the spirit is to treat reference to `this` in the original constructor as "direct" while treat a reference to a parameter "a" in a method called from the constructor, where "a" is assigned "this", as indirect? src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 1098: > 1096: private void visitLooped(T tree, Consumer visitor) { > 1097: this.visitScoped(tree, false, t -> { > 1098: while (true) { Why is this needed? Can the tracking state of `this` change after multiple "execution" of the same code? ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Tue Jan 10 19:22:58 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Tue, 10 Jan 2023 19:22:58 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v5] In-Reply-To: References: <_GkLRl5VTNh8ToJ3cjF-_v9j6eWWQzbUCCKStOXKh4g=.5e9505f1-8182-47e6-a8ed-78982db36c94@github.com> Message-ID: On Mon, 9 Jan 2023 15:03:10 GMT, Maurizio Cimadamore wrote: >> Archie L. Cobbs has updated the pull request incrementally with one additional commit since the last revision: >> >> Fix incorrect @bug numbers in unit tests. > > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 85: > >> 83: * >> 84: *

>> 85: * When tracking references, we distinguish between direct references and indirect references, > > I'm trying to understand the code and it's not obvious to me as to where this difference comes into play. I believe (but I'm not sure) the spirit is to treat reference to `this` in the original constructor as "direct" while treat a reference to a parameter "a" in a method called from the constructor, where "a" is assigned "this", as indirect? It's slightly different from that. Considering any of the various things in scope that can point to an object (these are: the current 'this' instance, the current outer 'this' instance, method parameter/variable, method return value, top of Java stack), such a thing has a "direct" reference if it might possibly _directly_ point to the 'this' we're tracking, while a thing has an "indirect" reference if it might possibly point to the 'this' we're tracking through _at least one level of indirection_. This is just an attempt to eliminate some false positives by distinguishing between those two cases. Originally I was going to try to track fields (in a very limited way), and so this distinction was going to be more important, but even without tracking fields it's still useful. For example, if some method invokes `x.y.foo()` and `x` represents a direct but not an indirect 'this' reference, then there is no leak declared. Considering the other options... (a) if you only track direct references, then you suffer from more false negatives (how many? unclear); (b) if you lump direct and indirect references into one bucket, then you suffer from more false positives (as in previous example `x.y.foo()`). You can see an example of an indirect reference being tracked and exposed in the unit test `ThisEscapeArrayElement.java`. Another motivating example is lambdas. The act of simply _creating_ a lambda never creates a leak, and a lambda never represents a _direct_ reference. But it might represent an _indirect_ reference. > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 1098: > >> 1096: private void visitLooped(T tree, Consumer visitor) { >> 1097: this.visitScoped(tree, false, t -> { >> 1098: while (true) { > > Why is this needed? Can the tracking state of `this` change after multiple "execution" of the same code? Yes, because the 'this' reference can bounce around through different variables in scope each time around the loop. So we have to repeat the loop until all 'this' references have "flooded" into all the nooks and crannies. The `ThisEscapeLoop.java` unit test demonstrates: public class ThisEscapeLoop { public ThisEscapeLoop() { ThisEscapeLoop ref1 = this; ThisEscapeLoop ref2 = null; ThisEscapeLoop ref3 = null; ThisEscapeLoop ref4 = null; for (int i = 0; i < 100; i++) { ref4 = ref3; ref3 = ref2; ref2 = ref1; if (ref4 != null) ref4.mightLeak(); } } public void mightLeak() { } } ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Tue Jan 10 19:44:56 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Tue, 10 Jan 2023 19:44:56 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v5] In-Reply-To: References: <_GkLRl5VTNh8ToJ3cjF-_v9j6eWWQzbUCCKStOXKh4g=.5e9505f1-8182-47e6-a8ed-78982db36c94@github.com> Message-ID: On Mon, 9 Jan 2023 14:23:47 GMT, Maurizio Cimadamore wrote: >> Archie L. Cobbs has updated the pull request incrementally with one additional commit since the last revision: >> >> Fix incorrect @bug numbers in unit tests. > > src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java line 2345: > >> 2343: if (!innerType.hasTag(CLASS) || !outerType.hasTag(CLASS)) >> 2344: return false; >> 2345: innerType = erasure(innerType); > > The javac way to write this would be either to compare types using `Types.isSameType` or to compare the underlying class symbols with == (as class symbols are shared across multiple type instances). OK I'm glad you pointed that out because I'm a little unclear on the best way to do this bit. Just to confirm, you are saying that this: `if (erasure(type).equalsIgnoreMetadata(outerType)) {` should be replaced with this? `if (isSameType(type, outerType)) {` ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Tue Jan 10 20:22:16 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Tue, 10 Jan 2023 20:22:16 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v6] In-Reply-To: References: Message-ID: <-cVR0e9azbb3U9vWObNm1dBbUGIDuI7T6bAOpuPSG8I=.a55f2d47-00ae-471c-a51c-df638c104487@github.com> > This PR adds a new lint warning category `this-escape`. > > It also adds `@SuppressWarnings` annotations as needed to the JDK itself to allow the JDK to continue to compile with `-Xlint:all`. > > A 'this' escape warning is generated for a constructor `A()` in a class `A` when the compiler detects that the following situation is _in theory possible:_ > * Some subclass `B extends A` exists, and `B` is defined in a separate source file (i.e., compilation unit) > * Some constructor `B()` of `B` invokes `A()` as its superclass constructor > * During the execution of `A()`, some non-static method of `B.foo()` could get invoked, perhaps indirectly > > In the above scenario, `B.foo()` would execute before `A()` has returned and before `B()` has performed any initialization. To the extent `B.foo()` accesses any fields of `B` - all of which are still uninitialized - it is likely to function incorrectly. > > Note, when determining if a 'this' escape is possible, the compiler makes no assumptions about code outside of the current compilation unit. It doesn't look outside of the current source file to see what might actually happen when a method is invoked. It does follow method and constructors within the current compilation unit, and applies a simplified union-of-all-possible-branches data flow analysis to see where 'this' could end up. > > From my review, virtually all of the warnings generated in the various JDK modules are valid warnings in the sense that a 'this' escape, as defined above, is really and truly possible. However, that doesn't imply that any bugs were found within the JDK - only that the possibility of a certain type of bug exists if certain superclass constructors are used by someone, somewhere, someday. > > For several "popular" classes, this PR also adds `@implNote`'s to the offending constructors so that subclass implementors are made aware of the threat. For one example, `TreeMap(Map)` invokes `putAll()` and `put()`. > > More details and a couple of motivating examples are given in an included [doc file](https://github.com/archiecobbs/jdk/blob/ThisEscape/src/java.base/share/classes/java/lang/doc-files/ThisEscape.html) that these `@implNote`'s link to. See also the recent thread on `amber-dev` for some background. > > Ideally, over time the owners of the various modules would review their `@SuppressWarnings("this-escape")` annotations and determine which other constructors also warranted such an `@implNote`. > > Because of all the`@SuppressWarnings` annotations, this PR touches a bunch of different JDK modules. My apologies for that. Adding these annotations was determined to be the more conservative approach, as compared to just excepting `this-escape` from various module builds globally. > > **Patch Navigation Guide** > > * Non-trivial compiler changes: > * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties` > > * Javadoc additions of `@implNote`: > > * `src/java.base/share/classes/java/io/PipedReader.java` > * `src/java.base/share/classes/java/io/PipedWriter.java` > * `src/java.base/share/classes/java/lang/Throwable.java` > * `src/java.base/share/classes/java/util/ArrayDeque.java` > * `src/java.base/share/classes/java/util/EnumMap.java` > * `src/java.base/share/classes/java/util/HashSet.java` > * `src/java.base/share/classes/java/util/Hashtable.java` > * `src/java.base/share/classes/java/util/LinkedList.java` > * `src/java.base/share/classes/java/util/TreeMap.java` > * `src/java.base/share/classes/java/util/TreeSet.java` > > * New unit tests > * `test/langtools/tools/javac/warnings/ThisEscape/*.java` > > * **Everything else** is just adding `@SuppressWarnings("this-escape")` Archie L. Cobbs has updated the pull request incrementally with one additional commit since the last revision: Add this-escape to the Javadoc list of strings supported by @SuppressWarnings. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/11874/files - new: https://git.openjdk.org/jdk/pull/11874/files/7e2fdb07..d70d12f4 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=11874&range=05 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=11874&range=04-05 Stats: 1 line in 1 file changed: 1 ins; 0 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/11874.diff Fetch: git fetch https://git.openjdk.org/jdk pull/11874/head:pull/11874 PR: https://git.openjdk.org/jdk/pull/11874 From mcimadamore at openjdk.org Tue Jan 10 23:41:19 2023 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Tue, 10 Jan 2023 23:41:19 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v5] In-Reply-To: References: <_GkLRl5VTNh8ToJ3cjF-_v9j6eWWQzbUCCKStOXKh4g=.5e9505f1-8182-47e6-a8ed-78982db36c94@github.com> Message-ID: <0Hksmg2eLQg0c9W5CB6y6dXw2vaEXxy-UY9_D0DtLQY=.351da0ec-208c-4f8d-bf16-318de07ca63e@github.com> On Tue, 10 Jan 2023 19:42:06 GMT, Archie L. Cobbs wrote: >> src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java line 2345: >> >>> 2343: if (!innerType.hasTag(CLASS) || !outerType.hasTag(CLASS)) >>> 2344: return false; >>> 2345: innerType = erasure(innerType); >> >> The javac way to write this would be either to compare types using `Types.isSameType` or to compare the underlying class symbols with == (as class symbols are shared across multiple type instances). > > OK I'm glad you pointed that out because I'm a little unclear on the best way to do this bit. > > Just to confirm, you are saying that this: > > `if (erasure(type).equalsIgnoreMetadata(outerType)) {` > > should be replaced with this? > > `if (isSameType(type, outerType)) {` yes ------------- PR: https://git.openjdk.org/jdk/pull/11874 From mcimadamore at openjdk.org Tue Jan 10 23:49:12 2023 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Tue, 10 Jan 2023 23:49:12 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v5] In-Reply-To: References: <_GkLRl5VTNh8ToJ3cjF-_v9j6eWWQzbUCCKStOXKh4g=.5e9505f1-8182-47e6-a8ed-78982db36c94@github.com> Message-ID: <8PxlV-Syo2Y48TBgSQupSjArfJxMqnA8BZQIYTfYGPA=.057f204c-330b-4fb9-96e5-f8dc8fe348aa@github.com> On Tue, 10 Jan 2023 19:18:04 GMT, Archie L. Cobbs wrote: >> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 85: >> >>> 83: * >>> 84: *

>>> 85: * When tracking references, we distinguish between direct references and indirect references, >> >> I'm trying to understand the code and it's not obvious to me as to where this difference comes into play. I believe (but I'm not sure) the spirit is to treat reference to `this` in the original constructor as "direct" while treat a reference to a parameter "a" in a method called from the constructor, where "a" is assigned "this", as indirect? > > It's slightly different from that. > > Considering any of the various things in scope that can point to an object (these are: the current 'this' instance, the current outer 'this' instance, method parameter/variable, method return value, top of Java stack), such a thing has a "direct" reference if it might possibly _directly_ point to the 'this' we're tracking, while a thing has an "indirect" reference if it might possibly point to the 'this' we're tracking through _at least one level of indirection_. > > This is just an attempt to eliminate some false positives by distinguishing between those two cases. Originally I was going to try to track fields (in a very limited way), and so this distinction was going to be more important, but even without tracking fields it's still useful. For example, if some method invokes `x.y.foo()` and `x` represents a direct but not an indirect 'this' reference, then there is no leak declared. > > Considering the other options... (a) if you only track direct references, then you suffer from more false negatives (how many? unclear); (b) if you lump direct and indirect references into one bucket, then you suffer from more false positives (as in previous example `x.y.foo()`). > > You can see an example of an indirect reference being tracked and exposed in the unit test `ThisEscapeArrayElement.java`. > > Another motivating example is lambdas. The act of simply _creating_ a lambda never creates a leak, and a lambda never represents a _direct_ reference. But it might represent an _indirect_ reference. So, if I understand correctly your array element test, when we have `new Object[][] { { this } }` the analysis is able to detect that there might be some direct reference nested inside the array. So the outer array is an indirect reference. The inner array is also an indirect reference - but any element accessed on the inner array are direct reference - and so you detect a leak there. Correct? ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Wed Jan 11 00:07:14 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Wed, 11 Jan 2023 00:07:14 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v5] In-Reply-To: <8PxlV-Syo2Y48TBgSQupSjArfJxMqnA8BZQIYTfYGPA=.057f204c-330b-4fb9-96e5-f8dc8fe348aa@github.com> References: <_GkLRl5VTNh8ToJ3cjF-_v9j6eWWQzbUCCKStOXKh4g=.5e9505f1-8182-47e6-a8ed-78982db36c94@github.com> <8PxlV-Syo2Y48TBgSQupSjArfJxMqnA8BZQIYTfYGPA=.057f204c-330b-4fb9-96e5-f8dc8fe348aa@github.com> Message-ID: On Tue, 10 Jan 2023 23:45:59 GMT, Maurizio Cimadamore wrote: >> It's slightly different from that. >> >> Considering any of the various things in scope that can point to an object (these are: the current 'this' instance, the current outer 'this' instance, method parameter/variable, method return value, top of Java stack), such a thing has a "direct" reference if it might possibly _directly_ point to the 'this' we're tracking, while a thing has an "indirect" reference if it might possibly point to the 'this' we're tracking through _at least one level of indirection_. >> >> This is just an attempt to eliminate some false positives by distinguishing between those two cases. Originally I was going to try to track fields (in a very limited way), and so this distinction was going to be more important, but even without tracking fields it's still useful. For example, if some method invokes `x.y.foo()` and `x` represents a direct but not an indirect 'this' reference, then there is no leak declared. >> >> Considering the other options... (a) if you only track direct references, then you suffer from more false negatives (how many? unclear); (b) if you lump direct and indirect references into one bucket, then you suffer from more false positives (as in previous example `x.y.foo()`). >> >> You can see an example of an indirect reference being tracked and exposed in the unit test `ThisEscapeArrayElement.java`. >> >> Another motivating example is lambdas. The act of simply _creating_ a lambda never creates a leak, and a lambda never represents a _direct_ reference. But it might represent an _indirect_ reference. > > So, if I understand correctly your array element test, when we have `new Object[][] { { this } }` the analysis is able to detect that there might be some direct reference nested inside the array. So the outer array is an indirect reference. The inner array is also an indirect reference - but any element accessed on the inner array are direct reference - and so you detect a leak there. Correct? Yes - although it's not tracked being tracked any more precisely than "one or more levels of indirection". And of course by "reference" we only mean "the possibility of a reference" - in general we don't know for sure. Here's the logic: * The analysis knows `this` is a direct reference * Therefore the array expression `{ this }` has an indirect reference (but no direct reference) * The outer array expression `{ { this } }` therefore _also_ has an indirect reference (but no direct reference) At this point, we don't know how many levels of indirection there are in `array` though.... only that its ? 1. * There expression `array[0]` therefore is determined to have both direct and indirect references (they are both _possible_ because we've dereferenced something with an indirect reference) * As does `array[0][0]` for the same reason So invoking `array[0][0].hashCode()` means invoking `hashCode()` on something that has a possible direct reference, and is therefore a leak. Note that because of the imprecision in the number of levels of indirection, invoking `array[0].hashCode()` would also have generated a warning - but in that case, a false positive. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From mcimadamore at openjdk.org Wed Jan 11 00:07:15 2023 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Wed, 11 Jan 2023 00:07:15 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v5] In-Reply-To: References: <_GkLRl5VTNh8ToJ3cjF-_v9j6eWWQzbUCCKStOXKh4g=.5e9505f1-8182-47e6-a8ed-78982db36c94@github.com> Message-ID: On Tue, 10 Jan 2023 19:20:35 GMT, Archie L. Cobbs wrote: >> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 1098: >> >>> 1096: private void visitLooped(T tree, Consumer visitor) { >>> 1097: this.visitScoped(tree, false, t -> { >>> 1098: while (true) { >> >> Why is this needed? Can the tracking state of `this` change after multiple "execution" of the same code? > > Yes, because the 'this' reference can bounce around through different variables in scope each time around the loop. So we have to repeat the loop until all 'this' references have "flooded" into all the nooks and crannies. > > The `ThisEscapeLoop.java` unit test demonstrates: > > public class ThisEscapeLoop { > > public ThisEscapeLoop() { > ThisEscapeLoop ref1 = this; > ThisEscapeLoop ref2 = null; > ThisEscapeLoop ref3 = null; > ThisEscapeLoop ref4 = null; > for (int i = 0; i < 100; i++) { > ref4 = ref3; > ref3 = ref2; > ref2 = ref1; > if (ref4 != null) > ref4.mightLeak(); > } > } > > public void mightLeak() { > } > } So, if the code was be like this: ThisEscapeLoop ref11 = this; ThisEscapeLoop ref12 = null; ThisEscapeLoop ref13 = null; ThisEscapeLoop ref14 = null; for (int i = 0; i < 100; i++) { ref14 = ref13; ref13 = ref12; ref12 = ref11; ThisEscapeLoop ref21 = ref14; ThisEscapeLoop ref22 = null; ThisEscapeLoop ref23 = null; ThisEscapeLoop ref24 = null; for (int i = 0; i < 100; i++) { ref24 = ref23; ref23 = ref22; ref22 = ref21; if (ref24 != null) ref24.mightLeak(); } } Then it would take not 3 iterations but 3 * 3 to figure out that it is a potential leak? ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Wed Jan 11 00:25:10 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Wed, 11 Jan 2023 00:25:10 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v5] In-Reply-To: References: <_GkLRl5VTNh8ToJ3cjF-_v9j6eWWQzbUCCKStOXKh4g=.5e9505f1-8182-47e6-a8ed-78982db36c94@github.com> Message-ID: On Wed, 11 Jan 2023 00:04:14 GMT, Maurizio Cimadamore wrote: >> Yes, because the 'this' reference can bounce around through different variables in scope each time around the loop. So we have to repeat the loop until all 'this' references have "flooded" into all the nooks and crannies. >> >> The `ThisEscapeLoop.java` unit test demonstrates: >> >> public class ThisEscapeLoop { >> >> public ThisEscapeLoop() { >> ThisEscapeLoop ref1 = this; >> ThisEscapeLoop ref2 = null; >> ThisEscapeLoop ref3 = null; >> ThisEscapeLoop ref4 = null; >> for (int i = 0; i < 100; i++) { >> ref4 = ref3; >> ref3 = ref2; >> ref2 = ref1; >> if (ref4 != null) >> ref4.mightLeak(); >> } >> } >> >> public void mightLeak() { >> } >> } > > So, if the code was be like this: > > > ThisEscapeLoop ref11 = this; > ThisEscapeLoop ref12 = null; > ThisEscapeLoop ref13 = null; > ThisEscapeLoop ref14 = null; > for (int i = 0; i < 100; i++) { > ref14 = ref13; > ref13 = ref12; > ref12 = ref11; > ThisEscapeLoop ref21 = ref14; > ThisEscapeLoop ref22 = null; > ThisEscapeLoop ref23 = null; > ThisEscapeLoop ref24 = null; > for (int i = 0; i < 100; i++) { > ref24 = ref23; > ref23 = ref22; > ref22 = ref21; > if (ref24 != null) > ref24.mightLeak(); > } > } > > > Then it would take not 3 iterations but 3 * 3 to figure out that it is a potential leak? Actually I think it would take 1 + 1 + 3 iterations. During the first two iterations of the outer loop, nothing changes after the first go round of the inner loop - i.e., the total set of possible references in existence does not change, because all of the assignments in the inner loop won't involve any 'this' references. It's only the during the third iteration of the outer loop that any 'this' references seep into any of the variables seen by the inner loop. Then it will take 3 cycles for the reference set to converge again. However, this is not to say that there aren't some pathological examples out there. I guess the question is could they exist in "normal" code. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Wed Jan 11 03:30:03 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Wed, 11 Jan 2023 03:30:03 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: Message-ID: > This PR adds a new lint warning category `this-escape`. > > It also adds `@SuppressWarnings` annotations as needed to the JDK itself to allow the JDK to continue to compile with `-Xlint:all`. > > A 'this' escape warning is generated for a constructor `A()` in a class `A` when the compiler detects that the following situation is _in theory possible:_ > * Some subclass `B extends A` exists, and `B` is defined in a separate source file (i.e., compilation unit) > * Some constructor `B()` of `B` invokes `A()` as its superclass constructor > * During the execution of `A()`, some non-static method of `B.foo()` could get invoked, perhaps indirectly > > In the above scenario, `B.foo()` would execute before `A()` has returned and before `B()` has performed any initialization. To the extent `B.foo()` accesses any fields of `B` - all of which are still uninitialized - it is likely to function incorrectly. > > Note, when determining if a 'this' escape is possible, the compiler makes no assumptions about code outside of the current compilation unit. It doesn't look outside of the current source file to see what might actually happen when a method is invoked. It does follow method and constructors within the current compilation unit, and applies a simplified union-of-all-possible-branches data flow analysis to see where 'this' could end up. > > From my review, virtually all of the warnings generated in the various JDK modules are valid warnings in the sense that a 'this' escape, as defined above, is really and truly possible. However, that doesn't imply that any bugs were found within the JDK - only that the possibility of a certain type of bug exists if certain superclass constructors are used by someone, somewhere, someday. > > For several "popular" classes, this PR also adds `@implNote`'s to the offending constructors so that subclass implementors are made aware of the threat. For one example, `TreeMap(Map)` invokes `putAll()` and `put()`. > > More details and a couple of motivating examples are given in an included [doc file](https://github.com/archiecobbs/jdk/blob/ThisEscape/src/java.base/share/classes/java/lang/doc-files/ThisEscape.html) that these `@implNote`'s link to. See also the recent thread on `amber-dev` for some background. > > Ideally, over time the owners of the various modules would review their `@SuppressWarnings("this-escape")` annotations and determine which other constructors also warranted such an `@implNote`. > > Because of all the`@SuppressWarnings` annotations, this PR touches a bunch of different JDK modules. My apologies for that. Adding these annotations was determined to be the more conservative approach, as compared to just excepting `this-escape` from various module builds globally. > > **Patch Navigation Guide** > > * Non-trivial compiler changes: > * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties` > > * Javadoc additions of `@implNote`: > > * `src/java.base/share/classes/java/io/PipedReader.java` > * `src/java.base/share/classes/java/io/PipedWriter.java` > * `src/java.base/share/classes/java/lang/Throwable.java` > * `src/java.base/share/classes/java/util/ArrayDeque.java` > * `src/java.base/share/classes/java/util/EnumMap.java` > * `src/java.base/share/classes/java/util/HashSet.java` > * `src/java.base/share/classes/java/util/Hashtable.java` > * `src/java.base/share/classes/java/util/LinkedList.java` > * `src/java.base/share/classes/java/util/TreeMap.java` > * `src/java.base/share/classes/java/util/TreeSet.java` > > * New unit tests > * `test/langtools/tools/javac/warnings/ThisEscape/*.java` > > * **Everything else** is just adding `@SuppressWarnings("this-escape")` Archie L. Cobbs has updated the pull request incrementally with two additional commits since the last revision: - Use the more appropriate Type comparison method Types.isSameType(). - Add some more comments to clarify how the analysis works. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/11874/files - new: https://git.openjdk.org/jdk/pull/11874/files/d70d12f4..6e96a7d7 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=11874&range=06 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=11874&range=05-06 Stats: 31 lines in 2 files changed: 16 ins; 10 del; 5 mod Patch: https://git.openjdk.org/jdk/pull/11874.diff Fetch: git fetch https://git.openjdk.org/jdk pull/11874/head:pull/11874 PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Wed Jan 11 03:30:05 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Wed, 11 Jan 2023 03:30:05 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v5] In-Reply-To: <0Hksmg2eLQg0c9W5CB6y6dXw2vaEXxy-UY9_D0DtLQY=.351da0ec-208c-4f8d-bf16-318de07ca63e@github.com> References: <_GkLRl5VTNh8ToJ3cjF-_v9j6eWWQzbUCCKStOXKh4g=.5e9505f1-8182-47e6-a8ed-78982db36c94@github.com> <0Hksmg2eLQg0c9W5CB6y6dXw2vaEXxy-UY9_D0DtLQY=.351da0ec-208c-4f8d-bf16-318de07ca63e@github.com> Message-ID: <7jUSzUYT_eWYGbHkDes10f2-1i5DNdmDGDACe8qsXU4=.5bca0f1b-e004-48bc-87e0-48d6fb9deb96@github.com> On Tue, 10 Jan 2023 23:38:14 GMT, Maurizio Cimadamore wrote: >> OK I'm glad you pointed that out because I'm a little unclear on the best way to do this bit. >> >> Just to confirm, you are saying that this: >> >> `if (erasure(type).equalsIgnoreMetadata(outerType)) {` >> >> should be replaced with this? >> >> `if (isSameType(type, outerType)) {` > > yes Thanks... updated in `6e96a7d76f8`. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From jlahoda at openjdk.org Wed Jan 11 07:25:23 2023 From: jlahoda at openjdk.org (Jan Lahoda) Date: Wed, 11 Jan 2023 07:25:23 GMT Subject: RFR: 8299902: Support for MarkDown javadoc in JShell Message-ID: Adding support for MarkDown javadoc in the JShell ------------- Depends on: https://git.openjdk.org/jdk/pull/11701 Commit messages: - Cleanup. - Post-merge updates. - Merge branch '8298405.doclet-markdown' into markdown-in-jshell - Improving handling of new trees. - Prototype of MarkDown javadoc support for JShell. Changes: https://git.openjdk.org/jdk/pull/11936/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=11936&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8299902 Stats: 1705 lines in 9 files changed: 947 ins; 752 del; 6 mod Patch: https://git.openjdk.org/jdk/pull/11936.diff Fetch: git fetch https://git.openjdk.org/jdk pull/11936/head:pull/11936 PR: https://git.openjdk.org/jdk/pull/11936 From asotona at openjdk.org Wed Jan 11 08:34:22 2023 From: asotona at openjdk.org (Adam Sotona) Date: Wed, 11 Jan 2023 08:34:22 GMT Subject: Integrated: 8299829: In jshell, the output of "0".repeat(49999)+"2" ends with a '0' In-Reply-To: References: Message-ID: On Tue, 10 Jan 2023 15:42:31 GMT, Adam Sotona wrote: > "0".repeat(49999)+"2" correctly evaluates to a string with a terminating '2'. > However, jshell outputs it with a terminating '0'. > > Jshell provides double truncation of long Strings. > One is performed in jdk.jshell.execution.ExecutionControlForwarder to fit into MAX_UTF_CHARS = 21844 (which is exactly the point where "2" disappears). > Second truncation is performed in jdk.internal.jshell.tool.Feedback to fit presentation requirements. > While ExecutionControlForwarder truncates right part of the String, Feedback truncated inner part in 2/3 and joins the parts with " ... ". > > Proposed patch fixes ExecutionControlForwarder to truncate long Strings the same way as Feedback, so the right part of any long String won't disappear and double or repeated truncation provides consistent results. > > Please review :) > > Thanks, > Adam This pull request has now been integrated. Changeset: 030e88d6 Author: Adam Sotona URL: https://git.openjdk.org/jdk/commit/030e88d63844f185b839977ff1b19bbc4fe688e8 Stats: 8 lines in 2 files changed: 5 ins; 0 del; 3 mod 8299829: In jshell, the output of "0".repeat(49999)+"2" ends with a '0' Reviewed-by: jlahoda ------------- PR: https://git.openjdk.org/jdk/pull/11927 From jlahoda at openjdk.org Wed Jan 11 09:02:11 2023 From: jlahoda at openjdk.org (Jan Lahoda) Date: Wed, 11 Jan 2023 09:02:11 GMT Subject: RFR: 8296789: -completion in jshell fails to expose synthetic bridge methods In-Reply-To: References: Message-ID: <5_1TqHsgG5qYGFndg7uDvsMJ2NkINbuVZ9LplfuQtes=.0822958d-8dc1-48e0-9d99-315f1bcc1d93@github.com> On Mon, 2 Jan 2023 16:57:54 GMT, Adam Sotona wrote: > Jshell does not propose completion for members declared in inaccessible parent classes (for example AbstractStringBuilder). > > This patch fixes the completion in SourceCodeAnalysisImpl using MethodSymbols and VarSymbols clones with altered enclosing elements. For documentation purpose (print of the enclosing classes) the original enclosing element is restored. > > The patch also includes new CompletionSuggestionTest::testPerentMembers > > Please review. > > Thanks, > Adam Ok. ------------- Marked as reviewed by jlahoda (Reviewer). PR: https://git.openjdk.org/jdk/pull/11814 From asotona at openjdk.org Wed Jan 11 09:24:19 2023 From: asotona at openjdk.org (Adam Sotona) Date: Wed, 11 Jan 2023 09:24:19 GMT Subject: Integrated: 8296789: -completion in jshell fails to expose synthetic bridge methods In-Reply-To: References: Message-ID: <2t6w5-czoY2cPtzaG2dnqNP33NqGFMSuwyA8efEUe2U=.bfba53ce-319f-4f03-9197-3c690b3e5c31@github.com> On Mon, 2 Jan 2023 16:57:54 GMT, Adam Sotona wrote: > Jshell does not propose completion for members declared in inaccessible parent classes (for example AbstractStringBuilder). > > This patch fixes the completion in SourceCodeAnalysisImpl using MethodSymbols and VarSymbols clones with altered enclosing elements. For documentation purpose (print of the enclosing classes) the original enclosing element is restored. > > The patch also includes new CompletionSuggestionTest::testPerentMembers > > Please review. > > Thanks, > Adam This pull request has now been integrated. Changeset: 257f667a Author: Adam Sotona URL: https://git.openjdk.org/jdk/commit/257f667afb3dfaefb9a5a6916472066257ca0788 Stats: 24 lines in 2 files changed: 19 ins; 0 del; 5 mod 8296789: -completion in jshell fails to expose synthetic bridge methods Reviewed-by: jlahoda ------------- PR: https://git.openjdk.org/jdk/pull/11814 From jlaskey at openjdk.org Wed Jan 11 13:57:29 2023 From: jlaskey at openjdk.org (Jim Laskey) Date: Wed, 11 Jan 2023 13:57:29 GMT Subject: RFR: JDK-8285932 Implementation of JEP 430 String Templates (Preview) [v33] In-Reply-To: References: Message-ID: > Enhance the Java programming language with string templates, which are similar to string literals but contain embedded expressions. A string template is interpreted at run time by replacing each expression with the result of evaluating that expression, possibly after further validation and transformation. This is a [preview language feature and API](http://openjdk.java.net/jeps/12). Jim Laskey has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 48 commits: - Merge branch 'master' into 8285932 - Merge branch 'master' into 8285932 - FormatProcessor changes - Update @since - Requested changes #12 - Seal Digits - Requested changes #11 - Typo - Requested changes #10 - Requested changes #9 - ... and 38 more: https://git.openjdk.org/jdk/compare/87238470...098467f0 ------------- Changes: https://git.openjdk.org/jdk/pull/10889/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=10889&range=32 Stats: 9519 lines in 81 files changed: 9356 ins; 28 del; 135 mod Patch: https://git.openjdk.org/jdk/pull/10889.diff Fetch: git fetch https://git.openjdk.org/jdk pull/10889/head:pull/10889 PR: https://git.openjdk.org/jdk/pull/10889 From jlaskey at openjdk.org Wed Jan 11 14:07:53 2023 From: jlaskey at openjdk.org (Jim Laskey) Date: Wed, 11 Jan 2023 14:07:53 GMT Subject: RFR: JDK-8285932 Implementation of JEP 430 String Templates (Preview) [v34] In-Reply-To: References: Message-ID: > Enhance the Java programming language with string templates, which are similar to string literals but contain embedded expressions. A string template is interpreted at run time by replacing each expression with the result of evaluating that expression, possibly after further validation and transformation. This is a [preview language feature and API](http://openjdk.java.net/jeps/12). Jim Laskey has updated the pull request incrementally with one additional commit since the last revision: Update to JDK 21 ------------- Changes: - all: https://git.openjdk.org/jdk/pull/10889/files - new: https://git.openjdk.org/jdk/pull/10889/files/098467f0..57638f97 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=10889&range=33 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=10889&range=32-33 Stats: 7 lines in 7 files changed: 0 ins; 0 del; 7 mod Patch: https://git.openjdk.org/jdk/pull/10889.diff Fetch: git fetch https://git.openjdk.org/jdk pull/10889/head:pull/10889 PR: https://git.openjdk.org/jdk/pull/10889 From mcimadamore at openjdk.org Wed Jan 11 14:15:18 2023 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Wed, 11 Jan 2023 14:15:18 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v5] In-Reply-To: References: <_GkLRl5VTNh8ToJ3cjF-_v9j6eWWQzbUCCKStOXKh4g=.5e9505f1-8182-47e6-a8ed-78982db36c94@github.com> Message-ID: On Wed, 11 Jan 2023 00:22:03 GMT, Archie L. Cobbs wrote: >> So, if the code was be like this: >> >> >> ThisEscapeLoop ref11 = this; >> ThisEscapeLoop ref12 = null; >> ThisEscapeLoop ref13 = null; >> ThisEscapeLoop ref14 = null; >> for (int i = 0; i < 100; i++) { >> ref14 = ref13; >> ref13 = ref12; >> ref12 = ref11; >> ThisEscapeLoop ref21 = ref14; >> ThisEscapeLoop ref22 = null; >> ThisEscapeLoop ref23 = null; >> ThisEscapeLoop ref24 = null; >> for (int i = 0; i < 100; i++) { >> ref24 = ref23; >> ref23 = ref22; >> ref22 = ref21; >> if (ref24 != null) >> ref24.mightLeak(); >> } >> } >> >> >> Then it would take not 3 iterations but 3 * 3 to figure out that it is a potential leak? > > Actually I think it would take 1 + 1 + 3 iterations. > > During the first two iterations of the outer loop, nothing changes after the first go round of the inner loop - i.e., the total set of possible references in existence does not change, because all of the assignments in the inner loop won't involve any 'this' references. > > It's only the during the third iteration of the outer loop that any 'this' references seep into any of the variables seen by the inner loop. Then it will take 3 cycles for the reference set to converge again. > > However, this is not to say that there aren't some pathological examples out there. I guess the question is could they exist in "normal" code. True - probably 3 * 3 can be achieved if this: ThisEscapeLoop ref21 = ref14; Is replaced with ThisEscapeLoop ref21 = this; In which case the inner loop won't converge immediately (as it will have to propagate from ref21 to ref22 to ref23 to ref24). I guess what I'm uncomfortable with is that we have effectively unbounded computation here (especially when we also consider the fact that the analysis "follows" method bodies as well, if they are found in the same compilation unit). I suggest one experiment where you: 1. downgrade the warnings to notes (so that they won't make the JDK build fail) 2. enable this Lint everywhere 3. compare JDK `clean images` time w/ and w/o the Lint ------------- PR: https://git.openjdk.org/jdk/pull/11874 From mcimadamore at openjdk.org Wed Jan 11 16:02:16 2023 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Wed, 11 Jan 2023 16:02:16 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: Message-ID: On Wed, 11 Jan 2023 03:30:03 GMT, Archie L. Cobbs wrote: >> This PR adds a new lint warning category `this-escape`. >> >> It also adds `@SuppressWarnings` annotations as needed to the JDK itself to allow the JDK to continue to compile with `-Xlint:all`. >> >> A 'this' escape warning is generated for a constructor `A()` in a class `A` when the compiler detects that the following situation is _in theory possible:_ >> * Some subclass `B extends A` exists, and `B` is defined in a separate source file (i.e., compilation unit) >> * Some constructor `B()` of `B` invokes `A()` as its superclass constructor >> * During the execution of `A()`, some non-static method of `B.foo()` could get invoked, perhaps indirectly >> >> In the above scenario, `B.foo()` would execute before `A()` has returned and before `B()` has performed any initialization. To the extent `B.foo()` accesses any fields of `B` - all of which are still uninitialized - it is likely to function incorrectly. >> >> Note, when determining if a 'this' escape is possible, the compiler makes no assumptions about code outside of the current compilation unit. It doesn't look outside of the current source file to see what might actually happen when a method is invoked. It does follow method and constructors within the current compilation unit, and applies a simplified union-of-all-possible-branches data flow analysis to see where 'this' could end up. >> >> From my review, virtually all of the warnings generated in the various JDK modules are valid warnings in the sense that a 'this' escape, as defined above, is really and truly possible. However, that doesn't imply that any bugs were found within the JDK - only that the possibility of a certain type of bug exists if certain superclass constructors are used by someone, somewhere, someday. >> >> For several "popular" classes, this PR also adds `@implNote`'s to the offending constructors so that subclass implementors are made aware of the threat. For one example, `TreeMap(Map)` invokes `putAll()` and `put()`. >> >> More details and a couple of motivating examples are given in an included [doc file](https://github.com/archiecobbs/jdk/blob/ThisEscape/src/java.base/share/classes/java/lang/doc-files/ThisEscape.html) that these `@implNote`'s link to. See also the recent thread on `amber-dev` for some background. >> >> Ideally, over time the owners of the various modules would review their `@SuppressWarnings("this-escape")` annotations and determine which other constructors also warranted such an `@implNote`. >> >> Because of all the`@SuppressWarnings` annotations, this PR touches a bunch of different JDK modules. My apologies for that. Adding these annotations was determined to be the more conservative approach, as compared to just excepting `this-escape` from various module builds globally. >> >> **Patch Navigation Guide** >> >> * Non-trivial compiler changes: >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties` >> >> * Javadoc additions of `@implNote`: >> >> * `src/java.base/share/classes/java/io/PipedReader.java` >> * `src/java.base/share/classes/java/io/PipedWriter.java` >> * `src/java.base/share/classes/java/lang/Throwable.java` >> * `src/java.base/share/classes/java/util/ArrayDeque.java` >> * `src/java.base/share/classes/java/util/EnumMap.java` >> * `src/java.base/share/classes/java/util/HashSet.java` >> * `src/java.base/share/classes/java/util/Hashtable.java` >> * `src/java.base/share/classes/java/util/LinkedList.java` >> * `src/java.base/share/classes/java/util/TreeMap.java` >> * `src/java.base/share/classes/java/util/TreeSet.java` >> >> * New unit tests >> * `test/langtools/tools/javac/warnings/ThisEscape/*.java` >> >> * **Everything else** is just adding `@SuppressWarnings("this-escape")` > > Archie L. Cobbs has updated the pull request incrementally with two additional commits since the last revision: > > - Use the more appropriate Type comparison method Types.isSameType(). > - Add some more comments to clarify how the analysis works. More questions. Let's say that we only tracked escaping of direct references to `this`. Do you have any sense of how many "less" warnings would be reported in real code (e.g. JDK) ? What I mean by this - let's say that we don't care about tracking _where_ `this` ends up going exactly (e.g. if it's aliased by another variable) - and perhaps also let's say we don't care about inspecting the method to which `this` is leaked too closely - e.g. we treat any early escape of `this` as a possible issue. Of course you could construct examples (like your tests) in which such a simplistic analysis would be defeated. What I'm interested in though is what incremental improvement is brought by the more complex analysis you have in this PR? ------------- PR: https://git.openjdk.org/jdk/pull/11874 From mcimadamore at openjdk.org Wed Jan 11 16:17:16 2023 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Wed, 11 Jan 2023 16:17:16 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v5] In-Reply-To: References: <_GkLRl5VTNh8ToJ3cjF-_v9j6eWWQzbUCCKStOXKh4g=.5e9505f1-8182-47e6-a8ed-78982db36c94@github.com> Message-ID: On Wed, 11 Jan 2023 14:12:46 GMT, Maurizio Cimadamore wrote: >> Actually I think it would take 1 + 1 + 3 iterations. >> >> During the first two iterations of the outer loop, nothing changes after the first go round of the inner loop - i.e., the total set of possible references in existence does not change, because all of the assignments in the inner loop won't involve any 'this' references. >> >> It's only the during the third iteration of the outer loop that any 'this' references seep into any of the variables seen by the inner loop. Then it will take 3 cycles for the reference set to converge again. >> >> However, this is not to say that there aren't some pathological examples out there. I guess the question is could they exist in "normal" code. > > True - probably 3 * 3 can be achieved if this: > > > ThisEscapeLoop ref21 = ref14; > > Is replaced with > > > ThisEscapeLoop ref21 = this; > > > In which case the inner loop won't converge immediately (as it will have to propagate from ref21 to ref22 to ref23 to ref24). > > I guess what I'm uncomfortable with is that we have effectively unbounded computation here (especially when we also consider the fact that the analysis "follows" method bodies as well, if they are found in the same compilation unit). > > I suggest one experiment where you: > 1. downgrade the warnings to notes (so that they won't make the JDK build fail) > 2. enable this Lint everywhere > 3. compare JDK `clean images` time w/ and w/o the Lint Also, looking at the loop test more closely, it seems to me that what the compiler needs to do is to prove that there can be possible paths by which a `this` can land into ref4. If we build a graph of all the assignments, we get: ref4 <- ref3 <- ref2 <- ref1 <- this So, if we ask "can ref4 possibly contain `this`?" we could "walk" the variable dependencies backwards and discover that, yes, there exist a possible path in which `this` would get there. Now, of course without a loop this can never be a real issue (since you can never send a `this` fully down the chain) - but again, this is a question of how much effort should be spend to handle false negatives in what look like a pathological case. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Wed Jan 11 18:47:14 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Wed, 11 Jan 2023 18:47:14 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v5] In-Reply-To: References: <_GkLRl5VTNh8ToJ3cjF-_v9j6eWWQzbUCCKStOXKh4g=.5e9505f1-8182-47e6-a8ed-78982db36c94@github.com> Message-ID: <0VZaG4s1DCehTwPfEshM6Lt90CKit-D-w_4F8NzAw8c=.b515334e-a4d3-495d-afae-6e4aa45ff683@github.com> On Wed, 11 Jan 2023 16:14:24 GMT, Maurizio Cimadamore wrote: >> True - probably 3 * 3 can be achieved if this: >> >> >> ThisEscapeLoop ref21 = ref14; >> >> Is replaced with >> >> >> ThisEscapeLoop ref21 = this; >> >> >> In which case the inner loop won't converge immediately (as it will have to propagate from ref21 to ref22 to ref23 to ref24). >> >> I guess what I'm uncomfortable with is that we have effectively unbounded computation here (especially when we also consider the fact that the analysis "follows" method bodies as well, if they are found in the same compilation unit). >> >> I suggest one experiment where you: >> 1. downgrade the warnings to notes (so that they won't make the JDK build fail) >> 2. enable this Lint everywhere >> 3. compare JDK `clean images` time w/ and w/o the Lint > > Also, looking at the loop test more closely, it seems to me that what the compiler needs to do is to prove that there can be possible paths by which a `this` can land into ref4. > > If we build a graph of all the assignments, we get: > > ref4 <- ref3 <- ref2 <- ref1 <- this > > So, if we ask "can ref4 possibly contain `this`?" we could "walk" the variable dependencies backwards and discover that, yes, there exist a possible path in which `this` would get there. > > Now, of course without a loop this can never be a real issue (since you can never send a `this` fully down the chain) - but again, this is a question of how much effort should be spend to handle false negatives in what look like a pathological case. Good idea. Looks like the difference is in the noise, at least on my Macbook: Builds of master (jdk-21+3-69-gc6588d5bb3f) ================================== Build times: real 2m24.650s user 13m46.727s sys 2m33.554s real 2m27.224s user 13m43.464s sys 2m37.251s real 2m26.658s user 13m42.578s sys 2m36.133s Builds of ThisEscape (jdk-21+3-125-g6e96a7d76f8) ================================== Modifications: - Reverted files in the make/ subdirectory to enable warning - Commented out lines 363-382 in ThisEscapeAnalyzer.java so no warnings are actually reported Build times: real 2m25.912s user 13m45.860s sys 2m32.741s real 2m27.213s user 13m44.830s sys 2m36.596s real 2m25.756s user 13m42.889s sys 2m35.659s ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Wed Jan 11 19:13:16 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Wed, 11 Jan 2023 19:13:16 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v5] In-Reply-To: <0VZaG4s1DCehTwPfEshM6Lt90CKit-D-w_4F8NzAw8c=.b515334e-a4d3-495d-afae-6e4aa45ff683@github.com> References: <_GkLRl5VTNh8ToJ3cjF-_v9j6eWWQzbUCCKStOXKh4g=.5e9505f1-8182-47e6-a8ed-78982db36c94@github.com> <0VZaG4s1DCehTwPfEshM6Lt90CKit-D-w_4F8NzAw8c=.b515334e-a4d3-495d-afae-6e4aa45ff683@github.com> Message-ID: On Wed, 11 Jan 2023 18:44:20 GMT, Archie L. Cobbs wrote: >> Also, looking at the loop test more closely, it seems to me that what the compiler needs to do is to prove that there can be possible paths by which a `this` can land into ref4. >> >> If we build a graph of all the assignments, we get: >> >> ref4 <- ref3 <- ref2 <- ref1 <- this >> >> So, if we ask "can ref4 possibly contain `this`?" we could "walk" the variable dependencies backwards and discover that, yes, there exist a possible path in which `this` would get there. >> >> Now, of course without a loop this can never be a real issue (since you can never send a `this` fully down the chain) - but again, this is a question of how much effort should be spend to handle false negatives in what look like a pathological case. > > Good idea. Looks like the difference is in the noise, at least on my Macbook: > > Builds of master (jdk-21+3-69-gc6588d5bb3f) > ================================== > > Build times: > > real 2m24.650s > user 13m46.727s > sys 2m33.554s > > real 2m27.224s > user 13m43.464s > sys 2m37.251s > > real 2m26.658s > user 13m42.578s > sys 2m36.133s > > Builds of ThisEscape (jdk-21+3-125-g6e96a7d76f8) > ================================== > > Modifications: > > - Reverted files in the make/ subdirectory to enable warning > - Commented out lines 363-382 in ThisEscapeAnalyzer.java > so no warnings are actually reported > > Build times: > > real 2m25.912s > user 13m45.860s > sys 2m32.741s > > real 2m27.213s > user 13m44.830s > sys 2m36.596s > > real 2m25.756s > user 13m42.889s > sys 2m35.659s Regarding the assignment graph approach, I think that would work if the references are bouncing around strictly between variables, but what if the chain includes any of the more complicated stuff that is currently being tracked, such as various Java expressions, method invocations, conditionals, etc.? Consider this example: public class ThisEscapeLoop { public ThisEscapeLoop() { ThisEscapeLoop ref1 = this; ThisEscapeLoop ref2 = null; ThisEscapeLoop ref3 = null; ThisEscapeLoop ref4 = null; for (int i = 0; i < 100; i++) { ref4 = this.returnMe(ref3); ref3 = ref2; ref2 = ref1; if (ref4 != null) ref4.mightLeak(); } } public T returnMe(T x) { return x; } public void mightLeak() { } } If you are only looking at variable assignments with values that are other variables, then the chain "breaks" when `ref4` is assigned indirectly via `returnMe()`, and you miss the leak. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Wed Jan 11 19:47:16 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Wed, 11 Jan 2023 19:47:16 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: Message-ID: On Wed, 11 Jan 2023 15:59:29 GMT, Maurizio Cimadamore wrote: > What I'm interested in though is what incremental improvement is brought by the more complex analysis you have in this PR? It's a good question. Here are some thoughts... One meta-goal is that this analysis be conservative. In other words, if your code does NOT generate any warnings, then you should feel confident that there is a high probability that there are no leaks. This is analogous to how you can be confident that you won't get any `ClassCastExceptions` at runtime if your code doesn't generate any `unchecked` warnings at compile time. I think this point is generally agreed upon. If so, then we would want?any simpler analysis to err on the side of generating more false positives rather than more false negatives. Assuming that, then the question comes down to a trade-off between code complexity vs. rate of false positives. >From my casual looking over the JDK, the current algorithm generates very few false positives - almost all of the warnings represent actual leaks (I'd be interested in any false positives you do see). (Of course, an irony is that most of these leaks have no real-world effect. For example package-private classes in the JDK (a) have already been debugged long ago, so any intra-package bugs due to 'this' escapes have already been fixed; and (b) are unlikely to be subclassed by anyone. And the ones that have a real-world effect (e.g., `HashSet(Collection)`) can't be fixed because of backward compatibility concerns. So this warning is most useful when writing new code.) So the current code is clearly "complex enough" already. FWIW that's ~975 lines of code excluding blank lines and comments. Now to answer your question about a theoretical simpler analysis: > let's say that we don't care about tracking where `this` ends up going exactly (e.g. if it's aliased by another variable) - and perhaps also let's say we don't care about inspecting the method to which `this` is leaked too closely - e.g. we treat any early escape of this as a possible issue. I'm not sure I completely understand the semantics. But are you saying that if a constructor invokes a private or static method, then this simpler analysis would always declare a leak? If that's the case then I think there are a lot of new false positives, because this is common in constructors. I would then worry that if we dilute the warnings with a bunch of new false positives people are just going to get discouraged and turn the warning off completely. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From darcy at openjdk.org Wed Jan 11 20:51:17 2023 From: darcy at openjdk.org (Joe Darcy) Date: Wed, 11 Jan 2023 20:51:17 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: Message-ID: On Wed, 11 Jan 2023 03:30:03 GMT, Archie L. Cobbs wrote: >> This PR adds a new lint warning category `this-escape`. >> >> It also adds `@SuppressWarnings` annotations as needed to the JDK itself to allow the JDK to continue to compile with `-Xlint:all`. >> >> A 'this' escape warning is generated for a constructor `A()` in a class `A` when the compiler detects that the following situation is _in theory possible:_ >> * Some subclass `B extends A` exists, and `B` is defined in a separate source file (i.e., compilation unit) >> * Some constructor `B()` of `B` invokes `A()` as its superclass constructor >> * During the execution of `A()`, some non-static method of `B.foo()` could get invoked, perhaps indirectly >> >> In the above scenario, `B.foo()` would execute before `A()` has returned and before `B()` has performed any initialization. To the extent `B.foo()` accesses any fields of `B` - all of which are still uninitialized - it is likely to function incorrectly. >> >> Note, when determining if a 'this' escape is possible, the compiler makes no assumptions about code outside of the current compilation unit. It doesn't look outside of the current source file to see what might actually happen when a method is invoked. It does follow method and constructors within the current compilation unit, and applies a simplified union-of-all-possible-branches data flow analysis to see where 'this' could end up. >> >> From my review, virtually all of the warnings generated in the various JDK modules are valid warnings in the sense that a 'this' escape, as defined above, is really and truly possible. However, that doesn't imply that any bugs were found within the JDK - only that the possibility of a certain type of bug exists if certain superclass constructors are used by someone, somewhere, someday. >> >> For several "popular" classes, this PR also adds `@implNote`'s to the offending constructors so that subclass implementors are made aware of the threat. For one example, `TreeMap(Map)` invokes `putAll()` and `put()`. >> >> More details and a couple of motivating examples are given in an included [doc file](https://github.com/archiecobbs/jdk/blob/ThisEscape/src/java.base/share/classes/java/lang/doc-files/ThisEscape.html) that these `@implNote`'s link to. See also the recent thread on `amber-dev` for some background. >> >> Ideally, over time the owners of the various modules would review their `@SuppressWarnings("this-escape")` annotations and determine which other constructors also warranted such an `@implNote`. >> >> Because of all the`@SuppressWarnings` annotations, this PR touches a bunch of different JDK modules. My apologies for that. Adding these annotations was determined to be the more conservative approach, as compared to just excepting `this-escape` from various module builds globally. >> >> **Patch Navigation Guide** >> >> * Non-trivial compiler changes: >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties` >> >> * Javadoc additions of `@implNote`: >> >> * `src/java.base/share/classes/java/io/PipedReader.java` >> * `src/java.base/share/classes/java/io/PipedWriter.java` >> * `src/java.base/share/classes/java/lang/Throwable.java` >> * `src/java.base/share/classes/java/util/ArrayDeque.java` >> * `src/java.base/share/classes/java/util/EnumMap.java` >> * `src/java.base/share/classes/java/util/HashSet.java` >> * `src/java.base/share/classes/java/util/Hashtable.java` >> * `src/java.base/share/classes/java/util/LinkedList.java` >> * `src/java.base/share/classes/java/util/TreeMap.java` >> * `src/java.base/share/classes/java/util/TreeSet.java` >> >> * New unit tests >> * `test/langtools/tools/javac/warnings/ThisEscape/*.java` >> >> * **Everything else** is just adding `@SuppressWarnings("this-escape")` > > Archie L. Cobbs has updated the pull request incrementally with two additional commits since the last revision: > > - Use the more appropriate Type comparison method Types.isSameType(). > - Add some more comments to clarify how the analysis works. Per the discussion in "Effective Java" on calling overridable methods in a constructor, future refinements of the check under review here could be extended to examine the bodies of clone and readObject methods. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From mcimadamore at openjdk.org Wed Jan 11 21:48:18 2023 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Wed, 11 Jan 2023 21:48:18 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v5] In-Reply-To: References: <_GkLRl5VTNh8ToJ3cjF-_v9j6eWWQzbUCCKStOXKh4g=.5e9505f1-8182-47e6-a8ed-78982db36c94@github.com> <0VZaG4s1DCehTwPfEshM6Lt90CKit-D-w_4F8NzAw8c=.b515334e-a4d3-495d-afae-6e4aa45ff683@github.com> Message-ID: <8RxCBaG_JM-5ej97lG5SDVzelH018OXgboIFFvs0hmQ=.ec5da5d8-01db-4797-938b-0419a3c1d2ec@github.com> On Wed, 11 Jan 2023 19:10:04 GMT, Archie L. Cobbs wrote: >> Good idea. Looks like the difference is in the noise, at least on my Macbook: >> >> Builds of master (jdk-21+3-69-gc6588d5bb3f) >> ================================== >> >> Build times: >> >> real 2m24.650s >> user 13m46.727s >> sys 2m33.554s >> >> real 2m27.224s >> user 13m43.464s >> sys 2m37.251s >> >> real 2m26.658s >> user 13m42.578s >> sys 2m36.133s >> >> Builds of ThisEscape (jdk-21+3-125-g6e96a7d76f8) >> ================================== >> >> Modifications: >> >> - Reverted files in the make/ subdirectory to enable warning >> - Commented out lines 363-382 in ThisEscapeAnalyzer.java >> so no warnings are actually reported >> >> Build times: >> >> real 2m25.912s >> user 13m45.860s >> sys 2m32.741s >> >> real 2m27.213s >> user 13m44.830s >> sys 2m36.596s >> >> real 2m25.756s >> user 13m42.889s >> sys 2m35.659s > > Regarding the assignment graph approach, I think that would work if the references are bouncing around strictly between variables, but what if the chain includes any of the more complicated stuff that is currently being tracked, such as various Java expressions, method invocations, conditionals, etc.? > > Consider this example: > > public class ThisEscapeLoop { > > public ThisEscapeLoop() { > ThisEscapeLoop ref1 = this; > ThisEscapeLoop ref2 = null; > ThisEscapeLoop ref3 = null; > ThisEscapeLoop ref4 = null; > for (int i = 0; i < 100; i++) { > ref4 = this.returnMe(ref3); > ref3 = ref2; > ref2 = ref1; > if (ref4 != null) > ref4.mightLeak(); > } > } > > public T returnMe(T x) { > return x; > } > > public void mightLeak() { > } > } > > If you are only looking at variable assignments with values that are other variables, then the chain "breaks" when `ref4` is assigned indirectly via `returnMe()`, and you miss the leak. > Good idea. Looks like the difference is in the noise, at least on my Macbook: > > ``` > Builds of master (jdk-21+3-69-gc6588d5bb3f) > ================================== > > Build times: > > real 2m24.650s > user 13m46.727s > sys 2m33.554s > > real 2m27.224s > user 13m43.464s > sys 2m37.251s > > real 2m26.658s > user 13m42.578s > sys 2m36.133s > > Builds of ThisEscape (jdk-21+3-125-g6e96a7d76f8) > ================================== > > Modifications: > > - Reverted files in the make/ subdirectory to enable warning > - Commented out lines 363-382 in ThisEscapeAnalyzer.java > so no warnings are actually reported > > Build times: > > real 2m25.912s > user 13m45.860s > sys 2m32.741s > > real 2m27.213s > user 13m44.830s > sys 2m36.596s > > real 2m25.756s > user 13m42.889s > sys 2m35.659s > ``` Thanks for trying it out - good to know that build time isn't affected. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From mcimadamore at openjdk.org Wed Jan 11 21:54:17 2023 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Wed, 11 Jan 2023 21:54:17 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v5] In-Reply-To: <8RxCBaG_JM-5ej97lG5SDVzelH018OXgboIFFvs0hmQ=.ec5da5d8-01db-4797-938b-0419a3c1d2ec@github.com> References: <_GkLRl5VTNh8ToJ3cjF-_v9j6eWWQzbUCCKStOXKh4g=.5e9505f1-8182-47e6-a8ed-78982db36c94@github.com> <0VZaG4s1DCehTwPfEshM6Lt90CKit-D-w_4F8NzAw8c=.b515334e-a4d3-495d-afae-6e4aa45ff683@github.com> <8RxCBaG_JM-5ej97lG5SDVzelH018OXgboI FFvs0hmQ=.ec5da5d8-01db-4797-938b-0419a3c1d2ec@github.com> Message-ID: On Wed, 11 Jan 2023 21:45:20 GMT, Maurizio Cimadamore wrote: >> Regarding the assignment graph approach, I think that would work if the references are bouncing around strictly between variables, but what if the chain includes any of the more complicated stuff that is currently being tracked, such as various Java expressions, method invocations, conditionals, etc.? >> >> Consider this example: >> >> public class ThisEscapeLoop { >> >> public ThisEscapeLoop() { >> ThisEscapeLoop ref1 = this; >> ThisEscapeLoop ref2 = null; >> ThisEscapeLoop ref3 = null; >> ThisEscapeLoop ref4 = null; >> for (int i = 0; i < 100; i++) { >> ref4 = this.returnMe(ref3); >> ref3 = ref2; >> ref2 = ref1; >> if (ref4 != null) >> ref4.mightLeak(); >> } >> } >> >> public T returnMe(T x) { >> return x; >> } >> >> public void mightLeak() { >> } >> } >> >> If you are only looking at variable assignments with values that are other variables, then the chain "breaks" when `ref4` is assigned indirectly via `returnMe()`, and you miss the leak. > >> Good idea. Looks like the difference is in the noise, at least on my Macbook: >> >> ``` >> Builds of master (jdk-21+3-69-gc6588d5bb3f) >> ================================== >> >> Build times: >> >> real 2m24.650s >> user 13m46.727s >> sys 2m33.554s >> >> real 2m27.224s >> user 13m43.464s >> sys 2m37.251s >> >> real 2m26.658s >> user 13m42.578s >> sys 2m36.133s >> >> Builds of ThisEscape (jdk-21+3-125-g6e96a7d76f8) >> ================================== >> >> Modifications: >> >> - Reverted files in the make/ subdirectory to enable warning >> - Commented out lines 363-382 in ThisEscapeAnalyzer.java >> so no warnings are actually reported >> >> Build times: >> >> real 2m25.912s >> user 13m45.860s >> sys 2m32.741s >> >> real 2m27.213s >> user 13m44.830s >> sys 2m36.596s >> >> real 2m25.756s >> user 13m42.889s >> sys 2m35.659s >> ``` > > Thanks for trying it out - good to know that build time isn't affected. > Regarding the assignment graph approach, I think that would work if the references are bouncing around strictly between variables, but what if the chain includes any of the more complicated stuff that is currently being tracked, such as various Java expressions, method invocations, conditionals, etc.? > > Consider this example: > > ```java > public class ThisEscapeLoop { > > public ThisEscapeLoop() { > ThisEscapeLoop ref1 = this; > ThisEscapeLoop ref2 = null; > ThisEscapeLoop ref3 = null; > ThisEscapeLoop ref4 = null; > for (int i = 0; i < 100; i++) { > ref4 = this.returnMe(ref3); > ref3 = ref2; > ref2 = ref1; > if (ref4 != null) > ref4.mightLeak(); > } > } > > public T returnMe(T x) { > return x; > } > > public void mightLeak() { > } > } > ``` > > If you are only looking at variable assignments with values that are other variables, then the chain "breaks" when `ref4` is assigned indirectly via `returnMe()`, and you miss the leak. So, in this example though you are calling an instance method before the object is initialized, which would seem to me like a leak (leaving aside heroics to try and chase the method body and see what the body of the method actually does). And, if the method is static, same story - you are passing `ref3` somewhere else, and `ref3` potentially contains `this`. While I know that this is not perfect, and bound to generate false positives, I get the spirit of my question is, really: is there a (much) simpler scheme we can get away with, which has bounded complexity, and which has the property we care about (which seems to be no false negative). I'm less worried about contrived cases emitting false positives, as it's an optional warning that can be shut down - but I'd like perhaps to move the discussion from trying to detect _precisely_ if the leak happens to try to detect if _potentially_ a leak can happen, and see if there's some simpler analysis that can be used to get there (e.g. one which doesn't require flooding). It's possible that you have already considered all these options and the analysis you have here is the best trade off between complexity and precision - but I'd like to have a better understanding of what the trade offs are, and, more importantly, what happens to real code when we tweak the analysis this or that way (as this is a problem where I feel it's easy to get in the land of diminishing returns). ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Wed Jan 11 22:43:16 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Wed, 11 Jan 2023 22:43:16 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v5] In-Reply-To: References: <_GkLRl5VTNh8ToJ3cjF-_v9j6eWWQzbUCCKStOXKh4g=.5e9505f1-8182-47e6-a8ed-78982db36c94@github.com> <0VZaG4s1DCehTwPfEshM6Lt90CKit-D-w_4F8NzAw8c=.b515334e-a4d3-495d-afae-6e4aa45ff683@github.com> <8RxCBaG_JM-5ej97lG5SDVzelH018OXgboI FFvs0hmQ=.ec5da5d8-01db-4797-938b-0419a3c1d2ec@github.com> Message-ID: On Wed, 11 Jan 2023 21:51:45 GMT, Maurizio Cimadamore wrote: > So, in this example though you are calling an instance method before the object is initialized, which would seem to me like a leak D'oh, you're right. But if you made `returnMe()` static or private then the argument would still hold. > And, if the method is static, same story - you are passing ref3 somewhere else, and ref3 potentially contains this. Not true... static methods are safe to "invoke" because they can't be overridden. When the analyzer "invokes" the method, it will see that all it does with its parameter is return it. In other words, any method (or constructor) in the current compilation unit that can't be overridden is never considered "somewhere else". > While I know that this is not perfect, and bound to generate false positives, I get the spirit of my question is, really: is there a (much) simpler scheme we can get away with, which has bounded complexity, and which has the property we care about (which seems to be no false negative). I'm less worried about contrived cases emitting false positives, as it's an optional warning that can be shut down - but I'd like perhaps to move the discussion from trying to detect precisely if the leak happens to try to detect if potentially a leak can happen, and see if there's some simpler analysis that can be used to get there (e.g. one which doesn't require flooding). It's possible that you have already considered all these options and the analysis you have here is the best trade off between complexity and precision - but I'd like to have a better understanding of what the trade offs are, and, more importantly, what happens to real code when we tweak the analysis this or that way (as this is a problem where I feel it's easy to get in the land of diminishing returns). I can only report from my own experience. I thought about this a bit and tried a few different things and what I ended up was the best I could come up with in terms of that trade-off. Of course there was a good bit of intuition and SWAG'ing in that and also a lot of thought experiments. Of course if you have a clever idea for how to do this in a simpler way that achieves basically the same result, I'm all ears :) But I don't really have an analysis of all the trade-offs. Really, at a certain point I stumbled on what I thought was a fairly straightforward way to achieve a good false negative rate and a very low false positive rate, without a lot of work. And frankly at that point I stopped caring about the question you're asking, although I agree it's certainly interesting from an academic point of view (I'm a practical person). A lot of my initial ideas were too simple for my taste, because I could easily find real-world false negatives. An example of "too simple": at first I was not trying to track an outer 'this'. But I found a lot of constructors out there that instantiate nested classes and then do things with them. Without tracking outer 'this' these would all be missed. To take a random example of that: public class FileChooserDemo extends JPanel implements ActionListener { ... public FileChooserDemo() { ... // create a radio listener to listen to option changes OptionListener optionListener = new OptionListener(); // Create options openRadioButton = new JRadioButton("Open"); openRadioButton.setSelected(true); openRadioButton.addActionListener(optionListener); // <- LEAK HERE ... } private class OptionListener implements ActionListener { ... } } That particular leak is (probably) innocuous, but it still qualifies as a leak and should be reported. Note that failing to track an outer 'this' causes false negatives, which are a bigger problem than false positives. On the flip side, I started out trying to explicitly track field references, but that seemed like more complexity than needed, at least for phase 1, so that was left out. The "flooding" aspect didn't really worry me because the reference set is "append only" and there is small, finite set of possible references at each scope, so it can't really get that out of hand. Testing indeed shows it's not a problem. By the way recursion also "floods" until convergence, just like looping. I would have been pleased to find "a much simpler scheme". But the more I thought about those options, the more I came up with easy misses. And after a certain point, it actually became easier to simply "execute" the code by scanning the AST while carrying around a `Set` to track possible references. It's really that simple. Instead of trying to be "smart" we just let the code tell us what happens. Apologies if this is not a very good answer to your question. In the big picture, the false positive rate is traded-off against code complexity, and we want the best possible trade-off, right? But how are you defining "complexity"? If you really mean performance, then I don't see a problem... the JDK build times are essentially unchanged. If you mean lines of code or whatever, then it doesn't seem inordinate. And the algorithm is more or less just an AST scan, like lots of other examples in the compiler code. So I don't see a problem there either. Yes, there may be a much simpler way that's just as good, but if I could have thought of it I would have already. Perhaps you or someone else has better insight. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From mcimadamore at openjdk.org Thu Jan 12 00:18:11 2023 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Thu, 12 Jan 2023 00:18:11 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v5] In-Reply-To: References: <_GkLRl5VTNh8ToJ3cjF-_v9j6eWWQzbUCCKStOXKh4g=.5e9505f1-8182-47e6-a8ed-78982db36c94@github.com> <0VZaG4s1DCehTwPfEshM6Lt90CKit-D-w_4F8NzAw8c=.b515334e-a4d3-495d-afae-6e4aa45ff683@github.com> <8RxCBaG_JM-5ej97lG5SDVzelH018OXgboI FFvs0hmQ=.ec5da5d8-01db-4797-938b-0419a3c1d2ec@github.com> Message-ID: On Wed, 11 Jan 2023 22:40:43 GMT, Archie L. Cobbs wrote: > > D'oh, you're right. But if you made `returnMe()` static or private then the argument would still hold. > > > And, if the method is static, same story - you are passing ref3 somewhere else, and ref3 potentially contains this. > > Not true... static methods are safe to "invoke" because they can't be overridden. When the analyzer "invokes" the method, it will see that all it does with its parameter is return it. > So, for static methods, it could go down two ways: either we don't even look at referenced method bodies, give up and just declare "sorry, escaping". Or, if we look into method bodies, and see that the relationship between inner and outer parameter is as simple, it's just like assignment again: ref1 -> ref2 -> ref3 -> x -> ref4 > But I don't really have an analysis of all the trade-offs. Really, at a certain point I stumbled on what I thought was a fairly straightforward way to achieve a good false negative rate and a very low false positive rate, without a lot of work. And frankly at that point I stopped caring about the question you're asking, although I agree it's certainly interesting from an academic point of view (I'm a practical person). The reason I'm asking these questions is that I'm trying to understand which ingredients went into the analysis and why, in order to try and build a mental problem of what the problem that needs to be solved is, what are the constraints, etc. I'm also a practical person :-) and I often find it easier to understand a piece of code if I know some of the reasoning that went behind it, or what's the behavior supposed to be. I do not know, off-hands, whether there is a simpler solution - I was mostly probing for war stories of the kind "I tried X and I got Y", and I apologize if that came off the wrong way. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Thu Jan 12 02:17:16 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Thu, 12 Jan 2023 02:17:16 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v5] In-Reply-To: References: <_GkLRl5VTNh8ToJ3cjF-_v9j6eWWQzbUCCKStOXKh4g=.5e9505f1-8182-47e6-a8ed-78982db36c94@github.com> <0VZaG4s1DCehTwPfEshM6Lt90CKit-D-w_4F8NzAw8c=.b515334e-a4d3-495d-afae-6e4aa45ff683@github.com> <8RxCBaG_JM-5ej97lG5SDVzelH018OXgboI FFvs0hmQ=.ec5da5d8-01db-4797-938b-0419a3c1d2ec@github.com> Message-ID: On Thu, 12 Jan 2023 00:15:08 GMT, Maurizio Cimadamore wrote: > So, for static methods, it could go down two ways: either we don't even look at referenced method bodies, give up and just declare "sorry, escaping". Or, if we look into method bodies, and see that the relationship between inner and outer parameter is as simple, it's just like assignment again: Right - and just to reconfirm, it's only the non-overridable methods in the same compilation unit that are "invoked" (i.e., analyzed & tracked). Any method that (might) exist in another compilation unit is off limits, so we have to assume the worst case and declare a leak if we are passing it any 'this' references. > in order to try and build a mental problem of what the problem that needs to be solved is Gotcha. Let's be clear about what exactly we're worrying about. It's this situation: You have a class `B extends A`, where `B` and `A` are in different compilation units, and during the `super()` call that constructor `B()` makes to its superclass constructor `A()`, some code in class `B` gets executed (really, it's some field in `B` getting accessed that actually matters) prior to `A()` returning. So the basic goal is to analyze `A` constructors and watch 'this' references until if/when they go to someplace where we can no longer watch them. At that point we have to assume that some code in `B` might get invoked and so we generate a warning. OK, so where can a 'this' reference go? Well, here are all of the possible places a Java reference can exist: 1. On the Java stack (a) The current 'this' instance (b) A method parameter (c) A local variable (d) A temporary value that is part of the current expression being evaluated (e) The return value from a method that just returned (f) A caught exception 1. In a field of some object... (a) A normal field (b) An outer 'this' instance (c) Other synthetic field (e.g., captured free variable) 1. As an element in a reference array 1. In native code as a native reference Those are the only possibilities AFAIK. So one way to locate yourself on the spectrum from "simple" to "complex" is to answer this question: Which of those are you going to try to keep track of, and for each one, how hard are you going to try? The `this-escape` analysis being proposed tracks 1(a-e) and 2(b) pretty closely (it tries hard), and it adds a very course tracking of 2(a-c), and 3 using the notion of indirect references (it doesn't try very hard). We do not track 1(f) or 4. So to think about the overall problem, imagine how you might or might not address all of those cases. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From mcimadamore at openjdk.org Thu Jan 12 10:00:21 2023 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Thu, 12 Jan 2023 10:00:21 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v5] In-Reply-To: References: <_GkLRl5VTNh8ToJ3cjF-_v9j6eWWQzbUCCKStOXKh4g=.5e9505f1-8182-47e6-a8ed-78982db36c94@github.com> <0VZaG4s1DCehTwPfEshM6Lt90CKit-D-w_4F8NzAw8c=.b515334e-a4d3-495d-afae-6e4aa45ff683@github.com> <8RxCBaG_JM-5ej97lG5SDVzelH018OXgboI FFvs0hmQ=.ec5da5d8-01db-4797-938b-0419a3c1d2ec@github.com> Message-ID: On Thu, 12 Jan 2023 02:14:10 GMT, Archie L. Cobbs wrote: >>> >>> D'oh, you're right. But if you made `returnMe()` static or private then the argument would still hold. >>> >>> > And, if the method is static, same story - you are passing ref3 somewhere else, and ref3 potentially contains this. >>> >>> Not true... static methods are safe to "invoke" because they can't be overridden. When the analyzer "invokes" the method, it will see that all it does with its parameter is return it. >>> >> >> So, for static methods, it could go down two ways: either we don't even look at referenced method bodies, give up and just declare "sorry, escaping". Or, if we look into method bodies, and see that the relationship between inner and outer parameter is as simple, it's just like assignment again: >> >> ref1 -> ref2 -> ref3 -> x -> ref4 >> >>> But I don't really have an analysis of all the trade-offs. Really, at a certain point I stumbled on what I thought was a fairly straightforward way to achieve a good false negative rate and a very low false positive rate, without a lot of work. And frankly at that point I stopped caring about the question you're asking, although I agree it's certainly interesting from an academic point of view (I'm a practical person). >> >> The reason I'm asking these questions is that I'm trying to understand which ingredients went into the analysis and why, in order to try and build a mental problem of what the problem that needs to be solved is, what are the constraints, etc. I'm also a practical person :-) and I often find it easier to understand a piece of code if I know some of the reasoning that went behind it, or what's the behavior supposed to be. >> >> I do not know, off-hands, whether there is a simpler solution - I was mostly probing for war stories of the kind "I tried X and I got Y", and I apologize if that came off the wrong way. > >> So, for static methods, it could go down two ways: either we don't even look at referenced method bodies, give up and just declare "sorry, escaping". Or, if we look into method bodies, and see that the relationship between inner and outer parameter is as simple, it's just like assignment again: > > Right - and just to reconfirm, it's only the non-overridable methods in the same compilation unit that are "invoked" (i.e., analyzed & tracked). Any method that (might) exist in another compilation unit is off limits, so we have to assume the worst case and declare a leak if we are passing it any 'this' references. > >> in order to try and build a mental problem of what the problem that needs to be solved is > > Gotcha. > > Let's be clear about what exactly we're worrying about. It's this situation: You have a class `B extends A`, where `B` and `A` are in different compilation units, and during the `super()` call that constructor `B()` makes to its superclass constructor `A()`, some code in class `B` gets executed (really, it's some field in `B` getting accessed that actually matters) prior to `A()` returning. > > So the basic goal is to analyze `A` constructors and watch 'this' references until if/when they go to someplace where we can no longer watch them. At that point we have to assume that some code in `B` might get invoked and so we generate a warning. > > OK, so where can a 'this' reference go? > > Well, here are all of the possible places a Java reference can exist: > 1. On the Java stack > (a) The current 'this' instance > (b) A method parameter > (c) A local variable > (d) A temporary value that is part of the current expression being evaluated > (e) The return value from a method that just returned > (f) A caught exception > 1. In a field of some object... > (a) A normal field > (b) An outer 'this' instance > (c) Other synthetic field (e.g., captured free variable) > 1. As an element in a reference array > 1. In native code as a native reference > > Those are the only possibilities AFAIK. > > So one way to locate yourself on the spectrum from "simple" to "complex" is to answer this question: Which of those are you going to try to keep track of, and for each one, how hard are you going to try? > > The `this-escape` analysis being proposed tracks 1(a-e) and 2(b) pretty closely (it tries hard), and it adds a very course tracking of 2(a-c), and 3 using the notion of indirect references (it doesn't try very hard). We do not track 1(f) or 4. > > So to think about the overall problem, imagine how you might or might not address all of those cases. > * On the Java stack > (a) The current 'this' instance > (b) A method parameter > (c) A local variable > (d) A temporary value that is part of the current expression being evaluated > (e) The return value from a method that just returned > (f) A caught exception > > * In a field of some object... > (a) A normal field > (b) An outer 'this' instance > (c) Other synthetic field (e.g., captured free variable) > > * As an element in a reference array > > * In native code as a native reference Thanks for the classification. This is helpful. I'm not sure what you mean by (1f). You mean `this` can be embedded in an exception being thrown? Is that different from (2)? Also, it seems to me that (3) is a special case of (2) - in the sense that you can imagine a reference array as a big object that has many fields as there are elements - so the same reasoning applies. When looking at (2d) and (2e) the fact that Javac's AST is not in SSA form means that, yes, we need to track _expressions_ not just variables (e.g. for chains of methods calls, ternary operators and such). ------------- PR: https://git.openjdk.org/jdk/pull/11874 From ihse at openjdk.org Thu Jan 12 12:16:18 2023 From: ihse at openjdk.org (Magnus Ihse Bursie) Date: Thu, 12 Jan 2023 12:16:18 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: Message-ID: On Wed, 11 Jan 2023 03:30:03 GMT, Archie L. Cobbs wrote: >> This PR adds a new lint warning category `this-escape`. >> >> It also adds `@SuppressWarnings` annotations as needed to the JDK itself to allow the JDK to continue to compile with `-Xlint:all`. >> >> A 'this' escape warning is generated for a constructor `A()` in a class `A` when the compiler detects that the following situation is _in theory possible:_ >> * Some subclass `B extends A` exists, and `B` is defined in a separate source file (i.e., compilation unit) >> * Some constructor `B()` of `B` invokes `A()` as its superclass constructor >> * During the execution of `A()`, some non-static method of `B.foo()` could get invoked, perhaps indirectly >> >> In the above scenario, `B.foo()` would execute before `A()` has returned and before `B()` has performed any initialization. To the extent `B.foo()` accesses any fields of `B` - all of which are still uninitialized - it is likely to function incorrectly. >> >> Note, when determining if a 'this' escape is possible, the compiler makes no assumptions about code outside of the current compilation unit. It doesn't look outside of the current source file to see what might actually happen when a method is invoked. It does follow method and constructors within the current compilation unit, and applies a simplified union-of-all-possible-branches data flow analysis to see where 'this' could end up. >> >> From my review, virtually all of the warnings generated in the various JDK modules are valid warnings in the sense that a 'this' escape, as defined above, is really and truly possible. However, that doesn't imply that any bugs were found within the JDK - only that the possibility of a certain type of bug exists if certain superclass constructors are used by someone, somewhere, someday. >> >> For several "popular" classes, this PR also adds `@implNote`'s to the offending constructors so that subclass implementors are made aware of the threat. For one example, `TreeMap(Map)` invokes `putAll()` and `put()`. >> >> More details and a couple of motivating examples are given in an included [doc file](https://github.com/archiecobbs/jdk/blob/ThisEscape/src/java.base/share/classes/java/lang/doc-files/ThisEscape.html) that these `@implNote`'s link to. See also the recent thread on `amber-dev` for some background. >> >> Ideally, over time the owners of the various modules would review their `@SuppressWarnings("this-escape")` annotations and determine which other constructors also warranted such an `@implNote`. >> >> Because of all the`@SuppressWarnings` annotations, this PR touches a bunch of different JDK modules. My apologies for that. Adding these annotations was determined to be the more conservative approach, as compared to just excepting `this-escape` from various module builds globally. >> >> **Patch Navigation Guide** >> >> * Non-trivial compiler changes: >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties` >> >> * Javadoc additions of `@implNote`: >> >> * `src/java.base/share/classes/java/io/PipedReader.java` >> * `src/java.base/share/classes/java/io/PipedWriter.java` >> * `src/java.base/share/classes/java/lang/Throwable.java` >> * `src/java.base/share/classes/java/util/ArrayDeque.java` >> * `src/java.base/share/classes/java/util/EnumMap.java` >> * `src/java.base/share/classes/java/util/HashSet.java` >> * `src/java.base/share/classes/java/util/Hashtable.java` >> * `src/java.base/share/classes/java/util/LinkedList.java` >> * `src/java.base/share/classes/java/util/TreeMap.java` >> * `src/java.base/share/classes/java/util/TreeSet.java` >> >> * New unit tests >> * `test/langtools/tools/javac/warnings/ThisEscape/*.java` >> >> * **Everything else** is just adding `@SuppressWarnings("this-escape")` > > Archie L. Cobbs has updated the pull request incrementally with two additional commits since the last revision: > > - Use the more appropriate Type comparison method Types.isSameType(). > - Add some more comments to clarify how the analysis works. FWIW, the make changes look good. I have nothing to say about the actual lint code itself. ------------- Marked as reviewed by ihse (Reviewer). PR: https://git.openjdk.org/jdk/pull/11874 From mcimadamore at openjdk.org Thu Jan 12 12:31:39 2023 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Thu, 12 Jan 2023 12:31:39 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: Message-ID: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> On Wed, 11 Jan 2023 03:30:03 GMT, Archie L. Cobbs wrote: >> This PR adds a new lint warning category `this-escape`. >> >> It also adds `@SuppressWarnings` annotations as needed to the JDK itself to allow the JDK to continue to compile with `-Xlint:all`. >> >> A 'this' escape warning is generated for a constructor `A()` in a class `A` when the compiler detects that the following situation is _in theory possible:_ >> * Some subclass `B extends A` exists, and `B` is defined in a separate source file (i.e., compilation unit) >> * Some constructor `B()` of `B` invokes `A()` as its superclass constructor >> * During the execution of `A()`, some non-static method of `B.foo()` could get invoked, perhaps indirectly >> >> In the above scenario, `B.foo()` would execute before `A()` has returned and before `B()` has performed any initialization. To the extent `B.foo()` accesses any fields of `B` - all of which are still uninitialized - it is likely to function incorrectly. >> >> Note, when determining if a 'this' escape is possible, the compiler makes no assumptions about code outside of the current compilation unit. It doesn't look outside of the current source file to see what might actually happen when a method is invoked. It does follow method and constructors within the current compilation unit, and applies a simplified union-of-all-possible-branches data flow analysis to see where 'this' could end up. >> >> From my review, virtually all of the warnings generated in the various JDK modules are valid warnings in the sense that a 'this' escape, as defined above, is really and truly possible. However, that doesn't imply that any bugs were found within the JDK - only that the possibility of a certain type of bug exists if certain superclass constructors are used by someone, somewhere, someday. >> >> For several "popular" classes, this PR also adds `@implNote`'s to the offending constructors so that subclass implementors are made aware of the threat. For one example, `TreeMap(Map)` invokes `putAll()` and `put()`. >> >> More details and a couple of motivating examples are given in an included [doc file](https://github.com/archiecobbs/jdk/blob/ThisEscape/src/java.base/share/classes/java/lang/doc-files/ThisEscape.html) that these `@implNote`'s link to. See also the recent thread on `amber-dev` for some background. >> >> Ideally, over time the owners of the various modules would review their `@SuppressWarnings("this-escape")` annotations and determine which other constructors also warranted such an `@implNote`. >> >> Because of all the`@SuppressWarnings` annotations, this PR touches a bunch of different JDK modules. My apologies for that. Adding these annotations was determined to be the more conservative approach, as compared to just excepting `this-escape` from various module builds globally. >> >> **Patch Navigation Guide** >> >> * Non-trivial compiler changes: >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties` >> >> * Javadoc additions of `@implNote`: >> >> * `src/java.base/share/classes/java/io/PipedReader.java` >> * `src/java.base/share/classes/java/io/PipedWriter.java` >> * `src/java.base/share/classes/java/lang/Throwable.java` >> * `src/java.base/share/classes/java/util/ArrayDeque.java` >> * `src/java.base/share/classes/java/util/EnumMap.java` >> * `src/java.base/share/classes/java/util/HashSet.java` >> * `src/java.base/share/classes/java/util/Hashtable.java` >> * `src/java.base/share/classes/java/util/LinkedList.java` >> * `src/java.base/share/classes/java/util/TreeMap.java` >> * `src/java.base/share/classes/java/util/TreeSet.java` >> >> * New unit tests >> * `test/langtools/tools/javac/warnings/ThisEscape/*.java` >> >> * **Everything else** is just adding `@SuppressWarnings("this-escape")` > > Archie L. Cobbs has updated the pull request incrementally with two additional commits since the last revision: > > - Use the more appropriate Type comparison method Types.isSameType(). > - Add some more comments to clarify how the analysis works. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 163: > 161: * invoked from the target constructor; if empty, we're still in the constructor. > 162: */ > 163: private final ArrayDeque callStack = new ArrayDeque<>(); There is a concept of push/popScope and then there's a separate concept of call stack (which is just a list of diagnostic position up to the point). I wonder if this could be better modeled by using a single class e.g. Scope/Frame which has a diagnostic position, plus other useful things. Perhaps it might even be helpful to have a ref set on each scope, so that you don't have to attach a "depth" to each ref - the depth of the ref would be determined by the "scope" in which it appears. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 175: > 173: private DiagnosticPosition[] pendingWarning; > 174: > 175: // These fields are scoped to the CONSTRUCTOR OR INVOKED METHOD BEING ANALYZED Watch out for "all caps" src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 218: > 216: new TreeScanner() { > 217: > 218: private Lint lint = ThisEscapeAnalyzer.this.lint; On a first look I'm not sure about the granularity of suppression here. I believe that suppressing at the class level, or at the constructor level is enough. Allowing to further annotate var declarations and non-constructor methods, while doable, might actually be counter productive - in the sense that the annotation does not occur in the constructor (where you'd want to see it) but in some other method. I think the fact that a constructor is escaping (willingly) should be a visible thing. Something to consider. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 220: > 218: private Lint lint = ThisEscapeAnalyzer.this.lint; > 219: private JCClassDecl currentClass; > 220: private boolean privateOuter; I don't think this is needed - see below src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 227: > 225: final boolean privateOuterPrev = this.privateOuter; > 226: final Lint lintPrev = this.lint; > 227: this.lint = this.lint.augment(tree.sym); general stylistic comment - I see here and everywhere in this class `this.xyz` - this is not the norm in the rest of the javac codebase, and it would be better to replace it with just `xyz` src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 230: > 228: try { > 229: this.currentClass = tree; > 230: this.privateOuter |= tree.sym.isAnonymous(); These can be inlined in the check below src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 270: > 268: final boolean analyzable = this.currentClassIsExternallyExtendable() && > 269: TreeInfo.isConstructor(tree) && > 270: !tree.sym.isPrivate() && Why aren't private constructors analyzed? If we have a class with a private constructor and public static factory invoking said constructor, and the constructor makes `this` escape, isn't that an issue we should detect? src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 294: > 292: !(this.currentClass.sym.isSealed() && this.currentClass.permitting.isEmpty()) && > 293: !(this.currentClass.sym.owner.kind == MTH) && > 294: !this.privateOuter; Here, note that is the owner of the current class symbol is a method, that covers anonymous classes too, which is a part of `privateOuter`. So the only think we need to check here is whether "currentClass" is private, which is a simple predicate. No need to carry `privateOuter` I believe src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 304: > 302: > 303: // We are looking for analyzable constructors only > 304: final Symbol sym = entry.getKey(); This seems unused. And, if so, perhaps we only need a `Set`, not a map. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 348: > 346: final Comparator ordering = (warning1, warning2) -> { > 347: for (int index1 = 0, index2 = 0; true; index1++, index2++) { > 348: final boolean end1 = index1 >= warning1.length; Another stylistic comment - the `final` here is not super helpful. The compiler performs effectively final analysis, so if your locals are only written once, you are good to go - and can even use them inside lambdas. From a documentation perspective it might carry a bit of value, but again, the rest of the javac code generally doesn't do that. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 411: > 409: final boolean referenceExpressionNode; > 410: switch (tree.getTag()) { > 411: case CASE: surprised to see `CASE` here - as that's not an expression src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 444: > 442: if (referenceExpressionNode) { > 443: > 444: // We treat instance methods as having a "value" equal to their instance The comment is slightly misleading - e.g. I'd suggest clarifying "having a "value" whose type is the same as that of the class in which the method is defined" src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 454: > 452: > 453: // If the expression type is incompatible with 'this', discard it > 454: if (type != null && !this.isSubtype(this.targetClass.sym.type, type)) Instead of adding the direct reference, and then having to check if the reference needs to be removed, would it be possible not to add the reference in the first place if the types mismatch? src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 504: > 502: // Recurse on method expression > 503: this.scan(invoke.meth); > 504: final boolean direct = this.refs.remove(ExprRef.direct(this.depth)); Understanding checkpoint. Considering this code: rec.m() There are two cases: * `rec` might be a direct reference to this (e.g. a local) * `rec` might be an indirect reference to this (a lambda containing `this`) So the receiver of the method might be direct or indirect. This will then determine how to interpret `this` in the context of that method analysis - e.g. when we see a `JCIdent` for `this`, we create a direct/indirect `ExprRef` based on what the receiver kind was. Correct? src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 817: > 815: // Methods - the "value" of a non-static method is a reference to its instance > 816: final Symbol sym = tree.sym; > 817: if (sym.kind == MTH) { This is perhaps where filtering based on the declaring class could make sense (to avoid having to filter later) ? Perhaps this could also be centralized - e.g. whenever you create an ExprRef you also pass the type for it, and if the type matches that for the current class you create it and add to the list, otherwise you skip it. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 875: > 873: // Reference to this? > 874: if (tree.name == names._this || tree.name == names._super) { > 875: if (this.refs.contains(ThisRef.direct())) This idiom occurs quite a lot. If I'm correct, this basically amounts at asking as to whether the receiver of the method we're currently evaluating is direct or not (which is an invariant, given a method body - e.g. for a given method this "fact" should stay the same). If that's the case, perhaps capturing this in a flag could be better - then you could have just have a single method e.g. `XYZRef.create(boolean direct)`, and remove the branching (here and elsewhere). src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 900: > 898: final Type.ClassType currentClassType = (Type.ClassType)this.methodClass.sym.type; > 899: final Type methodOwnerType = sym.owner.type; > 900: if (this.isSubtype(currentClassType, methodOwnerType)) { I believe what you need here is not subtyping but subclassing - see `Symbol.isSubclass` src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 909: > 907: > 908: // Check for implicit outer 'this' reference > 909: if (this.types.hasOuterClass(currentClassType, methodOwnerType)) { Similarly here - look for `Symbol.isEnclosedBy` src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 1302: > 1300: * In other words, a reference that's sitting on top of the stack. > 1301: */ > 1302: private static class ExprRef extends Ref { Maybe I'm wrong - but it seems that the only thing we need to track is whether the top of stack (e.g. last evaluated expression) has a direct reference or indirect reference (or none). Do we really need a set for this? (this seems the same as for ThisRef which is used inside method, which can be one of the same three options). While I do see value for tracking which variables are aliases for this (either direct or indirect), it seems like (at least on a superficial look) that expression refs might be replaced by a visitor field/parameter. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 1319: > 1317: /** A reference from the return value of the current method being "invoked". > 1318: */ > 1319: private static class ReturnRef extends Ref { Isn't this just an ExprRef? This might also be related with the fact that we deal with return values in different ways than with e.g. values returned from a nested scope (where we just pop, and then copy all pending expression to the outer depth). ------------- PR: https://git.openjdk.org/jdk/pull/11874 From mcimadamore at openjdk.org Thu Jan 12 13:04:18 2023 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Thu, 12 Jan 2023 13:04:18 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: Message-ID: On Wed, 11 Jan 2023 03:30:03 GMT, Archie L. Cobbs wrote: >> This PR adds a new lint warning category `this-escape`. >> >> It also adds `@SuppressWarnings` annotations as needed to the JDK itself to allow the JDK to continue to compile with `-Xlint:all`. >> >> A 'this' escape warning is generated for a constructor `A()` in a class `A` when the compiler detects that the following situation is _in theory possible:_ >> * Some subclass `B extends A` exists, and `B` is defined in a separate source file (i.e., compilation unit) >> * Some constructor `B()` of `B` invokes `A()` as its superclass constructor >> * During the execution of `A()`, some non-static method of `B.foo()` could get invoked, perhaps indirectly >> >> In the above scenario, `B.foo()` would execute before `A()` has returned and before `B()` has performed any initialization. To the extent `B.foo()` accesses any fields of `B` - all of which are still uninitialized - it is likely to function incorrectly. >> >> Note, when determining if a 'this' escape is possible, the compiler makes no assumptions about code outside of the current compilation unit. It doesn't look outside of the current source file to see what might actually happen when a method is invoked. It does follow method and constructors within the current compilation unit, and applies a simplified union-of-all-possible-branches data flow analysis to see where 'this' could end up. >> >> From my review, virtually all of the warnings generated in the various JDK modules are valid warnings in the sense that a 'this' escape, as defined above, is really and truly possible. However, that doesn't imply that any bugs were found within the JDK - only that the possibility of a certain type of bug exists if certain superclass constructors are used by someone, somewhere, someday. >> >> For several "popular" classes, this PR also adds `@implNote`'s to the offending constructors so that subclass implementors are made aware of the threat. For one example, `TreeMap(Map)` invokes `putAll()` and `put()`. >> >> More details and a couple of motivating examples are given in an included [doc file](https://github.com/archiecobbs/jdk/blob/ThisEscape/src/java.base/share/classes/java/lang/doc-files/ThisEscape.html) that these `@implNote`'s link to. See also the recent thread on `amber-dev` for some background. >> >> Ideally, over time the owners of the various modules would review their `@SuppressWarnings("this-escape")` annotations and determine which other constructors also warranted such an `@implNote`. >> >> Because of all the`@SuppressWarnings` annotations, this PR touches a bunch of different JDK modules. My apologies for that. Adding these annotations was determined to be the more conservative approach, as compared to just excepting `this-escape` from various module builds globally. >> >> **Patch Navigation Guide** >> >> * Non-trivial compiler changes: >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties` >> >> * Javadoc additions of `@implNote`: >> >> * `src/java.base/share/classes/java/io/PipedReader.java` >> * `src/java.base/share/classes/java/io/PipedWriter.java` >> * `src/java.base/share/classes/java/lang/Throwable.java` >> * `src/java.base/share/classes/java/util/ArrayDeque.java` >> * `src/java.base/share/classes/java/util/EnumMap.java` >> * `src/java.base/share/classes/java/util/HashSet.java` >> * `src/java.base/share/classes/java/util/Hashtable.java` >> * `src/java.base/share/classes/java/util/LinkedList.java` >> * `src/java.base/share/classes/java/util/TreeMap.java` >> * `src/java.base/share/classes/java/util/TreeSet.java` >> >> * New unit tests >> * `test/langtools/tools/javac/warnings/ThisEscape/*.java` >> >> * **Everything else** is just adding `@SuppressWarnings("this-escape")` > > Archie L. Cobbs has updated the pull request incrementally with two additional commits since the last revision: > > - Use the more appropriate Type comparison method Types.isSameType(). > - Add some more comments to clarify how the analysis works. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 334: > 332: // of the stack trace of B. For example, if constructor Foo(int x) has a leak, and constructor > 333: // Foo() invokes this(0), then emitting a warning for Foo() would be redundant. > 334: final BiPredicate extendsAsPrefix = (warning1, warning2) -> { Another strategy would be to give a single warning per leaking constructor. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Thu Jan 12 15:02:22 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Thu, 12 Jan 2023 15:02:22 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v5] In-Reply-To: References: <_GkLRl5VTNh8ToJ3cjF-_v9j6eWWQzbUCCKStOXKh4g=.5e9505f1-8182-47e6-a8ed-78982db36c94@github.com> <0VZaG4s1DCehTwPfEshM6Lt90CKit-D-w_4F8NzAw8c=.b515334e-a4d3-495d-afae-6e4aa45ff683@github.com> <8RxCBaG_JM-5ej97lG5SDVzelH018OXgboI FFvs0hmQ=.ec5da5d8-01db-4797-938b-0419a3c1d2ec@github.com> Message-ID: On Thu, 12 Jan 2023 09:57:00 GMT, Maurizio Cimadamore wrote: > I'm not sure what you mean by (1f). You mean this can be embedded in an exception being thrown? Is that different from (2)? Yes, this would be a different case from any other that you'd have to handle in the code if you wanted to deal with it. An example of how this could happen would be: public class ThrownThis extends RuntimeException { public ThrownThis(Object obj) { try { this.validate(obj); } catch (RuntimeException e) { e.mightLeak(); // LEAK HERE } } private void validate(Object obj) { if (obj.hashCode() != 123) throw this; } public void mightLeak() { } } Of course, that's an absurd example and the likelihood that any random piece of actually code does that is negligible. Regardless, I did briefly consider including handling for thrown exceptions but quickly decided it couldn't possibly be worth the trouble. As a result, if you compile that example with `-Xlint:this-escape` you don't get a warning. No major loss! > Also, it seems to me that (3) is a special case of (2) - in the sense that you can imagine a reference array as a big object that has many fields as there are elements - so the same reasoning applies. Yes it's effectively the same thing, but fields and array elements are accessed by different mechanisms in Java, so from the point of the analyzer they have to be handled separately for that reason, which is why I broke them out. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From mcimadamore at openjdk.org Thu Jan 12 15:12:56 2023 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Thu, 12 Jan 2023 15:12:56 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v5] In-Reply-To: References: <_GkLRl5VTNh8ToJ3cjF-_v9j6eWWQzbUCCKStOXKh4g=.5e9505f1-8182-47e6-a8ed-78982db36c94@github.com> <0VZaG4s1DCehTwPfEshM6Lt90CKit-D-w_4F8NzAw8c=.b515334e-a4d3-495d-afae-6e4aa45ff683@github.com> <8RxCBaG_JM-5ej97lG5SDVzelH018OXgboI FFvs0hmQ=.ec5da5d8-01db-4797-938b-0419a3c1d2ec@github.com> Message-ID: On Thu, 12 Jan 2023 14:59:12 GMT, Archie L. Cobbs wrote: >>> * On the Java stack >>> (a) The current 'this' instance >>> (b) A method parameter >>> (c) A local variable >>> (d) A temporary value that is part of the current expression being evaluated >>> (e) The return value from a method that just returned >>> (f) A caught exception >>> >>> * In a field of some object... >>> (a) A normal field >>> (b) An outer 'this' instance >>> (c) Other synthetic field (e.g., captured free variable) >>> >>> * As an element in a reference array >>> >>> * In native code as a native reference >> >> Thanks for the classification. This is helpful. >> >> I'm not sure what you mean by (1f). You mean `this` can be embedded in an exception being thrown? Is that different from (2)? >> >> Also, it seems to me that (3) is a special case of (2) - in the sense that you can imagine a reference array as a big object that has many fields as there are elements - so the same reasoning applies. >> >> When looking at (2d) and (2e) the fact that Javac's AST is not in SSA form means that, yes, we need to track _expressions_ not just variables (e.g. for chains of methods calls, ternary operators and such). > >> I'm not sure what you mean by (1f). You mean this can be embedded in an exception being thrown? Is that different from (2)? > > Yes, this would be a different case from any other that you'd have to handle in the code if you wanted to deal with it. > > An example of how this could happen would be: > > public class ThrownThis extends RuntimeException { > > public ThrownThis(Object obj) { > try { > this.validate(obj); > } catch (RuntimeException e) { > e.mightLeak(); // LEAK HERE > } > } > > private void validate(Object obj) { > if (obj.hashCode() != 123) > throw this; > } > > public void mightLeak() { > } > } > > Of course, that's an absurd example and the likelihood that any random piece of actually code does that is negligible. > > Regardless, I did briefly consider including handling for thrown exceptions but quickly decided it couldn't possibly be worth the trouble. > > As a result, if you compile that example with `-Xlint:this-escape` you don't get a warning. No major loss! > >> Also, it seems to me that (3) is a special case of (2) - in the sense that you can imagine a reference array as a big object that has many fields as there are elements - so the same reasoning applies. > > Yes it's effectively the same thing, but fields and array elements are accessed by different mechanisms in Java, so from the point of the analyzer they have to be handled separately for that reason, which is why I broke them out. > Yes, this would be a different case from any other that you'd have to handle in the code if you wanted to deal with it. > > An example of how this could happen would be: > > ```java > public class ThrownThis extends RuntimeException { > > public ThrownThis(Object obj) { > try { > this.validate(obj); > } catch (RuntimeException e) { > e.mightLeak(); // LEAK HERE > } > } > > private void validate(Object obj) { > if (obj.hashCode() != 123) > throw this; > } > > public void mightLeak() { > } > } > ``` > Interesting example - I thought you might have been referring to a case where the class being analyzed was itself an exception. Question - shouldn't we conclude that `this` leak when we see `throw this` ? E.g. what if the constructor did not have a `catch` (or if the catch was of a different type) ? > Of course, that's an absurd example and the likelihood that any random piece of actually code does that is negligible. > > Regardless, I did briefly consider including handling for thrown exceptions but quickly decided it couldn't possibly be worth the trouble. > > As a result, if you compile that example with `-Xlint:this-escape` you don't get a warning. No major loss! > > > Also, it seems to me that (3) is a special case of (2) - in the sense that you can imagine a reference array as a big object that has many fields as there are elements - so the same reasoning applies. > > Yes it's effectively the same thing, but fields and array elements are accessed by different mechanisms in Java, so from the point of the analyzer they have to be handled separately for that reason, which is why I broke them out. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Thu Jan 12 15:19:44 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Thu, 12 Jan 2023 15:19:44 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: Message-ID: On Thu, 12 Jan 2023 13:01:44 GMT, Maurizio Cimadamore wrote: >> Archie L. Cobbs has updated the pull request incrementally with two additional commits since the last revision: >> >> - Use the more appropriate Type comparison method Types.isSameType(). >> - Add some more comments to clarify how the analysis works. > > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 334: > >> 332: // of the stack trace of B. For example, if constructor Foo(int x) has a leak, and constructor >> 333: // Foo() invokes this(0), then emitting a warning for Foo() would be redundant. >> 334: final BiPredicate extendsAsPrefix = (warning1, warning2) -> { > > Another strategy would be to give a single warning per leaking constructor. We already impose a limit of at most one warning per constructor. But for this limit what is technically meant by "per constructor" is "At most one warning per constructor, assuming that constructor is the one being analyzed (i.e., the one invoked by the subclass and not via `this()`)." So that limitation doesn't stop a constructor from generating the same warning multiple times due to it being invoked indirectly by other constructors via `this()`. Those duplicate warnings are what the code above eliminates. So this code only generates one warning, and it's reported for the second constructor: public class DupWarn1 { public DupWarn1() { this(0); } public DupWarn1(int x) { this.mightLeak(); } public void mightLeak() { } } DupWarn1.java:8: warning: [this-escape] possible 'this' escape before subclass is fully initialized this.mightLeak(); ^ This is appropriate. The leak is really in the second constructor; the first constructor has nothing to do with it. Reporting a leak for both constructors would be redundant. An interesting side question: Is it possible to come up with an example where constructor A has a 'this' leak, and some other constructor B invokes `this()` to delegate to A, but when B delegates to A the leak occurs differently, or not at all? Because of the "flood" analysis, and the fact that you can't pass 'this' references to `this()` or `super()` (these are static contexts), I don't think it's possible. So in fact the deduplication will always apply whenever `this()` is involved. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Thu Jan 12 15:29:30 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Thu, 12 Jan 2023 15:29:30 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v5] In-Reply-To: References: <_GkLRl5VTNh8ToJ3cjF-_v9j6eWWQzbUCCKStOXKh4g=.5e9505f1-8182-47e6-a8ed-78982db36c94@github.com> <0VZaG4s1DCehTwPfEshM6Lt90CKit-D-w_4F8NzAw8c=.b515334e-a4d3-495d-afae-6e4aa45ff683@github.com> <8RxCBaG_JM-5ej97lG5SDVzelH018OXgboI FFvs0hmQ=.ec5da5d8-01db-4797-938b-0419a3c1d2ec@github.com> Message-ID: On Thu, 12 Jan 2023 15:10:19 GMT, Maurizio Cimadamore wrote: > Interesting example - I thought you might have been referring to a case where the class being analyzed was itself an exception. Yes - although that example doesn't compile (oops!). Just replace `catch (RuntimeException e)` with `catch (ThrownThis e)` and it should. > Question - shouldn't we conclude that this leak when we see throw this ? E.g. what if the constructor did not have a catch (or if the catch was of a different type) ? A thorough analysis would evaluate whether the exception was caught or not. But you're right - since we're not doing a thorough analysis, we should immediately declare a leak anytime we see `throw x` where `x` is a possible direct or indirect reference. Of course, this scenario should be unlikely in normal code. I will add a check for that. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Thu Jan 12 16:06:28 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Thu, 12 Jan 2023 16:06:28 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> Message-ID: On Thu, 12 Jan 2023 10:18:27 GMT, Maurizio Cimadamore wrote: >> Archie L. Cobbs has updated the pull request incrementally with two additional commits since the last revision: >> >> - Use the more appropriate Type comparison method Types.isSameType(). >> - Add some more comments to clarify how the analysis works. > > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 294: > >> 292: !(this.currentClass.sym.isSealed() && this.currentClass.permitting.isEmpty()) && >> 293: !(this.currentClass.sym.owner.kind == MTH) && >> 294: !this.privateOuter; > > Here, note that is the owner of the current class symbol is a method, that covers anonymous classes too, which is a part of `privateOuter`. So the only think we need to check here is whether "currentClass" is private, which is a simple predicate. No need to carry `privateOuter` I believe Unless you explicitly declare a nested class `private`, it won't have the `ACC_PRIVATE` flag, even though it is "implicitly private" because it has a `private` enclosing class. Example: $ cat PrivateOuter.java public class PrivateOuter { private static class Inner1 { static class Inner2 { } } } $ javap -v PrivateOuter$Inner1$Inner2 Classfile /Users/archie/proj/jdk/flex-test/classes/PrivateOuter$Inner1$Inner2.class Last modified Jan 12, 2023; size 408 bytes SHA-256 checksum 51ba6d39a5e66df2a078761d6424acbea7a8e32b8451f6ca7d2af49889673b2c Compiled from "PrivateOuter.java" class PrivateOuter$Inner1$Inner2 minor version: 0 major version: 63 flags: (0x0020) ACC_SUPER this_class: #7 // PrivateOuter$Inner1$Inner2 super_class: #2 // java/lang/Object ... So we have to keep track of this "implicit privateness" manually, which is what the `privateOuter` flag is for. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Thu Jan 12 16:24:37 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Thu, 12 Jan 2023 16:24:37 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> Message-ID: <2yMCKO6JFLW6MlAxdn1cRivontgIkZO8fCy-BexB6cg=.beb90f18-40b5-41eb-83c9-ec179e2ae2ff@github.com> On Thu, 12 Jan 2023 10:25:27 GMT, Maurizio Cimadamore wrote: >> Archie L. Cobbs has updated the pull request incrementally with two additional commits since the last revision: >> >> - Use the more appropriate Type comparison method Types.isSameType(). >> - Add some more comments to clarify how the analysis works. > > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 218: > >> 216: new TreeScanner() { >> 217: >> 218: private Lint lint = ThisEscapeAnalyzer.this.lint; > > On a first look I'm not sure about the granularity of suppression here. I believe that suppressing at the class level, or at the constructor level is enough. Allowing to further annotate var declarations and non-constructor methods, while doable, might actually be counter productive - in the sense that the annotation does not occur in the constructor (where you'd want to see it) but in some other method. I think the fact that a constructor is escaping (willingly) should be a visible thing. Something to consider. Two things... We need to support annotations on field declarations because their initializers are effectively mini-constructors. But we don't need it on local variables, parameters, etc. - too confusing. For annotations on methods, yes it's debatable. It can be handy if you have e.g. an `init()` method that all of your constructors invoke. However, I agree it's also confusing, so I will remove. But we should keep the notion that if a constructor invokes `this()`, and the invoked constructor has annotations suppressed, then we skip over the constructor invocation. I will make these updates. > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 304: > >> 302: >> 303: // We are looking for analyzable constructors only >> 304: final Symbol sym = entry.getKey(); > > This seems unused. And, if so, perhaps we only need a `Set`, not a map. Thanks, you're right, the map keys are not used here. I'll clean up the loop. But we still need a map, not a set, because the map is used elsewhere. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Thu Jan 12 16:31:21 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Thu, 12 Jan 2023 16:31:21 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> Message-ID: On Thu, 12 Jan 2023 10:32:19 GMT, Maurizio Cimadamore wrote: > If we have a class with a private constructor and public static factory invoking said constructor, and the constructor makes this escape, isn't that an issue we should detect? A static factory method will not create a subclassed instance, so there's no 'this' escape problem. But I admit I completely missed factory methods as a potential thing to worry about. Is it possible for a leak to be missed due to the use of a factory method? Hmm. I can't immediately think of how, but if you can come up with an example please share. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From mcimadamore at openjdk.org Thu Jan 12 16:46:31 2023 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Thu, 12 Jan 2023 16:46:31 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: <2yMCKO6JFLW6MlAxdn1cRivontgIkZO8fCy-BexB6cg=.beb90f18-40b5-41eb-83c9-ec179e2ae2ff@github.com> References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> <2yMCKO6JFLW6MlAxdn1cRivontgIkZO8fCy-BexB6cg=.beb90f18-40b5-41eb-83c9-ec179e2ae2ff@github.com> Message-ID: On Thu, 12 Jan 2023 16:20:12 GMT, Archie L. Cobbs wrote: >> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 218: >> >>> 216: new TreeScanner() { >>> 217: >>> 218: private Lint lint = ThisEscapeAnalyzer.this.lint; >> >> On a first look I'm not sure about the granularity of suppression here. I believe that suppressing at the class level, or at the constructor level is enough. Allowing to further annotate var declarations and non-constructor methods, while doable, might actually be counter productive - in the sense that the annotation does not occur in the constructor (where you'd want to see it) but in some other method. I think the fact that a constructor is escaping (willingly) should be a visible thing. Something to consider. > > Two things... > > We need to support annotations on field declarations because their initializers are effectively mini-constructors. But we don't need it on local variables, parameters, etc. - too confusing. > > For annotations on methods, yes it's debatable. It can be handy if you have e.g. an `init()` method that all of your constructors invoke. However, I agree it's also confusing, so I will remove. > > But we should keep the notion that if a constructor invokes `this()`, and the invoked constructor has annotations suppressed, then we skip over the constructor invocation. > > I will make these updates. Yep - I guess there's a general theme of "where do we want the warnings to be reported". My general feeling is that reporting a warning on the constructor might be enough - but I see that you try to generate a warning in the exact spot where the leakage happens - which I'm not sure if it's ok, or too clever. >> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 270: >> >>> 268: final boolean analyzable = this.currentClassIsExternallyExtendable() && >>> 269: TreeInfo.isConstructor(tree) && >>> 270: !tree.sym.isPrivate() && >> >> Why aren't private constructors analyzed? If we have a class with a private constructor and public static factory invoking said constructor, and the constructor makes `this` escape, isn't that an issue we should detect? > >> If we have a class with a private constructor and public static factory invoking said constructor, and the constructor makes this escape, isn't that an issue we should detect? > > A static factory method will not create a subclassed instance, so there's no 'this' escape problem. > > But I admit I completely missed factory methods as a potential thing to worry about. > > Is it possible for a leak to be missed due to the use of a factory method? > > Hmm. I can't immediately think of how, but if you can come up with an example please share. I guess what I'm thinking about: class Foo { private Foo() { m(this); } public void m() { ... } // overridable static Foo makeFoo() { return new Foo(); } } >> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 294: >> >>> 292: !(this.currentClass.sym.isSealed() && this.currentClass.permitting.isEmpty()) && >>> 293: !(this.currentClass.sym.owner.kind == MTH) && >>> 294: !this.privateOuter; >> >> Here, note that is the owner of the current class symbol is a method, that covers anonymous classes too, which is a part of `privateOuter`. So the only think we need to check here is whether "currentClass" is private, which is a simple predicate. No need to carry `privateOuter` I believe > > Unless you explicitly declare a nested class `private`, it won't have the `ACC_PRIVATE` flag, even though it is "implicitly private" because it has a `private` enclosing class. > > Example: > > $ cat PrivateOuter.java > public class PrivateOuter { > private static class Inner1 { > static class Inner2 { > } > } > } > $ javap -v PrivateOuter$Inner1$Inner2 > Classfile /Users/archie/proj/jdk/flex-test/classes/PrivateOuter$Inner1$Inner2.class > Last modified Jan 12, 2023; size 408 bytes > SHA-256 checksum 51ba6d39a5e66df2a078761d6424acbea7a8e32b8451f6ca7d2af49889673b2c > Compiled from "PrivateOuter.java" > class PrivateOuter$Inner1$Inner2 > minor version: 0 > major version: 63 > flags: (0x0020) ACC_SUPER > this_class: #7 // PrivateOuter$Inner1$Inner2 > super_class: #2 // java/lang/Object > ... > > > So we have to keep track of this "implicit privateness" manually, which is what the `privateOuter` flag is for. D'oh - missed the `|=` - so this keeps updating... ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Thu Jan 12 16:55:39 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Thu, 12 Jan 2023 16:55:39 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> Message-ID: On Thu, 12 Jan 2023 10:48:49 GMT, Maurizio Cimadamore wrote: >> Archie L. Cobbs has updated the pull request incrementally with two additional commits since the last revision: >> >> - Use the more appropriate Type comparison method Types.isSameType(). >> - Add some more comments to clarify how the analysis works. > > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 227: > >> 225: final boolean privateOuterPrev = this.privateOuter; >> 226: final Lint lintPrev = this.lint; >> 227: this.lint = this.lint.augment(tree.sym); > > general stylistic comment - I see here and everywhere in this class `this.xyz` - this is not the norm in the rest of the javac codebase, and it would be better to replace it with just `xyz` OK. I will reluctantly remove... `` > Why on earth wouldn't you want to make it clear which one of N outer classes a field comes from, and that it's a field, and not a variable declared somewhere off screen?? > > IMHO omitting 'this' qualifiers is effectively accepting the grave offense of code obfuscation in exchange for a tiny smidgen of brevity. > > It's definitely made it harder for me to read and understand the compiler, with all the levels of nesting it has. > `` I readily admit I'm probably in the minority on this and anyway it's a bikeshed thing so there's no point in debating it. I will go with the flow :) though I feel a little sorry for the next person who has to read this code. > From a documentation perspective it might carry a bit of value Yes, that's the purpose - the `final` is for the human viewer, not the compiler. Just trying to be helpful to the next person. But you're right it's inconsistent so I'll remove. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Thu Jan 12 17:16:34 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Thu, 12 Jan 2023 17:16:34 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> Message-ID: On Thu, 12 Jan 2023 10:56:53 GMT, Maurizio Cimadamore wrote: >> Archie L. Cobbs has updated the pull request incrementally with two additional commits since the last revision: >> >> - Use the more appropriate Type comparison method Types.isSameType(). >> - Add some more comments to clarify how the analysis works. > > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 411: > >> 409: final boolean referenceExpressionNode; >> 410: switch (tree.getTag()) { >> 411: case CASE: > > surprised to see `CASE` here - as that's not an expression I put it there because of switch expressions and `yeild`... ? ------------- PR: https://git.openjdk.org/jdk/pull/11874 From vromero at openjdk.org Thu Jan 12 17:43:26 2023 From: vromero at openjdk.org (Vicente Romero) Date: Thu, 12 Jan 2023 17:43:26 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: Message-ID: On Wed, 11 Jan 2023 03:30:03 GMT, Archie L. Cobbs wrote: >> This PR adds a new lint warning category `this-escape`. >> >> It also adds `@SuppressWarnings` annotations as needed to the JDK itself to allow the JDK to continue to compile with `-Xlint:all`. >> >> A 'this' escape warning is generated for a constructor `A()` in a class `A` when the compiler detects that the following situation is _in theory possible:_ >> * Some subclass `B extends A` exists, and `B` is defined in a separate source file (i.e., compilation unit) >> * Some constructor `B()` of `B` invokes `A()` as its superclass constructor >> * During the execution of `A()`, some non-static method of `B.foo()` could get invoked, perhaps indirectly >> >> In the above scenario, `B.foo()` would execute before `A()` has returned and before `B()` has performed any initialization. To the extent `B.foo()` accesses any fields of `B` - all of which are still uninitialized - it is likely to function incorrectly. >> >> Note, when determining if a 'this' escape is possible, the compiler makes no assumptions about code outside of the current compilation unit. It doesn't look outside of the current source file to see what might actually happen when a method is invoked. It does follow method and constructors within the current compilation unit, and applies a simplified union-of-all-possible-branches data flow analysis to see where 'this' could end up. >> >> From my review, virtually all of the warnings generated in the various JDK modules are valid warnings in the sense that a 'this' escape, as defined above, is really and truly possible. However, that doesn't imply that any bugs were found within the JDK - only that the possibility of a certain type of bug exists if certain superclass constructors are used by someone, somewhere, someday. >> >> For several "popular" classes, this PR also adds `@implNote`'s to the offending constructors so that subclass implementors are made aware of the threat. For one example, `TreeMap(Map)` invokes `putAll()` and `put()`. >> >> More details and a couple of motivating examples are given in an included [doc file](https://github.com/archiecobbs/jdk/blob/ThisEscape/src/java.base/share/classes/java/lang/doc-files/ThisEscape.html) that these `@implNote`'s link to. See also the recent thread on `amber-dev` for some background. >> >> Ideally, over time the owners of the various modules would review their `@SuppressWarnings("this-escape")` annotations and determine which other constructors also warranted such an `@implNote`. >> >> Because of all the`@SuppressWarnings` annotations, this PR touches a bunch of different JDK modules. My apologies for that. Adding these annotations was determined to be the more conservative approach, as compared to just excepting `this-escape` from various module builds globally. >> >> **Patch Navigation Guide** >> >> * Non-trivial compiler changes: >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties` >> >> * Javadoc additions of `@implNote`: >> >> * `src/java.base/share/classes/java/io/PipedReader.java` >> * `src/java.base/share/classes/java/io/PipedWriter.java` >> * `src/java.base/share/classes/java/lang/Throwable.java` >> * `src/java.base/share/classes/java/util/ArrayDeque.java` >> * `src/java.base/share/classes/java/util/EnumMap.java` >> * `src/java.base/share/classes/java/util/HashSet.java` >> * `src/java.base/share/classes/java/util/Hashtable.java` >> * `src/java.base/share/classes/java/util/LinkedList.java` >> * `src/java.base/share/classes/java/util/TreeMap.java` >> * `src/java.base/share/classes/java/util/TreeSet.java` >> >> * New unit tests >> * `test/langtools/tools/javac/warnings/ThisEscape/*.java` >> >> * **Everything else** is just adding `@SuppressWarnings("this-escape")` > > Archie L. Cobbs has updated the pull request incrementally with two additional commits since the last revision: > > - Use the more appropriate Type comparison method Types.isSameType(). > - Add some more comments to clarify how the analysis works. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 200: > 198: // > 199: > 200: public void analyzeTree(Env env) { nit: this method could be removed in favor of the overloaded version below src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 204: > 202: } > 203: > 204: public void analyzeTree(Env env, JCTree tree) { nit: `env` parameter doesn't seem to be used could be dropped I think ------------- PR: https://git.openjdk.org/jdk/pull/11874 From mcimadamore at openjdk.org Thu Jan 12 17:43:30 2023 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Thu, 12 Jan 2023 17:43:30 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> Message-ID: On Thu, 12 Jan 2023 17:13:55 GMT, Archie L. Cobbs wrote: >> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 411: >> >>> 409: final boolean referenceExpressionNode; >>> 410: switch (tree.getTag()) { >>> 411: case CASE: >> >> surprised to see `CASE` here - as that's not an expression > > I put it there because of switch expressions and `yeild`... ? Well, yield can... yield a value - `case` doesn't. So I'm confused. Also because the variable is called `referenceExpressionNode` and `CASE` is not an expression. Can `CASE` leave anything on the stack? YIELD does, but CASE? >> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 454: >> >>> 452: >>> 453: // If the expression type is incompatible with 'this', discard it >>> 454: if (type != null && !this.isSubtype(this.targetClass.sym.type, type)) >> >> Instead of adding the direct reference, and then having to check if the reference needs to be removed, would it be possible not to add the reference in the first place if the types mismatch? > > No because (for example) what if you cast? > > The thing you're casting might be compatible, but after the cast it might become incompatible. Uhm. Turns out I probably did not understand the filter correctly, and now I'm more dubious about what it actually does. Say you have this hierarchy: interface A { } class B { B() { A a = (A)this; ... } } class C extends B implements A { } ``` Pathological case, I know. But the filtering will end up dropping the expression Ref on the floor, right? (because B and A are unrelated). ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Thu Jan 12 17:43:36 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Thu, 12 Jan 2023 17:43:36 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> Message-ID: On Thu, 12 Jan 2023 11:09:35 GMT, Maurizio Cimadamore wrote: >> Archie L. Cobbs has updated the pull request incrementally with two additional commits since the last revision: >> >> - Use the more appropriate Type comparison method Types.isSameType(). >> - Add some more comments to clarify how the analysis works. > > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 444: > >> 442: if (referenceExpressionNode) { >> 443: >> 444: // We treat instance methods as having a "value" equal to their instance > > The comment is slightly misleading - e.g. I'd suggest clarifying "having a "value" whose type is the same as that of the class in which the method is defined" Agreed - will fix. > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 454: > >> 452: >> 453: // If the expression type is incompatible with 'this', discard it >> 454: if (type != null && !this.isSubtype(this.targetClass.sym.type, type)) > > Instead of adding the direct reference, and then having to check if the reference needs to be removed, would it be possible not to add the reference in the first place if the types mismatch? No because (for example) what if you cast? The thing you're casting might be compatible, but after the cast it might become incompatible. > This will then determine how to interpret this in the context of that method analysis - e.g. when we see a JCIdent for this, we create a direct/indirect ExprRef based on what the receiver kind was. Correct? Yes, exactly. When we "invoke" a method, we "preload" the set of current references that the method is going to have when it starts. That "preload" step includes any references from (a) the method receiver (non-static methods only) and (b) method parameters. To the extent the method receiver has a direct/indirect reference, that turns into a direct/indirect `ThisRef` during method execution. You can see this happen in the very next lines after what you quoted. But of course the method invocation (the "apply") could have been applied to any arbitrary expression as the receiver. > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 817: > >> 815: // Methods - the "value" of a non-static method is a reference to its instance >> 816: final Symbol sym = tree.sym; >> 817: if (sym.kind == MTH) { > > This is perhaps where filtering based on the declaring class could make sense (to avoid having to filter later) ? Perhaps this could also be centralized - e.g. whenever you create an ExprRef you also pass the type for it, and if the type matches that for the current class you create it and add to the list, otherwise you skip it. Yes but see previous comment regarding casting. > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 875: > >> 873: // Reference to this? >> 874: if (tree.name == names._this || tree.name == names._super) { >> 875: if (this.refs.contains(ThisRef.direct())) > > This idiom occurs quite a lot. If I'm correct, this basically amounts at asking as to whether the receiver of the method we're currently evaluating is direct or not (which is an invariant, given a method body - e.g. for a given method this "fact" should stay the same). If that's the case, perhaps capturing this in a flag could be better - then you could have just have a single method e.g. `XYZRef.create(boolean direct)`, and remove the branching (here and elsewhere). The code you quoted has nothing specifically to do with method invocations. This code is simply handing the evaluation of the expressions `this` and `super`. For example, `this` could just be a parameter we're passing to another method. When `this` or `super` expressions are evaluated, the thing left on top of the stack is a direct/indirect reference (i.e., an `ExprRef`) exactly when the there is a direct/indirect reference of type `ThisRef` in the current reference set. In cases where `this` is then "invoked", e.g., `this()`, the `ExprRef` (top of Java stack) becomes the method receiver, and when the method is "invoked" it turns back into a `ThisRef` (see earlier question). Regarding the optimization you mention, in light of the above I'm not sure it would still work. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Thu Jan 12 17:53:25 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Thu, 12 Jan 2023 17:53:25 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> Message-ID: On Thu, 12 Jan 2023 12:15:17 GMT, Maurizio Cimadamore wrote: >> Archie L. Cobbs has updated the pull request incrementally with two additional commits since the last revision: >> >> - Use the more appropriate Type comparison method Types.isSameType(). >> - Add some more comments to clarify how the analysis works. > > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 175: > >> 173: private DiagnosticPosition[] pendingWarning; >> 174: >> 175: // These fields are scoped to the CONSTRUCTOR OR INVOKED METHOD BEING ANALYZED > > Watch out for "all caps" Will fix. > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 900: > >> 898: final Type.ClassType currentClassType = (Type.ClassType)this.methodClass.sym.type; >> 899: final Type methodOwnerType = sym.owner.type; >> 900: if (this.isSubtype(currentClassType, methodOwnerType)) { > > I believe what you need here is not subtyping but subclassing - see `Symbol.isSubclass` Hmm, I tried using `Symbol.isSubclass()` but it caused test failures. Obviously I don't quite know what I'm doing and I'm loathe to break what is already working. Do you have a suggested patch? > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 909: > >> 907: >> 908: // Check for implicit outer 'this' reference >> 909: if (this.types.hasOuterClass(currentClassType, methodOwnerType)) { > > Similarly here - look for `Symbol.isEnclosedBy` Same comment as previous: I don't quite know what I'm doing and I'm loathe to break what is already working. Do you have a suggested patch? ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Thu Jan 12 18:00:36 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Thu, 12 Jan 2023 18:00:36 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> Message-ID: On Thu, 12 Jan 2023 12:17:32 GMT, Maurizio Cimadamore wrote: > There is a concept of push/popScope and then there's a separate concept of call stack (which is just a list of diagnostic position up to the point). I wonder if this could be better modeled by using a single class e.g. Scope/Frame which has a diagnostic position, plus other useful things. I think that would be more confusing, because they're really two different animals. Scopes only have meaning within a single method. They simply serve to bracket the lifetimes of `VarRef` references, following Java curly brace scope. When you "invoke" a method, you put aside the current stack of scopes and start over with an empty scope stack. They don't bridge between methods. Call stacks are just a list of method+code position therein, and they exist outside of any single method. They have nothing to do with Java scopes defined by curly braces. > Perhaps it might even be helpful to have a ref set on each scope, so that you don't have to attach a "depth" to each ref - the depth of the ref would be determined by the "scope" in which it appears. That's another way to skin the same cat... in fact I had a design like that before but then realized it was a lot simpler to just carry around one `RefSet`. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Thu Jan 12 18:09:27 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Thu, 12 Jan 2023 18:09:27 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> Message-ID: On Thu, 12 Jan 2023 12:26:27 GMT, Maurizio Cimadamore wrote: > Do we really need a set for this? There are surely other ways to model things. But I got myself really confused trying to build more complicated models. What I ended up with is this simple model that works: * There is a set of `Ref` subclasses that model the various types of 'this' references possible: `OuterRef`, `ExprRef`, etc. * There is a singleton `this.refs`, which just is a `Set`, containing the 'this' references that are alive at the current moment * As we "execute" code, all we need to do is update the `this.refs` based on what the current bit of code does E.g.... When a variable is assigned a value that has a reference, we add a `VarRef` for that variable. When we leave a scope, we remove any `Ref`'s that are no longer in scope. Before executing a method, we add `Ref`'s for the method receiver and parameter. When we return from a non-void method, we convert any `ReturnRef` into a `ExprRef`. Etc. THAT I can understand. I don't see converting the above into a bitmap or whatever as worth the additional complexity. We're not programming in perl here. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Thu Jan 12 18:16:25 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Thu, 12 Jan 2023 18:16:25 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: Message-ID: <1r69eKftXv6ZlGQP76mNrfgbldbDcMxhnyVOQ8oUV7U=.8facaf51-1f7e-486a-912e-a9a5912b7d88@github.com> On Thu, 12 Jan 2023 17:39:05 GMT, Vicente Romero wrote: >> Archie L. Cobbs has updated the pull request incrementally with two additional commits since the last revision: >> >> - Use the more appropriate Type comparison method Types.isSameType(). >> - Add some more comments to clarify how the analysis works. > > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 200: > >> 198: // >> 199: >> 200: public void analyzeTree(Env env) { > > nit: this method could be removed in favor of the overloaded version below Thanks - will fix. > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 204: > >> 202: } >> 203: >> 204: public void analyzeTree(Env env, JCTree tree) { > > nit: `env` parameter doesn't seem to be used could be dropped I think Thanks - will fix. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From mcimadamore at openjdk.org Thu Jan 12 18:16:27 2023 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Thu, 12 Jan 2023 18:16:27 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> Message-ID: On Thu, 12 Jan 2023 17:48:37 GMT, Archie L. Cobbs wrote: >> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 909: >> >>> 907: >>> 908: // Check for implicit outer 'this' reference >>> 909: if (this.types.hasOuterClass(currentClassType, methodOwnerType)) { >> >> Similarly here - look for `Symbol.isEnclosedBy` > > Same comment as previous: I don't quite know what I'm doing and I'm loathe to break what is already working. Do you have a suggested patch? I can't seem to be able to run tests - I get failures in the build: * For target support_test_micro_tools-classes__the.BUILD_INDIFY_batch: ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Thu Jan 12 18:16:31 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Thu, 12 Jan 2023 18:16:31 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> Message-ID: On Thu, 12 Jan 2023 12:28:12 GMT, Maurizio Cimadamore wrote: > This might also be related with the fact that we deal with return values in different ways than with e.g. values returned from a nested scope (where we just pop, and then copy all pending expression to the outer depth). Yes, a method return value that represents a reference is an `ExprRef` just before the `return` is actually executed, but then it turns into a `ReturnRef`. A `ReturnRef` is really just a yellow sticky note that reminds us "Hey whenever you finish 'executing' this method, remember that there is a reference in its return value". > This might also be related with the fact that we deal with return values in different ways than with e.g. values returned from a nested scope (where we just pop, and then copy all pending expression to the outer depth). Exactly. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From mcimadamore at openjdk.org Thu Jan 12 18:21:22 2023 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Thu, 12 Jan 2023 18:21:22 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> Message-ID: <1vfnyE9dnZELUp1To60nQYEUIre7g5pcfXHKKHOug0I=.9af24b57-2627-45d8-a7cc-1b4235e99237@github.com> On Thu, 12 Jan 2023 18:11:01 GMT, Maurizio Cimadamore wrote: >> Same comment as previous: I don't quite know what I'm doing and I'm loathe to break what is already working. Do you have a suggested patch? > > I can't seem to be able to run tests - I get failures in the build: > > > * For target support_test_micro_tools-classes__the.BUILD_INDIFY_batch: This patch: diff --git a/make/test/BuildMicrobenchmark.gmk b/make/test/BuildMicrobenchmark.gmk index 1c89328a388..7c3f0293edc 100644 --- a/make/test/BuildMicrobenchmark.gmk +++ b/make/test/BuildMicrobenchmark.gmk @@ -76,7 +76,7 @@ $(eval $(call SetupJavaCompilation, BUILD_INDIFY, \ TARGET_RELEASE := $(TARGET_RELEASE_BOOTJDK), \ SRC := $(TOPDIR)/test/jdk/java/lang/invoke, \ INCLUDE_FILES := indify/Indify.java, \ - DISABLED_WARNINGS := rawtypes serial options, \ + DISABLED_WARNINGS := this-escape rawtypes serial options, \ BIN := $(MICROBENCHMARK_TOOLS_CLASSES), \ JAVAC_FLAGS := -XDstringConcat=inline -Xprefer:newer, \ )) @@ -91,7 +91,7 @@ $(eval $(call SetupJavaCompilation, BUILD_JDK_MICROBENCHMARK, \ TARGET_RELEASE := $(TARGET_RELEASE_NEWJDK_UPGRADED), \ SMALL_JAVA := false, \ CLASSPATH := $(MICROBENCHMARK_CLASSPATH), \ - DISABLED_WARNINGS := processing rawtypes cast serial preview, \ + DISABLED_WARNINGS := this-escape processing rawtypes cast serial preview, \ SRC := $(MICROBENCHMARK_SRC), \ BIN := $(MICROBENCHMARK_CLASSES), \ JAVAC_FLAGS := --add-exports java.base/sun.security.util=ALL-UNNAMED \ diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java index 9d35c2fbc0a..4e2b1e558e7 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java @@ -897,6 +897,7 @@ class ThisEscapeAnalyzer extends TreeScanner { // Check for implicit 'this' reference final Type.ClassType currentClassType = (Type.ClassType)this.methodClass.sym.type; final Type methodOwnerType = sym.owner.type; + //if (currentClassType.tsym.isSubClass(sym.owner, types)) { if (this.isSubtype(currentClassType, methodOwnerType)) { if (this.refs.contains(ThisRef.direct())) this.refs.add(ExprRef.direct(this.depth)); @@ -906,6 +907,7 @@ class ThisEscapeAnalyzer extends TreeScanner { } // Check for implicit outer 'this' reference + // if (currentClassType.tsym.isEnclosedBy((ClassSymbol)sym.owner)) { if (this.types.hasOuterClass(currentClassType, methodOwnerType)) { if (this.refs.contains(OuterRef.direct())) this.refs.add(ExprRef.direct(this.depth)); Fixes the build failure. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Thu Jan 12 18:40:28 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Thu, 12 Jan 2023 18:40:28 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> <2yMCKO6JFLW6MlAxdn1cRivontgIkZO8fCy-BexB6cg=.beb90f18-40b5-41eb-83c9-ec179e2ae2ff@github.com> Message-ID: On Thu, 12 Jan 2023 16:40:33 GMT, Maurizio Cimadamore wrote: > I guess what I'm thinking about: No leak is possible in that example. * `new Foo()` creates an instance of `Foo` (not a subclass of `Foo`) therefore `m()` is not overridden * Any subclass of `Foo` that may exist in the outside world cannot use the `Foo()` constructor that leaks because it's private ------------- PR: https://git.openjdk.org/jdk/pull/11874 From mcimadamore at openjdk.org Thu Jan 12 18:43:21 2023 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Thu, 12 Jan 2023 18:43:21 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: <1vfnyE9dnZELUp1To60nQYEUIre7g5pcfXHKKHOug0I=.9af24b57-2627-45d8-a7cc-1b4235e99237@github.com> References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> <1vfnyE9dnZELUp1To60nQYEUIre7g5pcfXHKKHOug0I=.9af24b57-2627-45d8-a7cc-1b4235e99237@github.com> Message-ID: On Thu, 12 Jan 2023 18:18:38 GMT, Maurizio Cimadamore wrote: >> I can't seem to be able to run tests - I get failures in the build: >> >> >> * For target support_test_micro_tools-classes__the.BUILD_INDIFY_batch: > > This patch: > > > diff --git a/make/test/BuildMicrobenchmark.gmk b/make/test/BuildMicrobenchmark.gmk > index 1c89328a388..7c3f0293edc 100644 > --- a/make/test/BuildMicrobenchmark.gmk > +++ b/make/test/BuildMicrobenchmark.gmk > @@ -76,7 +76,7 @@ $(eval $(call SetupJavaCompilation, BUILD_INDIFY, \ > TARGET_RELEASE := $(TARGET_RELEASE_BOOTJDK), \ > SRC := $(TOPDIR)/test/jdk/java/lang/invoke, \ > INCLUDE_FILES := indify/Indify.java, \ > - DISABLED_WARNINGS := rawtypes serial options, \ > + DISABLED_WARNINGS := this-escape rawtypes serial options, \ > BIN := $(MICROBENCHMARK_TOOLS_CLASSES), \ > JAVAC_FLAGS := -XDstringConcat=inline -Xprefer:newer, \ > )) > @@ -91,7 +91,7 @@ $(eval $(call SetupJavaCompilation, BUILD_JDK_MICROBENCHMARK, \ > TARGET_RELEASE := $(TARGET_RELEASE_NEWJDK_UPGRADED), \ > SMALL_JAVA := false, \ > CLASSPATH := $(MICROBENCHMARK_CLASSPATH), \ > - DISABLED_WARNINGS := processing rawtypes cast serial preview, \ > + DISABLED_WARNINGS := this-escape processing rawtypes cast serial preview, \ > SRC := $(MICROBENCHMARK_SRC), \ > BIN := $(MICROBENCHMARK_CLASSES), \ > JAVAC_FLAGS := --add-exports java.base/sun.security.util=ALL-UNNAMED \ > diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java > index 9d35c2fbc0a..4e2b1e558e7 100644 > --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java > +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java > @@ -897,6 +897,7 @@ class ThisEscapeAnalyzer extends TreeScanner { > // Check for implicit 'this' reference > final Type.ClassType currentClassType = (Type.ClassType)this.methodClass.sym.type; > final Type methodOwnerType = sym.owner.type; > + //if (currentClassType.tsym.isSubClass(sym.owner, types)) { > if (this.isSubtype(currentClassType, methodOwnerType)) { > if (this.refs.contains(ThisRef.direct())) > this.refs.add(ExprRef.direct(this.depth)); > @@ -906,6 +907,7 @@ class ThisEscapeAnalyzer extends TreeScanner { > } > > // Check for implicit outer 'this' reference > + // if (currentClassType.tsym.isEnclosedBy((ClassSymbol)sym.owner)) { > if (this.types.hasOuterClass(currentClassType, methodOwnerType)) { > if (this.refs.contains(OuterRef.direct())) > this.refs.add(ExprRef.direct(this.depth)); > > > Fixes the build failure. This patch passes all tests: diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java index 9d35c2fbc0a..e755c54d0c8 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java @@ -451,7 +451,7 @@ class ThisEscapeAnalyzer extends TreeScanner { } // If the expression type is incompatible with 'this', discard it - if (type != null && !this.isSubtype(this.targetClass.sym.type, type)) + if (type != null && !this.targetClass.sym.isSubClass(type.tsym, types)) this.refs.remove(ExprRef.direct(this.depth)); } } @@ -672,7 +672,7 @@ class ThisEscapeAnalyzer extends TreeScanner { if (explicitOuterThis != null) { this.scan(explicitOuterThis); this.refs.removeExprs(this.depth, direct -> outerRefs.add(new OuterRef(direct))); - } else if (this.types.hasOuterClass(type, this.methodClass.type)) { + } else if (type.tsym.isEnclosedBy(this.methodClass.sym)) { if (this.refs.contains(ThisRef.direct())) outerRefs.add(OuterRef.direct()); if (this.refs.contains(ThisRef.indirect())) @@ -801,9 +801,8 @@ class ThisEscapeAnalyzer extends TreeScanner { // Explicit outer 'this' reference? final Type selectedType = this.types.erasure(tree.selected.type); if (selectedType.hasTag(CLASS)) { - final Type.ClassType selectedClassType = (Type.ClassType)selectedType; if (tree.name == this.names._this && - this.types.hasOuterClass(currentClassType, selectedClassType)) { + currentClassType.tsym.isEnclosedBy((ClassSymbol)selectedType.tsym)) { if (this.refs.contains(OuterRef.direct())) this.refs.add(ExprRef.direct(this.depth)); if (this.refs.contains(OuterRef.indirect())) @@ -895,9 +894,7 @@ class ThisEscapeAnalyzer extends TreeScanner { final MethodSymbol sym = (MethodSymbol)tree.sym; // Check for implicit 'this' reference - final Type.ClassType currentClassType = (Type.ClassType)this.methodClass.sym.type; - final Type methodOwnerType = sym.owner.type; - if (this.isSubtype(currentClassType, methodOwnerType)) { + if (methodClass.sym.isSubClass(sym.owner, types)) { if (this.refs.contains(ThisRef.direct())) this.refs.add(ExprRef.direct(this.depth)); if (this.refs.contains(ThisRef.indirect())) @@ -906,7 +903,7 @@ class ThisEscapeAnalyzer extends TreeScanner { } // Check for implicit outer 'this' reference - if (this.types.hasOuterClass(currentClassType, methodOwnerType)) { + if (methodClass.sym.isEnclosedBy((ClassSymbol)sym.owner)) { if (this.refs.contains(OuterRef.direct())) this.refs.add(ExprRef.direct(this.depth)); Btw, I believe a similar trick can be used in TreeInfo.isExplicitThisReference. If I'm correct, `hasOuterClass` should probably be removed as it duplicates already existing functionality. Since I'm bringing this up, as TreeInfo.isExplicitThisReference is only used by the new analyzer, it would be cleaner if it was defined there, at least until it's clear it might be needed by some other client. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From mcimadamore at openjdk.org Thu Jan 12 18:51:33 2023 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Thu, 12 Jan 2023 18:51:33 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> <2yMCKO6JFLW6MlAxdn1cRivontgIkZO8fCy-BexB6cg=.beb90f18-40b5-41eb-83c9-ec179e2ae2ff@github.com> Message-ID: On Thu, 12 Jan 2023 18:37:06 GMT, Archie L. Cobbs wrote: >> I guess what I'm thinking about: >> >> class Foo { >> private Foo() { >> m(this); >> } >> >> public void m() { ... } // overridable >> >> static Foo makeFoo() { return new Foo(); } >> } > >> I guess what I'm thinking about: > > No leak is possible in that example. > * `new Foo()` creates an instance of `Foo` (not a subclass of `Foo`) therefore `m()` is not overridden > * Any subclass of `Foo` that may exist in the outside world cannot use the `Foo()` constructor that leaks because it's private but what if `m` is a static method in a separate compilation unit? Should it be able to observe a partially initialized Foo? ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Thu Jan 12 19:04:22 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Thu, 12 Jan 2023 19:04:22 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> Message-ID: On Thu, 12 Jan 2023 17:29:22 GMT, Maurizio Cimadamore wrote: >> I put it there because of switch expressions and `yeild`... ? > > Well, yield can... yield a value - `case` doesn't. So I'm confused. Also because the variable is called `referenceExpressionNode` and `CASE` is not an expression. Can `CASE` leave anything on the stack? YIELD does, but CASE? It's just an artifact of the way switch expressions are handled: @Override public void visitSwitchExpression(JCSwitchExpression tree) { visitScoped(tree, true, t -> { scan(t.selector); refs.discardExprs(depth); RefSet combinedRefs = new RefSet<>(); for (List cases = t.cases; cases.nonEmpty(); cases = cases.tail) { scan(cases.head); combinedRefs.addAll(refs.removeExprs(depth)); } refs.addAll(combinedRefs); }); } @Override public void visitCase(JCCase tree) { scan(tree.stats); // no need to scan labels } After scanning a switch expression case, the `yield`'ed value will be on the top of the stack. Then `visitCase` does NOT remove it, so that it can be picked up and removed by `visitSwitchExpression()`. But this can be cleaned up a little bit, by having `visitSwitchExpression()` not delegate to `visitCase()` but rather iterate through the case statements itself directly. Then we can remove the `CASE` as you suggest. Also I realized we need to handle `yield`'ed values like `return` values, i.e., collect and remember them until the entire case is complete. I'll fix. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From mcimadamore at openjdk.org Thu Jan 12 19:04:25 2023 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Thu, 12 Jan 2023 19:04:25 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> Message-ID: On Thu, 12 Jan 2023 17:33:48 GMT, Archie L. Cobbs wrote: >> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 875: >> >>> 873: // Reference to this? >>> 874: if (tree.name == names._this || tree.name == names._super) { >>> 875: if (this.refs.contains(ThisRef.direct())) >> >> This idiom occurs quite a lot. If I'm correct, this basically amounts at asking as to whether the receiver of the method we're currently evaluating is direct or not (which is an invariant, given a method body - e.g. for a given method this "fact" should stay the same). If that's the case, perhaps capturing this in a flag could be better - then you could have just have a single method e.g. `XYZRef.create(boolean direct)`, and remove the branching (here and elsewhere). > > The code you quoted has nothing specifically to do with method invocations. This code is simply handing the evaluation of the expressions `this` and `super`. For example, `this` could just be a parameter we're passing to another method. > > When `this` or `super` expressions are evaluated, the thing left on top of the stack is a direct/indirect reference (i.e., an `ExprRef`) exactly when the there is a direct/indirect reference of type `ThisRef` in the current reference set. > > In cases where `this` is then "invoked", e.g., `this()`, the `ExprRef` (top of Java stack) becomes the method receiver, and when the method is "invoked" it turns back into a `ThisRef` (see earlier question). > > Regarding the optimization you mention, in light of the above I'm not sure it would still work. My point is about who puts ThisRef in the set to begin with. It seems to me that ThisRef is put there at the start of a method analysis. After which, there's several code points where we say "if there's a direct ThisRef in the set, do this, otherwise, if there's an indirect ThisRef in the set, do that". But the ThisRef (whether indirect or direct) seems set once and for all (when we start the analysis, and then inside visitApply). There is also this bit in `visitReference`: case SUPER: if (this.refs.contains(ThisRef.direct())) receiverRefs.add(ThisRef.direct()); if (this.refs.contains(ThisRef.indirect())) receiverRefs.add(ThisRef.indirect()); break; But this doesn't change what I'm saying - there seems to be a general property when we execute this analysis which says whether the current execution context has a direct `this` or not. This seems to me better captured with a boolean, which is then fed back to all the other various downstream ref creation. The main observation, at least for me, is that the code unifies everything under refs, when in reality there are different aspects: * the set of variables that can point to this, whether directly or indirectly (this is truly a set) * whether the current context has a direct or indirect this (this seems more a flag to me) * whether the expression on top of stack is direct/indirect this reference or not (again, 3 possible values here) - but granted, there `depth` here to take into account, so you probably end up with a set (given that we don't want to model a scope with its own set) When reading the code, seeing set expression like containment checks or removals for things that doesn't seem to be truly sets (unless I'm missing something) was genuinely confusing me. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Thu Jan 12 19:15:20 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Thu, 12 Jan 2023 19:15:20 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> Message-ID: On Thu, 12 Jan 2023 17:40:36 GMT, Maurizio Cimadamore wrote: > But the filtering will end up dropping the expression Ref on the floor, right? (because B and A are unrelated). Ah, I see what you mean. Here's a more complete example: public class CastLeak { public CastLeak() { ((CastLeak)(Runnable)this).mightLeak(); } public void mightLeak() { } } That would be a leak for any subclass that implements `Runnable`. Yet no warning is generated. So the filtering by expression type is going to potentially create false negatives. But it also eliminates a bunch of false positives. And the false negatives are probably all somewhat pathological like the example above. So I still think it's worth doing. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Thu Jan 12 19:27:24 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Thu, 12 Jan 2023 19:27:24 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> <1vfnyE9dnZELUp1To60nQYEUIre7g5pcfXHKKHOug0I=.9af24b57-2627-45d8-a7cc-1b4235e99237@github.com> Message-ID: On Thu, 12 Jan 2023 18:40:38 GMT, Maurizio Cimadamore wrote: >> This patch: >> >> >> diff --git a/make/test/BuildMicrobenchmark.gmk b/make/test/BuildMicrobenchmark.gmk >> index 1c89328a388..7c3f0293edc 100644 >> --- a/make/test/BuildMicrobenchmark.gmk >> +++ b/make/test/BuildMicrobenchmark.gmk >> @@ -76,7 +76,7 @@ $(eval $(call SetupJavaCompilation, BUILD_INDIFY, \ >> TARGET_RELEASE := $(TARGET_RELEASE_BOOTJDK), \ >> SRC := $(TOPDIR)/test/jdk/java/lang/invoke, \ >> INCLUDE_FILES := indify/Indify.java, \ >> - DISABLED_WARNINGS := rawtypes serial options, \ >> + DISABLED_WARNINGS := this-escape rawtypes serial options, \ >> BIN := $(MICROBENCHMARK_TOOLS_CLASSES), \ >> JAVAC_FLAGS := -XDstringConcat=inline -Xprefer:newer, \ >> )) >> @@ -91,7 +91,7 @@ $(eval $(call SetupJavaCompilation, BUILD_JDK_MICROBENCHMARK, \ >> TARGET_RELEASE := $(TARGET_RELEASE_NEWJDK_UPGRADED), \ >> SMALL_JAVA := false, \ >> CLASSPATH := $(MICROBENCHMARK_CLASSPATH), \ >> - DISABLED_WARNINGS := processing rawtypes cast serial preview, \ >> + DISABLED_WARNINGS := this-escape processing rawtypes cast serial preview, \ >> SRC := $(MICROBENCHMARK_SRC), \ >> BIN := $(MICROBENCHMARK_CLASSES), \ >> JAVAC_FLAGS := --add-exports java.base/sun.security.util=ALL-UNNAMED \ >> diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java >> index 9d35c2fbc0a..4e2b1e558e7 100644 >> --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java >> +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java >> @@ -897,6 +897,7 @@ class ThisEscapeAnalyzer extends TreeScanner { >> // Check for implicit 'this' reference >> final Type.ClassType currentClassType = (Type.ClassType)this.methodClass.sym.type; >> final Type methodOwnerType = sym.owner.type; >> + //if (currentClassType.tsym.isSubClass(sym.owner, types)) { >> if (this.isSubtype(currentClassType, methodOwnerType)) { >> if (this.refs.contains(ThisRef.direct())) >> this.refs.add(ExprRef.direct(this.depth)); >> @@ -906,6 +907,7 @@ class ThisEscapeAnalyzer extends TreeScanner { >> } >> >> // Check for implicit outer 'this' reference >> + // if (currentClassType.tsym.isEnclosedBy((ClassSymbol)sym.owner)) { >> if (this.types.hasOuterClass(currentClassType, methodOwnerType)) { >> if (this.refs.contains(OuterRef.direct())) >> this.refs.add(ExprRef.direct(this.depth)); >> >> >> Fixes the build failure. > > This patch passes all tests: > > > diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java > index 9d35c2fbc0a..e755c54d0c8 100644 > --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java > +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java > @@ -451,7 +451,7 @@ class ThisEscapeAnalyzer extends TreeScanner { > } > > // If the expression type is incompatible with 'this', discard it > - if (type != null && !this.isSubtype(this.targetClass.sym.type, type)) > + if (type != null && !this.targetClass.sym.isSubClass(type.tsym, types)) > this.refs.remove(ExprRef.direct(this.depth)); > } > } > @@ -672,7 +672,7 @@ class ThisEscapeAnalyzer extends TreeScanner { > if (explicitOuterThis != null) { > this.scan(explicitOuterThis); > this.refs.removeExprs(this.depth, direct -> outerRefs.add(new OuterRef(direct))); > - } else if (this.types.hasOuterClass(type, this.methodClass.type)) { > + } else if (type.tsym.isEnclosedBy(this.methodClass.sym)) { > if (this.refs.contains(ThisRef.direct())) > outerRefs.add(OuterRef.direct()); > if (this.refs.contains(ThisRef.indirect())) > @@ -801,9 +801,8 @@ class ThisEscapeAnalyzer extends TreeScanner { > // Explicit outer 'this' reference? > final Type selectedType = this.types.erasure(tree.selected.type); > if (selectedType.hasTag(CLASS)) { > - final Type.ClassType selectedClassType = (Type.ClassType)selectedType; > if (tree.name == this.names._this && > - this.types.hasOuterClass(currentClassType, selectedClassType)) { > + currentClassType.tsym.isEnclosedBy((ClassSymbol)selectedType.tsym)) { > if (this.refs.contains(OuterRef.direct())) > this.refs.add(ExprRef.direct(this.depth)); > if (this.refs.contains(OuterRef.indirect())) > @@ -895,9 +894,7 @@ class ThisEscapeAnalyzer extends TreeScanner { > final MethodSymbol sym = (MethodSymbol)tree.sym; > > // Check for implicit 'this' reference > - final Type.ClassType currentClassType = (Type.ClassType)this.methodClass.sym.type; > - final Type methodOwnerType = sym.owner.type; > - if (this.isSubtype(currentClassType, methodOwnerType)) { > + if (methodClass.sym.isSubClass(sym.owner, types)) { > if (this.refs.contains(ThisRef.direct())) > this.refs.add(ExprRef.direct(this.depth)); > if (this.refs.contains(ThisRef.indirect())) > @@ -906,7 +903,7 @@ class ThisEscapeAnalyzer extends TreeScanner { > } > > // Check for implicit outer 'this' reference > - if (this.types.hasOuterClass(currentClassType, methodOwnerType)) { > + if (methodClass.sym.isEnclosedBy((ClassSymbol)sym.owner)) { > if (this.refs.contains(OuterRef.direct())) > this.refs.add(ExprRef.direct(this.depth)); > > > Btw, I believe a similar trick can be used in TreeInfo.isExplicitThisReference. If I'm correct, `hasOuterClass` should probably be removed as it duplicates already existing functionality. > > Since I'm bringing this up, as TreeInfo.isExplicitThisReference is only used by the new analyzer, it would be cleaner if it was defined there, at least until it's clear it might be needed by some other client. Weird. I don't get that build failure. Neither does github... I have been relying on the github build "Actions" succeeding to determine if "the build works" and according to that it is building. I will add the `DISABLED_WARNINGS` in any case. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Thu Jan 12 21:07:28 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Thu, 12 Jan 2023 21:07:28 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> <2yMCKO6JFLW6MlAxdn1cRivontgIkZO8fCy-BexB6cg=.beb90f18-40b5-41eb-83c9-ec179e2ae2ff@github.com> Message-ID: On Thu, 12 Jan 2023 18:48:25 GMT, Maurizio Cimadamore wrote: >>> I guess what I'm thinking about: >> >> No leak is possible in that example. >> * `new Foo()` creates an instance of `Foo` (not a subclass of `Foo`) therefore `m()` is not overridden >> * Any subclass of `Foo` that may exist in the outside world cannot use the `Foo()` constructor that leaks because it's private > > but what if `m` is a static method in a separate compilation unit? Should it be able to observe a partially initialized Foo? Caring about the proper initialization of any class in the _current_ compilation unit is an explicit non-goal. We only care about bugs where a superclass and subclass are in separate compilation units. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Thu Jan 12 21:07:30 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Thu, 12 Jan 2023 21:07:30 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> <1vfnyE9dnZELUp1To60nQYEUIre7g5pcfXHKKHOug0I=.9af24b57-2627-45d8-a7cc-1b4235e99237@github.com> Message-ID: On Thu, 12 Jan 2023 19:24:50 GMT, Archie L. Cobbs wrote: >> This patch passes all tests: >> >> >> diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java >> index 9d35c2fbc0a..e755c54d0c8 100644 >> --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java >> +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java >> @@ -451,7 +451,7 @@ class ThisEscapeAnalyzer extends TreeScanner { >> } >> >> // If the expression type is incompatible with 'this', discard it >> - if (type != null && !this.isSubtype(this.targetClass.sym.type, type)) >> + if (type != null && !this.targetClass.sym.isSubClass(type.tsym, types)) >> this.refs.remove(ExprRef.direct(this.depth)); >> } >> } >> @@ -672,7 +672,7 @@ class ThisEscapeAnalyzer extends TreeScanner { >> if (explicitOuterThis != null) { >> this.scan(explicitOuterThis); >> this.refs.removeExprs(this.depth, direct -> outerRefs.add(new OuterRef(direct))); >> - } else if (this.types.hasOuterClass(type, this.methodClass.type)) { >> + } else if (type.tsym.isEnclosedBy(this.methodClass.sym)) { >> if (this.refs.contains(ThisRef.direct())) >> outerRefs.add(OuterRef.direct()); >> if (this.refs.contains(ThisRef.indirect())) >> @@ -801,9 +801,8 @@ class ThisEscapeAnalyzer extends TreeScanner { >> // Explicit outer 'this' reference? >> final Type selectedType = this.types.erasure(tree.selected.type); >> if (selectedType.hasTag(CLASS)) { >> - final Type.ClassType selectedClassType = (Type.ClassType)selectedType; >> if (tree.name == this.names._this && >> - this.types.hasOuterClass(currentClassType, selectedClassType)) { >> + currentClassType.tsym.isEnclosedBy((ClassSymbol)selectedType.tsym)) { >> if (this.refs.contains(OuterRef.direct())) >> this.refs.add(ExprRef.direct(this.depth)); >> if (this.refs.contains(OuterRef.indirect())) >> @@ -895,9 +894,7 @@ class ThisEscapeAnalyzer extends TreeScanner { >> final MethodSymbol sym = (MethodSymbol)tree.sym; >> >> // Check for implicit 'this' reference >> - final Type.ClassType currentClassType = (Type.ClassType)this.methodClass.sym.type; >> - final Type methodOwnerType = sym.owner.type; >> - if (this.isSubtype(currentClassType, methodOwnerType)) { >> + if (methodClass.sym.isSubClass(sym.owner, types)) { >> if (this.refs.contains(ThisRef.direct())) >> this.refs.add(ExprRef.direct(this.depth)); >> if (this.refs.contains(ThisRef.indirect())) >> @@ -906,7 +903,7 @@ class ThisEscapeAnalyzer extends TreeScanner { >> } >> >> // Check for implicit outer 'this' reference >> - if (this.types.hasOuterClass(currentClassType, methodOwnerType)) { >> + if (methodClass.sym.isEnclosedBy((ClassSymbol)sym.owner)) { >> if (this.refs.contains(OuterRef.direct())) >> this.refs.add(ExprRef.direct(this.depth)); >> >> >> Btw, I believe a similar trick can be used in TreeInfo.isExplicitThisReference. If I'm correct, `hasOuterClass` should probably be removed as it duplicates already existing functionality. >> >> Since I'm bringing this up, as TreeInfo.isExplicitThisReference is only used by the new analyzer, it would be cleaner if it was defined there, at least until it's clear it might be needed by some other client. > > Weird. I don't get that build failure. > > Neither does github... I have been relying on the github build "Actions" succeeding to determine if "the build works" and according to that it is building. > > I will add the `DISABLED_WARNINGS` in any case. Thanks for the patch! The semantics of `hasOuterClass()` returns false if A and B are the same class, while `isEnclosedBy()` returns true if A and B are the same class. However, I don't think it would actually matter in practice... Regardless, I'll add the extra equality comparison and apply your patch and also the suggestions to integrate `isExplicitThisReference()` and eliminate `hasOuterClass()`. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Thu Jan 12 21:31:25 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Thu, 12 Jan 2023 21:31:25 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> Message-ID: On Thu, 12 Jan 2023 19:01:10 GMT, Maurizio Cimadamore wrote: >> The code you quoted has nothing specifically to do with method invocations. This code is simply handing the evaluation of the expressions `this` and `super`. For example, `this` could just be a parameter we're passing to another method. >> >> When `this` or `super` expressions are evaluated, the thing left on top of the stack is a direct/indirect reference (i.e., an `ExprRef`) exactly when the there is a direct/indirect reference of type `ThisRef` in the current reference set. >> >> In cases where `this` is then "invoked", e.g., `this()`, the `ExprRef` (top of Java stack) becomes the method receiver, and when the method is "invoked" it turns back into a `ThisRef` (see earlier question). >> >> Regarding the optimization you mention, in light of the above I'm not sure it would still work. > > My point is about who puts ThisRef in the set to begin with. It seems to me that ThisRef is put there at the start of a method analysis. After which, there's several code points where we say "if there's a direct ThisRef in the set, do this, otherwise, if there's an indirect ThisRef in the set, do that". But the ThisRef (whether indirect or direct) seems set once and for all (when we start the analysis, and then inside visitApply). > > There is also this bit in `visitReference`: > > > case SUPER: > if (this.refs.contains(ThisRef.direct())) > receiverRefs.add(ThisRef.direct()); > if (this.refs.contains(ThisRef.indirect())) > receiverRefs.add(ThisRef.indirect()); > break; > > > But this doesn't change what I'm saying - there seems to be a general property when we execute this analysis which says whether the current execution context has a direct `this` or not. This seems to me better captured with a boolean, which is then fed back to all the other various downstream ref creation. > > The main observation, at least for me, is that the code unifies everything under refs, when in reality there are different aspects: > > * the set of variables that can point to this, whether directly or indirectly (this is truly a set) > * whether the current context has a direct or indirect this (this seems more a flag to me) > * whether the expression on top of stack is direct/indirect this reference or not (again, 3 possible values here) - but granted, there `depth` here to take into account, so you probably end up with a set (given that we don't want to model a scope with its own set) > > When reading the code, seeing set expression like containment checks or removals for things that doesn't seem to be truly sets (unless I'm missing something) was genuinely confusing me. I get what you're saying - it seems silly to model what is essentially a fixed, boolean property with the membership of a singleton in a set field, rather than with a simple boolean field. There is a conceptual trade-off though... a lot of the code relates to converting `Ref`'s from one type to another. For example, as pointed out above, a method invocation might convert a `ExprRef` to a `ThisRef`, then to a `ReturnRef`'s, etc. Having these things all be considered part of the same family helps conceptually. The fact that a direct `ThisRef` is a singleton is just a coincidence in this way of looking at things. The benefit is the simplicity of being able to think of the data model as "just a set of references". For example, methods like `RefSet.replaceExprs()` become less elegant (or basically impossible) if there have to be special cases for each type of reference, whereas currently we can do clean stuff like this: @Override public void visitReturn(JCReturn tree) { scan(tree.expr); refs.replaceExprs(depth, ReturnRef::new); } But I'm also realizing now that several places can be cleaned up by taking this event further. E.g., we should replace this code: if (refs.contains(ThisRef.direct())) outerRefs.add(OuterRef.direct()); if (refs.contains(ThisRef.indirect())) outerRefs.add(OuterRef.indirect()); with something like this: refs.mapInto(outerRefs, ThisRef.class, OuterRef::new); I will go through and refactor to do that and clean things up a little more. > When reading the code, seeing set expression like containment checks or removals for things that doesn't seem to be truly sets (unless I'm missing something) was genuinely confusing me. Probably my fault for not providing better documentation of the overall "set of references" conceptual approach. FWIW I added a little bit more in f83a9cf0. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From mcimadamore at openjdk.org Thu Jan 12 21:47:24 2023 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Thu, 12 Jan 2023 21:47:24 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> Message-ID: On Thu, 12 Jan 2023 21:28:12 GMT, Archie L. Cobbs wrote: >> My point is about who puts ThisRef in the set to begin with. It seems to me that ThisRef is put there at the start of a method analysis. After which, there's several code points where we say "if there's a direct ThisRef in the set, do this, otherwise, if there's an indirect ThisRef in the set, do that". But the ThisRef (whether indirect or direct) seems set once and for all (when we start the analysis, and then inside visitApply). >> >> There is also this bit in `visitReference`: >> >> >> case SUPER: >> if (this.refs.contains(ThisRef.direct())) >> receiverRefs.add(ThisRef.direct()); >> if (this.refs.contains(ThisRef.indirect())) >> receiverRefs.add(ThisRef.indirect()); >> break; >> >> >> But this doesn't change what I'm saying - there seems to be a general property when we execute this analysis which says whether the current execution context has a direct `this` or not. This seems to me better captured with a boolean, which is then fed back to all the other various downstream ref creation. >> >> The main observation, at least for me, is that the code unifies everything under refs, when in reality there are different aspects: >> >> * the set of variables that can point to this, whether directly or indirectly (this is truly a set) >> * whether the current context has a direct or indirect this (this seems more a flag to me) >> * whether the expression on top of stack is direct/indirect this reference or not (again, 3 possible values here) - but granted, there `depth` here to take into account, so you probably end up with a set (given that we don't want to model a scope with its own set) >> >> When reading the code, seeing set expression like containment checks or removals for things that doesn't seem to be truly sets (unless I'm missing something) was genuinely confusing me. > > I get what you're saying - it seems silly to model what is essentially a fixed, boolean property with the membership of a singleton in a set field, rather than with a simple boolean field. > > There is a conceptual trade-off though... a lot of the code relates to converting `Ref`'s from one type to another. For example, as pointed out above, a method invocation might convert a `ExprRef` to a `ThisRef`, then to a `ReturnRef`'s, etc. Having these things all be considered part of the same family helps conceptually. The fact that a direct `ThisRef` is a singleton is just a coincidence in this way of looking at things. > > The benefit is the simplicity of being able to think of the data model as "just a set of references". > > For example, methods like `RefSet.replaceExprs()` become less elegant (or basically impossible) if there have to be special cases for each type of reference, whereas currently we can do clean stuff like this: > > > @Override > public void visitReturn(JCReturn tree) { > scan(tree.expr); > refs.replaceExprs(depth, ReturnRef::new); > } > > > But I'm also realizing now that several places can be cleaned up by taking this event further. E.g., we should replace this code: > > if (refs.contains(ThisRef.direct())) > outerRefs.add(OuterRef.direct()); > if (refs.contains(ThisRef.indirect())) > outerRefs.add(OuterRef.indirect()); > > with something like this: > > refs.mapInto(outerRefs, ThisRef.class, OuterRef::new); > > > I will go through and refactor to do that and clean things up a little more. > >> When reading the code, seeing set expression like containment checks or removals for things that doesn't seem to be truly sets (unless I'm missing something) was genuinely confusing me. > > Probably my fault for not providing better documentation of the overall "set of references" conceptual approach. FWIW I added a little bit more in f83a9cf0. > ```java > ```java > if (refs.contains(ThisRef.direct())) > outerRefs.add(OuterRef.direct()); > if (refs.contains(ThisRef.indirect())) > outerRefs.add(OuterRef.indirect()); > ``` > > > > > > > > > > > > with something like this: > ```java > refs.mapInto(outerRefs, ThisRef.class, OuterRef::new); > ``` > ``` This sounds like a good idea, that idiom is quite widespread, so it should help avoiding repetition. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Fri Jan 13 04:04:36 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Fri, 13 Jan 2023 04:04:36 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v8] In-Reply-To: References: Message-ID: > This PR adds a new lint warning category `this-escape`. > > It also adds `@SuppressWarnings` annotations as needed to the JDK itself to allow the JDK to continue to compile with `-Xlint:all`. > > A 'this' escape warning is generated for a constructor `A()` in a class `A` when the compiler detects that the following situation is _in theory possible:_ > * Some subclass `B extends A` exists, and `B` is defined in a separate source file (i.e., compilation unit) > * Some constructor `B()` of `B` invokes `A()` as its superclass constructor > * During the execution of `A()`, some non-static method of `B.foo()` could get invoked, perhaps indirectly > > In the above scenario, `B.foo()` would execute before `A()` has returned and before `B()` has performed any initialization. To the extent `B.foo()` accesses any fields of `B` - all of which are still uninitialized - it is likely to function incorrectly. > > Note, when determining if a 'this' escape is possible, the compiler makes no assumptions about code outside of the current compilation unit. It doesn't look outside of the current source file to see what might actually happen when a method is invoked. It does follow method and constructors within the current compilation unit, and applies a simplified union-of-all-possible-branches data flow analysis to see where 'this' could end up. > > From my review, virtually all of the warnings generated in the various JDK modules are valid warnings in the sense that a 'this' escape, as defined above, is really and truly possible. However, that doesn't imply that any bugs were found within the JDK - only that the possibility of a certain type of bug exists if certain superclass constructors are used by someone, somewhere, someday. > > For several "popular" classes, this PR also adds `@implNote`'s to the offending constructors so that subclass implementors are made aware of the threat. For one example, `TreeMap(Map)` invokes `putAll()` and `put()`. > > More details and a couple of motivating examples are given in an included [doc file](https://github.com/archiecobbs/jdk/blob/ThisEscape/src/java.base/share/classes/java/lang/doc-files/ThisEscape.html) that these `@implNote`'s link to. See also the recent thread on `amber-dev` for some background. > > Ideally, over time the owners of the various modules would review their `@SuppressWarnings("this-escape")` annotations and determine which other constructors also warranted such an `@implNote`. > > Because of all the`@SuppressWarnings` annotations, this PR touches a bunch of different JDK modules. My apologies for that. Adding these annotations was determined to be the more conservative approach, as compared to just excepting `this-escape` from various module builds globally. > > **Patch Navigation Guide** > > * Non-trivial compiler changes: > * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties` > > * Javadoc additions of `@implNote`: > > * `src/java.base/share/classes/java/io/PipedReader.java` > * `src/java.base/share/classes/java/io/PipedWriter.java` > * `src/java.base/share/classes/java/lang/Throwable.java` > * `src/java.base/share/classes/java/util/ArrayDeque.java` > * `src/java.base/share/classes/java/util/EnumMap.java` > * `src/java.base/share/classes/java/util/HashSet.java` > * `src/java.base/share/classes/java/util/Hashtable.java` > * `src/java.base/share/classes/java/util/LinkedList.java` > * `src/java.base/share/classes/java/util/TreeMap.java` > * `src/java.base/share/classes/java/util/TreeSet.java` > > * New unit tests > * `test/langtools/tools/javac/warnings/ThisEscape/*.java` > > * **Everything else** is just adding `@SuppressWarnings("this-escape")` Archie L. Cobbs has updated the pull request incrementally with 16 additional commits since the last revision: - Fix bug where all but the last yeild statement were being ignored. - Add method RefSet.mapInto() and use to refactor/clean up. - Fix possible assertion failure when handling if statements. - Use Symbol methods isSubClass() and isEnclosedBy() instead of homebrew stuff. Suggested-by: mcimadamore - Add comment regarding limitations of expresison type filtering. - Add a few more DISABLED_WARNINGS to unbreak build. - Clean up handling of switch expressions a bit. - Remove unused method variant of analyzeTree(). - Avoid all caps in comments. - Clarify confusing comment. - ... and 6 more: https://git.openjdk.org/jdk/compare/6e96a7d7...edf3c3f5 ------------- Changes: - all: https://git.openjdk.org/jdk/pull/11874/files - new: https://git.openjdk.org/jdk/pull/11874/files/6e96a7d7..edf3c3f5 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=11874&range=07 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=11874&range=06-07 Stats: 540 lines in 8 files changed: 120 ins; 92 del; 328 mod Patch: https://git.openjdk.org/jdk/pull/11874.diff Fetch: git fetch https://git.openjdk.org/jdk pull/11874/head:pull/11874 PR: https://git.openjdk.org/jdk/pull/11874 From mcimadamore at openjdk.org Fri Jan 13 04:04:37 2023 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 13 Jan 2023 04:04:37 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> Message-ID: On Thu, 12 Jan 2023 19:12:27 GMT, Archie L. Cobbs wrote: >> Uhm. Turns out I probably did not understand the filter correctly, and now I'm more dubious about what it actually does. Say you have this hierarchy: >> >> >> interface A { } >> class B { >> B() { >> A a = (A)this; >> ... >> } >> } >> class C extends B implements A { } >> ``` >> >> Pathological case, I know. But the filtering will end up dropping the expression Ref on the floor, right? (because B and A are unrelated). > >> But the filtering will end up dropping the expression Ref on the floor, right? (because B and A are unrelated). > > Ah, I see what you mean. > > Here's a more complete example: > > public class CastLeak { > > public CastLeak() { > ((CastLeak)(Runnable)this).mightLeak(); > } > > public void mightLeak() { > } > } > > That would be a leak for any subclass that implements `Runnable`. Yet no warning is generated. > > So the filtering by expression type is going to potentially create false negatives. But it also eliminates a bunch of false positives. And the false negatives are probably all somewhat pathological like the example above. > > So I still think it's worth doing. Ok - I thought false negative was the thing to absolutely avoid - and that was the no. 1 concern. I think a possible approach to keep both the filtering and the code more or less similar to what you have, is to save the type of the expression in the ExprRef. Then, I believe that, at the end of scan() you can just get whatever type is there, and check that it's the correct one, if not drop it. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Fri Jan 13 04:04:37 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Fri, 13 Jan 2023 04:04:37 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> Message-ID: On Thu, 12 Jan 2023 21:47:28 GMT, Maurizio Cimadamore wrote: > Ok - I thought false negative was the thing to absolutely avoid - and that was the no. 1 concern. You're right. I think at the time I reasoned that it would be unusual enough for the type of an expression to start as an instanceof X, then change to not being an instanceof X, and then change back, that it was worth it to go ahead and filter these out. But admittedly that was based on intuition, not science. > I think a possible approach to keep both the filtering and the code more or less similar to what you have, is to save the type of the expression in the ExprRef. Then, I believe that, at the end of scan() you can just get whatever type is there, and check that it's the correct one, if not drop it. That's a nice idea... thanks. I'll play around with it some. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From mcimadamore at openjdk.org Fri Jan 13 11:01:24 2023 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 13 Jan 2023 11:01:24 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> <2yMCKO6JFLW6MlAxdn1cRivontgIkZO8fCy-BexB6cg=.beb90f18-40b5-41eb-83c9-ec179e2ae2ff@github.com> Message-ID: On Thu, 12 Jan 2023 21:04:09 GMT, Archie L. Cobbs wrote: >> but what if `m` is a static method in a separate compilation unit? Should it be able to observe a partially initialized Foo? > > Caring about the proper initialization of any class in the _current_ compilation unit is an explicit non-goal. > > We only care about bugs where a superclass and subclass are in separate compilation units. So, to clarify, in this case: import java.util.*; class B { final Object ref; private B(Object ref) { Foo.consume(this); this.ref = ref; } } Even though `this` leaks to a method clearly before it is fully initialized, we do not care because there can be no subclass involved observing this. I guess I was confused because, while subclasses are a particularly sneaky case where uninitialized values can show up, the above leak seems potentially dangerous as well - we're effectively leaking a class whose final field has not been initialized! That said, if that was discussed, and it was decided for the warning not to deal with this case, that's ok. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From mcimadamore at openjdk.org Fri Jan 13 11:11:31 2023 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 13 Jan 2023 11:11:31 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> <2yMCKO6JFLW6MlAxdn1cRivontgIkZO8fCy-BexB6cg=.beb90f18-40b5-41eb-83c9-ec179e2ae2ff@github.com> Message-ID: On Fri, 13 Jan 2023 10:58:33 GMT, Maurizio Cimadamore wrote: >> Caring about the proper initialization of any class in the _current_ compilation unit is an explicit non-goal. >> >> We only care about bugs where a superclass and subclass are in separate compilation units. > > So, to clarify, in this case: > > > import java.util.*; > > class B { > final Object ref; > > private B(Object ref) { > Foo.consume(this); > this.ref = ref; > } > } > > > Even though `this` leaks to a method clearly before it is fully initialized, we do not care because there can be no subclass involved observing this. I guess I was confused because, while subclasses are a particularly sneaky case where uninitialized values can show up, the above leak seems potentially dangerous as well - we're effectively leaking a class whose final field has not been initialized! > > That said, if that was discussed, and it was decided for the warning not to deal with this case, that's ok. Perhaps my confusion might come from the name `this-escape` of the lint warning - which seems overpromising in this respect. But I looked at the description of the lint warning using `javac --help-lint` and I got this: this-escape Warn when a constructor invokes a method that could be overriden in a subclass; Which indeed aligns well with what this PR is doing. So that's ok. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From mcimadamore at openjdk.org Fri Jan 13 11:11:31 2023 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 13 Jan 2023 11:11:31 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> <2yMCKO6JFLW6MlAxdn1cRivontgIkZO8fCy-BexB6cg=.beb90f18-40b5-41eb-83c9-ec179e2ae2ff@github.com> Message-ID: On Fri, 13 Jan 2023 11:05:51 GMT, Maurizio Cimadamore wrote: >> So, to clarify, in this case: >> >> >> import java.util.*; >> >> class B { >> final Object ref; >> >> private B(Object ref) { >> Foo.consume(this); >> this.ref = ref; >> } >> } >> >> >> Even though `this` leaks to a method clearly before it is fully initialized, we do not care because there can be no subclass involved observing this. I guess I was confused because, while subclasses are a particularly sneaky case where uninitialized values can show up, the above leak seems potentially dangerous as well - we're effectively leaking a class whose final field has not been initialized! >> >> That said, if that was discussed, and it was decided for the warning not to deal with this case, that's ok. > > Perhaps my confusion might come from the name `this-escape` of the lint warning - which seems overpromising in this respect. But I looked at the description of the lint warning using `javac --help-lint` and I got this: > > > this-escape Warn when a constructor invokes a method that could be overriden in a subclass; > > > Which indeed aligns well with what this PR is doing. So that's ok. Something seems to be up with the lint description for this-escape - compare this: serial Warn about Serializable classes that do not have a serialVersionUID field. Also warn about other suspect declarations in Serializable and Externalizable classes and interfaces. with this: this-escape Warn when a constructor invokes a method that could be overriden in a subclass; such a method would execute before the subclass constructor completes its initialization. Indentation seems to be missing, which causes readability issues in the `--help-lint` output. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From vromero at openjdk.org Fri Jan 13 12:45:34 2023 From: vromero at openjdk.org (Vicente Romero) Date: Fri, 13 Jan 2023 12:45:34 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v8] In-Reply-To: References: Message-ID: On Fri, 13 Jan 2023 04:04:36 GMT, Archie L. Cobbs wrote: >> This PR adds a new lint warning category `this-escape`. >> >> It also adds `@SuppressWarnings` annotations as needed to the JDK itself to allow the JDK to continue to compile with `-Xlint:all`. >> >> A 'this' escape warning is generated for a constructor `A()` in a class `A` when the compiler detects that the following situation is _in theory possible:_ >> * Some subclass `B extends A` exists, and `B` is defined in a separate source file (i.e., compilation unit) >> * Some constructor `B()` of `B` invokes `A()` as its superclass constructor >> * During the execution of `A()`, some non-static method of `B.foo()` could get invoked, perhaps indirectly >> >> In the above scenario, `B.foo()` would execute before `A()` has returned and before `B()` has performed any initialization. To the extent `B.foo()` accesses any fields of `B` - all of which are still uninitialized - it is likely to function incorrectly. >> >> Note, when determining if a 'this' escape is possible, the compiler makes no assumptions about code outside of the current compilation unit. It doesn't look outside of the current source file to see what might actually happen when a method is invoked. It does follow method and constructors within the current compilation unit, and applies a simplified union-of-all-possible-branches data flow analysis to see where 'this' could end up. >> >> From my review, virtually all of the warnings generated in the various JDK modules are valid warnings in the sense that a 'this' escape, as defined above, is really and truly possible. However, that doesn't imply that any bugs were found within the JDK - only that the possibility of a certain type of bug exists if certain superclass constructors are used by someone, somewhere, someday. >> >> For several "popular" classes, this PR also adds `@implNote`'s to the offending constructors so that subclass implementors are made aware of the threat. For one example, `TreeMap(Map)` invokes `putAll()` and `put()`. >> >> More details and a couple of motivating examples are given in an included [doc file](https://github.com/archiecobbs/jdk/blob/ThisEscape/src/java.base/share/classes/java/lang/doc-files/ThisEscape.html) that these `@implNote`'s link to. See also the recent thread on `amber-dev` for some background. >> >> Ideally, over time the owners of the various modules would review their `@SuppressWarnings("this-escape")` annotations and determine which other constructors also warranted such an `@implNote`. >> >> Because of all the`@SuppressWarnings` annotations, this PR touches a bunch of different JDK modules. My apologies for that. Adding these annotations was determined to be the more conservative approach, as compared to just excepting `this-escape` from various module builds globally. >> >> **Patch Navigation Guide** >> >> * Non-trivial compiler changes: >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties` >> >> * Javadoc additions of `@implNote`: >> >> * `src/java.base/share/classes/java/io/PipedReader.java` >> * `src/java.base/share/classes/java/io/PipedWriter.java` >> * `src/java.base/share/classes/java/lang/Throwable.java` >> * `src/java.base/share/classes/java/util/ArrayDeque.java` >> * `src/java.base/share/classes/java/util/EnumMap.java` >> * `src/java.base/share/classes/java/util/HashSet.java` >> * `src/java.base/share/classes/java/util/Hashtable.java` >> * `src/java.base/share/classes/java/util/LinkedList.java` >> * `src/java.base/share/classes/java/util/TreeMap.java` >> * `src/java.base/share/classes/java/util/TreeSet.java` >> >> * New unit tests >> * `test/langtools/tools/javac/warnings/ThisEscape/*.java` >> >> * **Everything else** is just adding `@SuppressWarnings("this-escape")` > > Archie L. Cobbs has updated the pull request incrementally with 16 additional commits since the last revision: > > - Fix bug where all but the last yeild statement were being ignored. > - Add method RefSet.mapInto() and use to refactor/clean up. > - Fix possible assertion failure when handling if statements. > - Use Symbol methods isSubClass() and isEnclosedBy() instead of homebrew stuff. > > Suggested-by: mcimadamore > - Add comment regarding limitations of expresison type filtering. > - Add a few more DISABLED_WARNINGS to unbreak build. > - Clean up handling of switch expressions a bit. > - Remove unused method variant of analyzeTree(). > - Avoid all caps in comments. > - Clarify confusing comment. > - ... and 6 more: https://git.openjdk.org/jdk/compare/6e96a7d7...edf3c3f5 src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 516: > 514: Name name = TreeInfo.name(invoke.meth); > 515: if (name == names._super) { > 516: scanInitializers(); it seems like the code scan initializers every time it finds a super() invocation, I guess that this scanning could be done once per class ------------- PR: https://git.openjdk.org/jdk/pull/11874 From vromero at openjdk.org Fri Jan 13 14:34:40 2023 From: vromero at openjdk.org (Vicente Romero) Date: Fri, 13 Jan 2023 14:34:40 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v8] In-Reply-To: References: Message-ID: On Fri, 13 Jan 2023 04:04:36 GMT, Archie L. Cobbs wrote: >> This PR adds a new lint warning category `this-escape`. >> >> It also adds `@SuppressWarnings` annotations as needed to the JDK itself to allow the JDK to continue to compile with `-Xlint:all`. >> >> A 'this' escape warning is generated for a constructor `A()` in a class `A` when the compiler detects that the following situation is _in theory possible:_ >> * Some subclass `B extends A` exists, and `B` is defined in a separate source file (i.e., compilation unit) >> * Some constructor `B()` of `B` invokes `A()` as its superclass constructor >> * During the execution of `A()`, some non-static method of `B.foo()` could get invoked, perhaps indirectly >> >> In the above scenario, `B.foo()` would execute before `A()` has returned and before `B()` has performed any initialization. To the extent `B.foo()` accesses any fields of `B` - all of which are still uninitialized - it is likely to function incorrectly. >> >> Note, when determining if a 'this' escape is possible, the compiler makes no assumptions about code outside of the current compilation unit. It doesn't look outside of the current source file to see what might actually happen when a method is invoked. It does follow method and constructors within the current compilation unit, and applies a simplified union-of-all-possible-branches data flow analysis to see where 'this' could end up. >> >> From my review, virtually all of the warnings generated in the various JDK modules are valid warnings in the sense that a 'this' escape, as defined above, is really and truly possible. However, that doesn't imply that any bugs were found within the JDK - only that the possibility of a certain type of bug exists if certain superclass constructors are used by someone, somewhere, someday. >> >> For several "popular" classes, this PR also adds `@implNote`'s to the offending constructors so that subclass implementors are made aware of the threat. For one example, `TreeMap(Map)` invokes `putAll()` and `put()`. >> >> More details and a couple of motivating examples are given in an included [doc file](https://github.com/archiecobbs/jdk/blob/ThisEscape/src/java.base/share/classes/java/lang/doc-files/ThisEscape.html) that these `@implNote`'s link to. See also the recent thread on `amber-dev` for some background. >> >> Ideally, over time the owners of the various modules would review their `@SuppressWarnings("this-escape")` annotations and determine which other constructors also warranted such an `@implNote`. >> >> Because of all the`@SuppressWarnings` annotations, this PR touches a bunch of different JDK modules. My apologies for that. Adding these annotations was determined to be the more conservative approach, as compared to just excepting `this-escape` from various module builds globally. >> >> **Patch Navigation Guide** >> >> * Non-trivial compiler changes: >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties` >> >> * Javadoc additions of `@implNote`: >> >> * `src/java.base/share/classes/java/io/PipedReader.java` >> * `src/java.base/share/classes/java/io/PipedWriter.java` >> * `src/java.base/share/classes/java/lang/Throwable.java` >> * `src/java.base/share/classes/java/util/ArrayDeque.java` >> * `src/java.base/share/classes/java/util/EnumMap.java` >> * `src/java.base/share/classes/java/util/HashSet.java` >> * `src/java.base/share/classes/java/util/Hashtable.java` >> * `src/java.base/share/classes/java/util/LinkedList.java` >> * `src/java.base/share/classes/java/util/TreeMap.java` >> * `src/java.base/share/classes/java/util/TreeSet.java` >> >> * New unit tests >> * `test/langtools/tools/javac/warnings/ThisEscape/*.java` >> >> * **Everything else** is just adding `@SuppressWarnings("this-escape")` > > Archie L. Cobbs has updated the pull request incrementally with 16 additional commits since the last revision: > > - Fix bug where all but the last yeild statement were being ignored. > - Add method RefSet.mapInto() and use to refactor/clean up. > - Fix possible assertion failure when handling if statements. > - Use Symbol methods isSubClass() and isEnclosedBy() instead of homebrew stuff. > > Suggested-by: mcimadamore > - Add comment regarding limitations of expresison type filtering. > - Add a few more DISABLED_WARNINGS to unbreak build. > - Clean up handling of switch expressions a bit. > - Remove unused method variant of analyzeTree(). > - Avoid all caps in comments. > - Clarify confusing comment. > - ... and 6 more: https://git.openjdk.org/jdk/compare/6e96a7d7...edf3c3f5 src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 533: > 531: if (sym != null && > 532: sym.owner.kind == TYP && > 533: ((ClassSymbol)sym.owner).fullname == names.java_lang_Object && nit: in general we use another idiom for this in the compiler: sym.owner.type.tsym == syms.objectType.tsym where `syms` is an instance of: `com.sun.tools.javac.code.Symtab` ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Fri Jan 13 15:11:48 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Fri, 13 Jan 2023 15:11:48 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> <2yMCKO6JFLW6MlAxdn1cRivontgIkZO8fCy-BexB6cg=.beb90f18-40b5-41eb-83c9-ec179e2ae2ff@github.com> Message-ID: On Fri, 13 Jan 2023 11:08:33 GMT, Maurizio Cimadamore wrote: >> Perhaps my confusion might come from the name `this-escape` of the lint warning - which seems overpromising in this respect. But I looked at the description of the lint warning using `javac --help-lint` and I got this: >> >> >> this-escape Warn when a constructor invokes a method that could be overriden in a subclass; >> >> >> Which indeed aligns well with what this PR is doing. So that's ok. > > Something seems to be up with the lint description for this-escape - compare this: > > > serial Warn about Serializable classes that do not have a serialVersionUID field. > Also warn about other suspect declarations in Serializable and Externalizable classes and interfaces. > > with this: > > > this-escape Warn when a constructor invokes a method that could be overriden in a subclass; > such a method would execute before the subclass constructor completes its initialization. > > > Indentation seems to be missing, which causes readability issues in the `--help-lint` output. > I guess I was confused because, while subclasses are a particularly sneaky case where uninitialized values can show up, the above leak seems potentially dangerous as well... Yes - and this very question did come up in the discussions around this warning (see amber-dev). The decision was to go with drawing the "warning boundary" at the compilation unit. The reasoning is that (a) this aligns with the compiler's "knowledge boundary", i.e., we can know for sure from code inspection, and also (b) focuses the warning on the particularly pernicious aspect of these bugs, which is that they arise from the non-obvious interaction among two or more files - even when looking at any single one of those files, there doesn't seem to be any apparent problem. In other words, we decided "not to try to save any single source code from itself". But I think it's still an interesting question. Maybe experience will provide more guidance over time. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Fri Jan 13 15:11:49 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Fri, 13 Jan 2023 15:11:49 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> <2yMCKO6JFLW6MlAxdn1cRivontgIkZO8fCy-BexB6cg=.beb90f18-40b5-41eb-83c9-ec179e2ae2ff@github.com> Message-ID: On Fri, 13 Jan 2023 15:08:43 GMT, Archie L. Cobbs wrote: >> Something seems to be up with the lint description for this-escape - compare this: >> >> >> serial Warn about Serializable classes that do not have a serialVersionUID field. >> Also warn about other suspect declarations in Serializable and Externalizable classes and interfaces. >> >> with this: >> >> >> this-escape Warn when a constructor invokes a method that could be overriden in a subclass; >> such a method would execute before the subclass constructor completes its initialization. >> >> >> Indentation seems to be missing, which causes readability issues in the `--help-lint` output. > >> I guess I was confused because, while subclasses are a particularly sneaky case where uninitialized values can show up, the above leak seems potentially dangerous as well... > > Yes - and this very question did come up in the discussions around this warning (see amber-dev). > > The decision was to go with drawing the "warning boundary" at the compilation unit. The reasoning is that (a) this aligns with the compiler's "knowledge boundary", i.e., we can know for sure from code inspection, and also (b) focuses the warning on the particularly pernicious aspect of these bugs, which is that they arise from the non-obvious interaction among two or more files - even when looking at any single one of those files, there doesn't seem to be any apparent problem. In other words, we decided "not to try to save any single source code from itself". > > But I think it's still an interesting question. Maybe experience will provide more guidance over time. > Something seems to be up with the lint description for this-escape - compare this: Oops, will fix - thanks. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Fri Jan 13 15:16:59 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Fri, 13 Jan 2023 15:16:59 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v8] In-Reply-To: References: Message-ID: On Fri, 13 Jan 2023 12:42:24 GMT, Vicente Romero wrote: >> Archie L. Cobbs has updated the pull request incrementally with 16 additional commits since the last revision: >> >> - Fix bug where all but the last yeild statement were being ignored. >> - Add method RefSet.mapInto() and use to refactor/clean up. >> - Fix possible assertion failure when handling if statements. >> - Use Symbol methods isSubClass() and isEnclosedBy() instead of homebrew stuff. >> >> Suggested-by: mcimadamore >> - Add comment regarding limitations of expresison type filtering. >> - Add a few more DISABLED_WARNINGS to unbreak build. >> - Clean up handling of switch expressions a bit. >> - Remove unused method variant of analyzeTree(). >> - Avoid all caps in comments. >> - Clarify confusing comment. >> - ... and 6 more: https://git.openjdk.org/jdk/compare/6e96a7d7...edf3c3f5 > > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 516: > >> 514: Name name = TreeInfo.name(invoke.meth); >> 515: if (name == names._super) { >> 516: scanInitializers(); > > it seems like the code scan initializers every time it finds a super() invocation, I guess that this scanning could be done once per class Yes... I did it that way is so that it doesn't require any adaptation if/when JDK-8194743 ever gets implemented. And it keeps the code a little simpler in exchange for a little redundancy. I'm happy to fix this if you think it is necessary though. > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 533: > >> 531: if (sym != null && >> 532: sym.owner.kind == TYP && >> 533: ((ClassSymbol)sym.owner).fullname == names.java_lang_Object && > > nit: in general we use another idiom for this in the compiler: > > sym.owner.type.tsym == syms.objectType.tsym > > where `syms` is an instance of: `com.sun.tools.javac.code.Symtab` Thanks - will fix. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From mcimadamore at openjdk.org Fri Jan 13 16:09:37 2023 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 13 Jan 2023 16:09:37 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> <2yMCKO6JFLW6MlAxdn1cRivontgIkZO8fCy-BexB6cg=.beb90f18-40b5-41eb-83c9-ec179e2ae2ff@github.com> Message-ID: On Fri, 13 Jan 2023 15:08:59 GMT, Archie L. Cobbs wrote: >>> I guess I was confused because, while subclasses are a particularly sneaky case where uninitialized values can show up, the above leak seems potentially dangerous as well... >> >> Yes - and this very question did come up in the discussions around this warning (see amber-dev). >> >> The decision was to go with drawing the "warning boundary" at the compilation unit. The reasoning is that (a) this aligns with the compiler's "knowledge boundary", i.e., we can know for sure from code inspection, and also (b) focuses the warning on the particularly pernicious aspect of these bugs, which is that they arise from the non-obvious interaction among two or more files - even when looking at any single one of those files, there doesn't seem to be any apparent problem. In other words, we decided "not to try to save any single source code from itself". >> >> But I think it's still an interesting question. Maybe experience will provide more guidance over time. > >> Something seems to be up with the lint description for this-escape - compare this: > > Oops, will fix - thanks. > The decision was to go with drawing the "warning boundary" at the compilation unit. The reasoning is that (a) this aligns with the compiler's "knowledge boundary", i.e., we can know for sure from code inspection, and also (b) focuses the warning on the particularly pernicious aspect of these bugs, which is that they arise from the non-obvious interaction among two or more files Sorry for being picky - you mention this "compilation unit" boundary before, but this is not really the reason here. Note that in my example B constructor calls out to a static method that is "outside" the boundary. The reason as to why my example is not flagged is simply that "escaping" is defined as "escaping into a subclass method", not just "escaping from the constructor (into some other compilation unit)". ------------- PR: https://git.openjdk.org/jdk/pull/11874 From vromero at openjdk.org Fri Jan 13 16:15:32 2023 From: vromero at openjdk.org (Vicente Romero) Date: Fri, 13 Jan 2023 16:15:32 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v8] In-Reply-To: References: Message-ID: <77lMG_P3_ZGjTegQictMdNN1IKjWixuzLWy5-GbHYnI=.bdbfc529-2ac8-4bba-b3a6-d08f0977e372@github.com> On Fri, 13 Jan 2023 15:14:05 GMT, Archie L. Cobbs wrote: >> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 516: >> >>> 514: Name name = TreeInfo.name(invoke.meth); >>> 515: if (name == names._super) { >>> 516: scanInitializers(); >> >> it seems like the code scan initializers every time it finds a super() invocation, I guess that this scanning could be done once per class > > Yes... I did it that way is so that it doesn't require any adaptation if/when JDK-8194743 ever gets implemented. And it keeps the code a little simpler in exchange for a little redundancy. > > I'm happy to fix this if you think it is necessary though. I'm OK either way we can revisit this later either as part of this PR or in a future one. I let it to your consideration ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Fri Jan 13 16:23:39 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Fri, 13 Jan 2023 16:23:39 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> <2yMCKO6JFLW6MlAxdn1cRivontgIkZO8fCy-BexB6cg=.beb90f18-40b5-41eb-83c9-ec179e2ae2ff@github.com> Message-ID: On Fri, 13 Jan 2023 16:06:04 GMT, Maurizio Cimadamore wrote: >>> Something seems to be up with the lint description for this-escape - compare this: >> >> Oops, will fix - thanks. > >> The decision was to go with drawing the "warning boundary" at the compilation unit. The reasoning is that (a) this aligns with the compiler's "knowledge boundary", i.e., we can know for sure from code inspection, and also (b) focuses the warning on the particularly pernicious aspect of these bugs, which is that they arise from the non-obvious interaction among two or more files > > Sorry for being picky - you mention this "compilation unit" boundary before, but this is not really the reason here. Note that in my example B constructor calls out to a static method that is "outside" the boundary. The reason as to why my example is not flagged is simply that "escaping" is defined as "escaping into a subclass method", not just "escaping from the constructor (into some other compilation unit)". Oops, you're right, I answered the wrong question so to speak. The "must involve a subclass" requirement is another dimension on which a "boundary" was declared. This was also part of the original discussion. So yes the requirement is: "requires involvement of a subclass" **AND** "that subclass lives in a separate compilation unit". ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Fri Jan 13 16:23:42 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Fri, 13 Jan 2023 16:23:42 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v8] In-Reply-To: <77lMG_P3_ZGjTegQictMdNN1IKjWixuzLWy5-GbHYnI=.bdbfc529-2ac8-4bba-b3a6-d08f0977e372@github.com> References: <77lMG_P3_ZGjTegQictMdNN1IKjWixuzLWy5-GbHYnI=.bdbfc529-2ac8-4bba-b3a6-d08f0977e372@github.com> Message-ID: On Fri, 13 Jan 2023 16:12:50 GMT, Vicente Romero wrote: >> Yes... I did it that way is so that it doesn't require any adaptation if/when JDK-8194743 ever gets implemented. And it keeps the code a little simpler in exchange for a little redundancy. >> >> I'm happy to fix this if you think it is necessary though. > > I'm OK either way we can revisit this later either as part of this PR or in a future one. I let it to your consideration Sounds good - thanks. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From vromero at openjdk.org Fri Jan 13 17:38:27 2023 From: vromero at openjdk.org (Vicente Romero) Date: Fri, 13 Jan 2023 17:38:27 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v8] In-Reply-To: References: Message-ID: On Fri, 13 Jan 2023 04:04:36 GMT, Archie L. Cobbs wrote: >> This PR adds a new lint warning category `this-escape`. >> >> It also adds `@SuppressWarnings` annotations as needed to the JDK itself to allow the JDK to continue to compile with `-Xlint:all`. >> >> A 'this' escape warning is generated for a constructor `A()` in a class `A` when the compiler detects that the following situation is _in theory possible:_ >> * Some subclass `B extends A` exists, and `B` is defined in a separate source file (i.e., compilation unit) >> * Some constructor `B()` of `B` invokes `A()` as its superclass constructor >> * During the execution of `A()`, some non-static method of `B.foo()` could get invoked, perhaps indirectly >> >> In the above scenario, `B.foo()` would execute before `A()` has returned and before `B()` has performed any initialization. To the extent `B.foo()` accesses any fields of `B` - all of which are still uninitialized - it is likely to function incorrectly. >> >> Note, when determining if a 'this' escape is possible, the compiler makes no assumptions about code outside of the current compilation unit. It doesn't look outside of the current source file to see what might actually happen when a method is invoked. It does follow method and constructors within the current compilation unit, and applies a simplified union-of-all-possible-branches data flow analysis to see where 'this' could end up. >> >> From my review, virtually all of the warnings generated in the various JDK modules are valid warnings in the sense that a 'this' escape, as defined above, is really and truly possible. However, that doesn't imply that any bugs were found within the JDK - only that the possibility of a certain type of bug exists if certain superclass constructors are used by someone, somewhere, someday. >> >> For several "popular" classes, this PR also adds `@implNote`'s to the offending constructors so that subclass implementors are made aware of the threat. For one example, `TreeMap(Map)` invokes `putAll()` and `put()`. >> >> More details and a couple of motivating examples are given in an included [doc file](https://github.com/archiecobbs/jdk/blob/ThisEscape/src/java.base/share/classes/java/lang/doc-files/ThisEscape.html) that these `@implNote`'s link to. See also the recent thread on `amber-dev` for some background. >> >> Ideally, over time the owners of the various modules would review their `@SuppressWarnings("this-escape")` annotations and determine which other constructors also warranted such an `@implNote`. >> >> Because of all the`@SuppressWarnings` annotations, this PR touches a bunch of different JDK modules. My apologies for that. Adding these annotations was determined to be the more conservative approach, as compared to just excepting `this-escape` from various module builds globally. >> >> **Patch Navigation Guide** >> >> * Non-trivial compiler changes: >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties` >> >> * Javadoc additions of `@implNote`: >> >> * `src/java.base/share/classes/java/io/PipedReader.java` >> * `src/java.base/share/classes/java/io/PipedWriter.java` >> * `src/java.base/share/classes/java/lang/Throwable.java` >> * `src/java.base/share/classes/java/util/ArrayDeque.java` >> * `src/java.base/share/classes/java/util/EnumMap.java` >> * `src/java.base/share/classes/java/util/HashSet.java` >> * `src/java.base/share/classes/java/util/Hashtable.java` >> * `src/java.base/share/classes/java/util/LinkedList.java` >> * `src/java.base/share/classes/java/util/TreeMap.java` >> * `src/java.base/share/classes/java/util/TreeSet.java` >> >> * New unit tests >> * `test/langtools/tools/javac/warnings/ThisEscape/*.java` >> >> * **Everything else** is just adding `@SuppressWarnings("this-escape")` > > Archie L. Cobbs has updated the pull request incrementally with 16 additional commits since the last revision: > > - Fix bug where all but the last yeild statement were being ignored. > - Add method RefSet.mapInto() and use to refactor/clean up. > - Fix possible assertion failure when handling if statements. > - Use Symbol methods isSubClass() and isEnclosedBy() instead of homebrew stuff. > > Suggested-by: mcimadamore > - Add comment regarding limitations of expresison type filtering. > - Add a few more DISABLED_WARNINGS to unbreak build. > - Clean up handling of switch expressions a bit. > - Remove unused method variant of analyzeTree(). > - Avoid all caps in comments. > - Clarify confusing comment. > - ... and 6 more: https://git.openjdk.org/jdk/compare/6e96a7d7...edf3c3f5 src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 685: > 683: > 684: @Override > 685: public void visitDoLoop(JCDoWhileLoop tree) { I was thinking, code can also loop using labels and `break` / `continue`, not something we need to cover as part of this prototype but could be a future TODO that we can document ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Fri Jan 13 17:52:31 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Fri, 13 Jan 2023 17:52:31 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v8] In-Reply-To: References: Message-ID: On Fri, 13 Jan 2023 17:35:08 GMT, Vicente Romero wrote: >> Archie L. Cobbs has updated the pull request incrementally with 16 additional commits since the last revision: >> >> - Fix bug where all but the last yeild statement were being ignored. >> - Add method RefSet.mapInto() and use to refactor/clean up. >> - Fix possible assertion failure when handling if statements. >> - Use Symbol methods isSubClass() and isEnclosedBy() instead of homebrew stuff. >> >> Suggested-by: mcimadamore >> - Add comment regarding limitations of expresison type filtering. >> - Add a few more DISABLED_WARNINGS to unbreak build. >> - Clean up handling of switch expressions a bit. >> - Remove unused method variant of analyzeTree(). >> - Avoid all caps in comments. >> - Clarify confusing comment. >> - ... and 6 more: https://git.openjdk.org/jdk/compare/6e96a7d7...edf3c3f5 > > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 685: > >> 683: >> 684: @Override >> 685: public void visitDoLoop(JCDoWhileLoop tree) { > > I was thinking, code can also loop using labels and `break` / `continue`, not something we need to cover as part of this prototype but could be a future TODO that we can document Hah - I didn't think of that. But actually I don't think we would miss anything (see if you agree). The code "executes" every loop, in a sort-of simulation, adding references until the set of references converges. Moreover, that reference set is "append only" while this is happening. Therefore, during actual execution, a break or continue may cause less code to be executed than in our simulation, but never more code than our simulation. So during actual execution it might be that fewer actual 'this' references are created, but never more. Therefore, this effect might cause false positives (which of course we already have with loops and code in general because we take all possible branches), but never false negatives. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Fri Jan 13 19:09:54 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Fri, 13 Jan 2023 19:09:54 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v9] In-Reply-To: References: Message-ID: > This PR adds a new lint warning category `this-escape`. > > It also adds `@SuppressWarnings` annotations as needed to the JDK itself to allow the JDK to continue to compile with `-Xlint:all`. > > A 'this' escape warning is generated for a constructor `A()` in a class `A` when the compiler detects that the following situation is _in theory possible:_ > * Some subclass `B extends A` exists, and `B` is defined in a separate source file (i.e., compilation unit) > * Some constructor `B()` of `B` invokes `A()` as its superclass constructor > * During the execution of `A()`, some non-static method of `B.foo()` could get invoked, perhaps indirectly > > In the above scenario, `B.foo()` would execute before `A()` has returned and before `B()` has performed any initialization. To the extent `B.foo()` accesses any fields of `B` - all of which are still uninitialized - it is likely to function incorrectly. > > Note, when determining if a 'this' escape is possible, the compiler makes no assumptions about code outside of the current compilation unit. It doesn't look outside of the current source file to see what might actually happen when a method is invoked. It does follow method and constructors within the current compilation unit, and applies a simplified union-of-all-possible-branches data flow analysis to see where 'this' could end up. > > From my review, virtually all of the warnings generated in the various JDK modules are valid warnings in the sense that a 'this' escape, as defined above, is really and truly possible. However, that doesn't imply that any bugs were found within the JDK - only that the possibility of a certain type of bug exists if certain superclass constructors are used by someone, somewhere, someday. > > For several "popular" classes, this PR also adds `@implNote`'s to the offending constructors so that subclass implementors are made aware of the threat. For one example, `TreeMap(Map)` invokes `putAll()` and `put()`. > > More details and a couple of motivating examples are given in an included [doc file](https://github.com/archiecobbs/jdk/blob/ThisEscape/src/java.base/share/classes/java/lang/doc-files/ThisEscape.html) that these `@implNote`'s link to. See also the recent thread on `amber-dev` for some background. > > Ideally, over time the owners of the various modules would review their `@SuppressWarnings("this-escape")` annotations and determine which other constructors also warranted such an `@implNote`. > > Because of all the`@SuppressWarnings` annotations, this PR touches a bunch of different JDK modules. My apologies for that. Adding these annotations was determined to be the more conservative approach, as compared to just excepting `this-escape` from various module builds globally. > > **Patch Navigation Guide** > > * Non-trivial compiler changes: > * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties` > > * Javadoc additions of `@implNote`: > > * `src/java.base/share/classes/java/io/PipedReader.java` > * `src/java.base/share/classes/java/io/PipedWriter.java` > * `src/java.base/share/classes/java/lang/Throwable.java` > * `src/java.base/share/classes/java/util/ArrayDeque.java` > * `src/java.base/share/classes/java/util/EnumMap.java` > * `src/java.base/share/classes/java/util/HashSet.java` > * `src/java.base/share/classes/java/util/Hashtable.java` > * `src/java.base/share/classes/java/util/LinkedList.java` > * `src/java.base/share/classes/java/util/TreeMap.java` > * `src/java.base/share/classes/java/util/TreeSet.java` > > * New unit tests > * `test/langtools/tools/javac/warnings/ThisEscape/*.java` > > * **Everything else** is just adding `@SuppressWarnings("this-escape")` Archie L. Cobbs has updated the pull request incrementally with three additional commits since the last revision: - Use more idiomatic test for java.lang.Object. - Revert 27cb30129; the error was actually fixed in edf3c3f51. - Fix formatting issue with the "this-escape" --help-lint description. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/11874/files - new: https://git.openjdk.org/jdk/pull/11874/files/edf3c3f5..ae37ff7c Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=11874&range=08 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=11874&range=07-08 Stats: 12 lines in 3 files changed: 3 ins; 4 del; 5 mod Patch: https://git.openjdk.org/jdk/pull/11874.diff Fetch: git fetch https://git.openjdk.org/jdk pull/11874/head:pull/11874 PR: https://git.openjdk.org/jdk/pull/11874 From vromero at openjdk.org Fri Jan 13 19:20:29 2023 From: vromero at openjdk.org (Vicente Romero) Date: Fri, 13 Jan 2023 19:20:29 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v8] In-Reply-To: References: Message-ID: <9xqxePs8UvBJIyPMojy6Bjbl7h3VguJcIwjFhbPr_78=.5ed61dac-21e7-4214-8faf-85f5612f5b46@github.com> On Fri, 13 Jan 2023 17:49:05 GMT, Archie L. Cobbs wrote: >> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 685: >> >>> 683: >>> 684: @Override >>> 685: public void visitDoLoop(JCDoWhileLoop tree) { >> >> I was thinking, code can also loop using labels and `break` / `continue`, not something we need to cover as part of this prototype but could be a future TODO that we can document > > Hah - I didn't think of that. But actually I don't think we would miss anything (see if you agree). > > The code "executes" every loop, in a sort-of simulation, adding references until the set of references converges. Moreover, that reference set is "append only" while this is happening. > > Therefore, during actual execution, a break or continue may cause less code to be executed than in our simulation, but never more code than our simulation. So during actual execution it might be that fewer actual 'this' references are created, but never more. > > Therefore, this effect might cause false positives (which of course we already have with loops and code in general because we take all possible branches), but never false negatives. yep I agree ------------- PR: https://git.openjdk.org/jdk/pull/11874 From vromero at openjdk.org Fri Jan 13 20:19:53 2023 From: vromero at openjdk.org (Vicente Romero) Date: Fri, 13 Jan 2023 20:19:53 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v9] In-Reply-To: References: Message-ID: On Fri, 13 Jan 2023 19:09:54 GMT, Archie L. Cobbs wrote: >> This PR adds a new lint warning category `this-escape`. >> >> It also adds `@SuppressWarnings` annotations as needed to the JDK itself to allow the JDK to continue to compile with `-Xlint:all`. >> >> A 'this' escape warning is generated for a constructor `A()` in a class `A` when the compiler detects that the following situation is _in theory possible:_ >> * Some subclass `B extends A` exists, and `B` is defined in a separate source file (i.e., compilation unit) >> * Some constructor `B()` of `B` invokes `A()` as its superclass constructor >> * During the execution of `A()`, some non-static method of `B.foo()` could get invoked, perhaps indirectly >> >> In the above scenario, `B.foo()` would execute before `A()` has returned and before `B()` has performed any initialization. To the extent `B.foo()` accesses any fields of `B` - all of which are still uninitialized - it is likely to function incorrectly. >> >> Note, when determining if a 'this' escape is possible, the compiler makes no assumptions about code outside of the current compilation unit. It doesn't look outside of the current source file to see what might actually happen when a method is invoked. It does follow method and constructors within the current compilation unit, and applies a simplified union-of-all-possible-branches data flow analysis to see where 'this' could end up. >> >> From my review, virtually all of the warnings generated in the various JDK modules are valid warnings in the sense that a 'this' escape, as defined above, is really and truly possible. However, that doesn't imply that any bugs were found within the JDK - only that the possibility of a certain type of bug exists if certain superclass constructors are used by someone, somewhere, someday. >> >> For several "popular" classes, this PR also adds `@implNote`'s to the offending constructors so that subclass implementors are made aware of the threat. For one example, `TreeMap(Map)` invokes `putAll()` and `put()`. >> >> More details and a couple of motivating examples are given in an included [doc file](https://github.com/archiecobbs/jdk/blob/ThisEscape/src/java.base/share/classes/java/lang/doc-files/ThisEscape.html) that these `@implNote`'s link to. See also the recent thread on `amber-dev` for some background. >> >> Ideally, over time the owners of the various modules would review their `@SuppressWarnings("this-escape")` annotations and determine which other constructors also warranted such an `@implNote`. >> >> Because of all the`@SuppressWarnings` annotations, this PR touches a bunch of different JDK modules. My apologies for that. Adding these annotations was determined to be the more conservative approach, as compared to just excepting `this-escape` from various module builds globally. >> >> **Patch Navigation Guide** >> >> * Non-trivial compiler changes: >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties` >> >> * Javadoc additions of `@implNote`: >> >> * `src/java.base/share/classes/java/io/PipedReader.java` >> * `src/java.base/share/classes/java/io/PipedWriter.java` >> * `src/java.base/share/classes/java/lang/Throwable.java` >> * `src/java.base/share/classes/java/util/ArrayDeque.java` >> * `src/java.base/share/classes/java/util/EnumMap.java` >> * `src/java.base/share/classes/java/util/HashSet.java` >> * `src/java.base/share/classes/java/util/Hashtable.java` >> * `src/java.base/share/classes/java/util/LinkedList.java` >> * `src/java.base/share/classes/java/util/TreeMap.java` >> * `src/java.base/share/classes/java/util/TreeSet.java` >> >> * New unit tests >> * `test/langtools/tools/javac/warnings/ThisEscape/*.java` >> >> * **Everything else** is just adding `@SuppressWarnings("this-escape")` > > Archie L. Cobbs has updated the pull request incrementally with three additional commits since the last revision: > > - Use more idiomatic test for java.lang.Object. > - Revert 27cb30129; the error was actually fixed in edf3c3f51. > - Fix formatting issue with the "this-escape" --help-lint description. test/langtools/tools/javac/warnings/ThisEscape/ThisEscapeBasic.java line 8: > 6: */ > 7: > 8: public class ThisEscapeBasic { I wonder if it could be better to just fold most of these tests in particular the small ones and create just one, or a few tests, with several subclasses, that will reduce the overhead if in the future we change the code and we need to change the golden files. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From vromero at openjdk.org Fri Jan 13 20:24:46 2023 From: vromero at openjdk.org (Vicente Romero) Date: Fri, 13 Jan 2023 20:24:46 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v9] In-Reply-To: References: Message-ID: On Fri, 13 Jan 2023 19:09:54 GMT, Archie L. Cobbs wrote: >> This PR adds a new lint warning category `this-escape`. >> >> It also adds `@SuppressWarnings` annotations as needed to the JDK itself to allow the JDK to continue to compile with `-Xlint:all`. >> >> A 'this' escape warning is generated for a constructor `A()` in a class `A` when the compiler detects that the following situation is _in theory possible:_ >> * Some subclass `B extends A` exists, and `B` is defined in a separate source file (i.e., compilation unit) >> * Some constructor `B()` of `B` invokes `A()` as its superclass constructor >> * During the execution of `A()`, some non-static method of `B.foo()` could get invoked, perhaps indirectly >> >> In the above scenario, `B.foo()` would execute before `A()` has returned and before `B()` has performed any initialization. To the extent `B.foo()` accesses any fields of `B` - all of which are still uninitialized - it is likely to function incorrectly. >> >> Note, when determining if a 'this' escape is possible, the compiler makes no assumptions about code outside of the current compilation unit. It doesn't look outside of the current source file to see what might actually happen when a method is invoked. It does follow method and constructors within the current compilation unit, and applies a simplified union-of-all-possible-branches data flow analysis to see where 'this' could end up. >> >> From my review, virtually all of the warnings generated in the various JDK modules are valid warnings in the sense that a 'this' escape, as defined above, is really and truly possible. However, that doesn't imply that any bugs were found within the JDK - only that the possibility of a certain type of bug exists if certain superclass constructors are used by someone, somewhere, someday. >> >> For several "popular" classes, this PR also adds `@implNote`'s to the offending constructors so that subclass implementors are made aware of the threat. For one example, `TreeMap(Map)` invokes `putAll()` and `put()`. >> >> More details and a couple of motivating examples are given in an included [doc file](https://github.com/archiecobbs/jdk/blob/ThisEscape/src/java.base/share/classes/java/lang/doc-files/ThisEscape.html) that these `@implNote`'s link to. See also the recent thread on `amber-dev` for some background. >> >> Ideally, over time the owners of the various modules would review their `@SuppressWarnings("this-escape")` annotations and determine which other constructors also warranted such an `@implNote`. >> >> Because of all the`@SuppressWarnings` annotations, this PR touches a bunch of different JDK modules. My apologies for that. Adding these annotations was determined to be the more conservative approach, as compared to just excepting `this-escape` from various module builds globally. >> >> **Patch Navigation Guide** >> >> * Non-trivial compiler changes: >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties` >> >> * Javadoc additions of `@implNote`: >> >> * `src/java.base/share/classes/java/io/PipedReader.java` >> * `src/java.base/share/classes/java/io/PipedWriter.java` >> * `src/java.base/share/classes/java/lang/Throwable.java` >> * `src/java.base/share/classes/java/util/ArrayDeque.java` >> * `src/java.base/share/classes/java/util/EnumMap.java` >> * `src/java.base/share/classes/java/util/HashSet.java` >> * `src/java.base/share/classes/java/util/Hashtable.java` >> * `src/java.base/share/classes/java/util/LinkedList.java` >> * `src/java.base/share/classes/java/util/TreeMap.java` >> * `src/java.base/share/classes/java/util/TreeSet.java` >> >> * New unit tests >> * `test/langtools/tools/javac/warnings/ThisEscape/*.java` >> >> * **Everything else** is just adding `@SuppressWarnings("this-escape")` > > Archie L. Cobbs has updated the pull request incrementally with three additional commits since the last revision: > > - Use more idiomatic test for java.lang.Object. > - Revert 27cb30129; the error was actually fixed in edf3c3f51. > - Fix formatting issue with the "this-escape" --help-lint description. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 1088: > 1086: private void visitLooped(T tree, Consumer visitor) { > 1087: visitScoped(tree, false, t -> { > 1088: while (true) { I have also been thinking if the loop analysis could go wild and execute a large, unbound number of times. But it seems from Archie's experiments that this probably won't occur in "normal" code and worst case scenario if that were to occur we can always limit the number of times we will process loops to a set number of times ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Fri Jan 13 21:23:24 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Fri, 13 Jan 2023 21:23:24 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v9] In-Reply-To: References: Message-ID: On Fri, 13 Jan 2023 20:16:25 GMT, Vicente Romero wrote: >> Archie L. Cobbs has updated the pull request incrementally with three additional commits since the last revision: >> >> - Use more idiomatic test for java.lang.Object. >> - Revert 27cb30129; the error was actually fixed in edf3c3f51. >> - Fix formatting issue with the "this-escape" --help-lint description. > > test/langtools/tools/javac/warnings/ThisEscape/ThisEscapeBasic.java line 8: > >> 6: */ >> 7: >> 8: public class ThisEscapeBasic { > > I wonder if it could be better to just fold most of these tests in particular the small ones and create just one, or a few tests, with several subclasses, that will reduce the overhead if in the future we change the code and we need to change the golden files. I really don't have any informed opinion on this. I can see arguments both ways... putting all you eggs in one basket can be seen alternately as foolhardy or highly efficient :) FWIW in the past I've had problems with trying to combine multiples tests that generate errors into one file. The compiler seems to like to bail out early when it sees errors. I guess that experience was working subconsciously. Of course that doesn't apply here as these are all warnings. And a bunch of separate files make the test run slower. So I agree with you - I'll consolidate them. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Fri Jan 13 21:31:25 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Fri, 13 Jan 2023 21:31:25 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v9] In-Reply-To: References: Message-ID: On Fri, 13 Jan 2023 20:21:24 GMT, Vicente Romero wrote: >> Archie L. Cobbs has updated the pull request incrementally with three additional commits since the last revision: >> >> - Use more idiomatic test for java.lang.Object. >> - Revert 27cb30129; the error was actually fixed in edf3c3f51. >> - Fix formatting issue with the "this-escape" --help-lint description. > > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 1088: > >> 1086: private void visitLooped(T tree, Consumer visitor) { >> 1087: visitScoped(tree, false, t -> { >> 1088: while (true) { > > I have also been thinking if the loop analysis could go wild and execute a large, unbound number of times. But it seems from Archie's experiments that this probably won't occur in "normal" code and worst case scenario if that were to occur we can always limit the number of times we will process loops to a set number of times The number of times around any single loop is bounded by the number of new references that can possibly be created during the analysis of that loop. That number is at most 2 * (1 + 1 + 1 + 1 + N) where N is the number of parameters and/or variables declared in that scope (the 2 is for direct or indirect, and the 1's are for each of the singleton reference types `ThisRef`, `OuterRef`, `ExprRef`, and `ReturnRef`). If you have nested scopes A, B, C each with Na, Nb, and Nc variables declared therein (respectively), then the bound would be something like 2 * (1 + 1 + 1 + 1 + Na + (Na * Nb) + (Na * Nb * Nc)) worst case (waving hands here). ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Fri Jan 13 21:36:30 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Fri, 13 Jan 2023 21:36:30 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v8] In-Reply-To: References: <77lMG_P3_ZGjTegQictMdNN1IKjWixuzLWy5-GbHYnI=.bdbfc529-2ac8-4bba-b3a6-d08f0977e372@github.com> Message-ID: On Fri, 13 Jan 2023 16:20:41 GMT, Archie L. Cobbs wrote: >> I'm OK either way we can revisit this later either as part of this PR or in a future one. I let it to your consideration > > Sounds good - thanks. Ah. I just realized that we need to do it your way because of the following bug: Suppose you have a constructor and a field with initializer that both leak, but you have `@SuppressWarnings("this-escape")` on the constructor. Then the leak for the field will never be reported because we never get to it. I'll fix. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From vromero at openjdk.org Fri Jan 13 22:04:03 2023 From: vromero at openjdk.org (Vicente Romero) Date: Fri, 13 Jan 2023 22:04:03 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v8] In-Reply-To: References: <77lMG_P3_ZGjTegQictMdNN1IKjWixuzLWy5-GbHYnI=.bdbfc529-2ac8-4bba-b3a6-d08f0977e372@github.com> Message-ID: <1ylDnjbWJwdsJP-dVL1zthfhVHZbcOgnC3gxgNuKBZk=.6367e3b4-18ae-4232-b43a-c469e58f9a2d@github.com> On Fri, 13 Jan 2023 21:33:02 GMT, Archie L. Cobbs wrote: >> Sounds good - thanks. > > Ah. I just realized that we need to do it your way because of the following bug: > > Suppose you have a constructor and a field with initializer that both leak, but you have `@SuppressWarnings("this-escape")` on the constructor. > > Then the leak for the field will never be reported because we never get to it. > > I'll fix. yep, right in that case that leak wouldn't be reported ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Fri Jan 13 22:48:59 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Fri, 13 Jan 2023 22:48:59 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v10] In-Reply-To: References: Message-ID: > This PR adds a new lint warning category `this-escape`. > > It also adds `@SuppressWarnings` annotations as needed to the JDK itself to allow the JDK to continue to compile with `-Xlint:all`. > > A 'this' escape warning is generated for a constructor `A()` in a class `A` when the compiler detects that the following situation is _in theory possible:_ > * Some subclass `B extends A` exists, and `B` is defined in a separate source file (i.e., compilation unit) > * Some constructor `B()` of `B` invokes `A()` as its superclass constructor > * During the execution of `A()`, some non-static method of `B.foo()` could get invoked, perhaps indirectly > > In the above scenario, `B.foo()` would execute before `A()` has returned and before `B()` has performed any initialization. To the extent `B.foo()` accesses any fields of `B` - all of which are still uninitialized - it is likely to function incorrectly. > > Note, when determining if a 'this' escape is possible, the compiler makes no assumptions about code outside of the current compilation unit. It doesn't look outside of the current source file to see what might actually happen when a method is invoked. It does follow method and constructors within the current compilation unit, and applies a simplified union-of-all-possible-branches data flow analysis to see where 'this' could end up. > > From my review, virtually all of the warnings generated in the various JDK modules are valid warnings in the sense that a 'this' escape, as defined above, is really and truly possible. However, that doesn't imply that any bugs were found within the JDK - only that the possibility of a certain type of bug exists if certain superclass constructors are used by someone, somewhere, someday. > > For several "popular" classes, this PR also adds `@implNote`'s to the offending constructors so that subclass implementors are made aware of the threat. For one example, `TreeMap(Map)` invokes `putAll()` and `put()`. > > More details and a couple of motivating examples are given in an included [doc file](https://github.com/archiecobbs/jdk/blob/ThisEscape/src/java.base/share/classes/java/lang/doc-files/ThisEscape.html) that these `@implNote`'s link to. See also the recent thread on `amber-dev` for some background. > > Ideally, over time the owners of the various modules would review their `@SuppressWarnings("this-escape")` annotations and determine which other constructors also warranted such an `@implNote`. > > Because of all the`@SuppressWarnings` annotations, this PR touches a bunch of different JDK modules. My apologies for that. Adding these annotations was determined to be the more conservative approach, as compared to just excepting `this-escape` from various module builds globally. > > **Patch Navigation Guide** > > * Non-trivial compiler changes: > * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties` > > * Javadoc additions of `@implNote`: > > * `src/java.base/share/classes/java/io/PipedReader.java` > * `src/java.base/share/classes/java/io/PipedWriter.java` > * `src/java.base/share/classes/java/lang/Throwable.java` > * `src/java.base/share/classes/java/util/ArrayDeque.java` > * `src/java.base/share/classes/java/util/EnumMap.java` > * `src/java.base/share/classes/java/util/HashSet.java` > * `src/java.base/share/classes/java/util/Hashtable.java` > * `src/java.base/share/classes/java/util/LinkedList.java` > * `src/java.base/share/classes/java/util/TreeMap.java` > * `src/java.base/share/classes/java/util/TreeSet.java` > > * New unit tests > * `test/langtools/tools/javac/warnings/ThisEscape/*.java` > > * **Everything else** is just adding `@SuppressWarnings("this-escape")` Archie L. Cobbs has updated the pull request incrementally with two additional commits since the last revision: - Fix bug where field initializer warnings could be incorrectly suppressed. - Consolidate all the unit tests that generate warnings into one. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/11874/files - new: https://git.openjdk.org/jdk/pull/11874/files/ae37ff7c..0b06dc32 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=11874&range=09 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=11874&range=08-09 Stats: 1454 lines in 35 files changed: 658 ins; 762 del; 34 mod Patch: https://git.openjdk.org/jdk/pull/11874.diff Fetch: git fetch https://git.openjdk.org/jdk pull/11874/head:pull/11874 PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Sat Jan 14 01:57:32 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Sat, 14 Jan 2023 01:57:32 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v7] In-Reply-To: References: <7lxiY8WIdkIkI5fqLn52qkq2fvSc04huqWL_fV2WSy8=.7bd29e16-bcee-473e-937e-aea32b211db3@github.com> Message-ID: On Fri, 13 Jan 2023 00:57:14 GMT, Archie L. Cobbs wrote: >> Ok - I thought false negative was the thing to absolutely avoid - and that was the no. 1 concern. I think a possible approach to keep both the filtering and the code more or less similar to what you have, is to save the type of the expression in the ExprRef. Then, I believe that, at the end of scan() you can just get whatever type is there, and check that it's the correct one, if not drop it. > >> Ok - I thought false negative was the thing to absolutely avoid - and that was the no. 1 concern. > > You're right. I think at the time I reasoned that it would be unusual enough for the type of an expression to start as an instanceof X, then change to not being an instanceof X, and then change back, that it was worth it to go ahead and filter these out. But admittedly that was based on intuition, not science. > >> I think a possible approach to keep both the filtering and the code more or less similar to what you have, is to save the type of the expression in the ExprRef. Then, I believe that, at the end of scan() you can just get whatever type is there, and check that it's the correct one, if not drop it. > > That's a nice idea... thanks. I'll play around with it some. I was curious how much of a difference this type filtering makes, so I built the JDK with and without it. The results were identical except for one case: package java.lang.invoke; ... public abstract sealed class CallSite permits ConstantCallSite, MutableCallSite, VolatileCallSite { ... CallSite(MethodType targetType, MethodHandle createTargetHook) throws Throwable { this(targetType); // need to initialize target to make CallSite.type() work in createTargetHook ConstantCallSite selfCCS = (ConstantCallSite) this; MethodHandle boundTarget = (MethodHandle) createTargetHook.invokeWithArguments(selfCCS); setTargetNormal(boundTarget); // ConstantCallSite doesn't publish CallSite.target UNSAFE.storeStoreFence(); // barrier between target and isFrozen updates } When we do type filtering, `(ConstantCallSite) this` causes the 'this' reference to be discarded so no leak is reported on the next line for `invokeWithArguments(selfCCS)`. Just a side note, there is also a leak on the next line because final method `setTargetNormal()` invokes `MethodHandleNatives.setCallSiteTargetNormal(this, newTarget)`, so a leak does get reported anyway even with type filtering. When type filtering is disabled, we report a leak at `invokeWithArguments(selfCCS)` - which is accurate. So what did we learn? First it looks like type filtering has very minimal effect. I think this is because it requires some version of two casts in a row in and out of type compatibility, and this is probably very rare. But looking at the one data point we do have, the type filtering did in fact cause a false negative. And when building the entire JDK, it causes zero net new false positives. So to me this is evidence that we should just remove the type filtering altogether... @vicente-romero-oracle your thoughts? ------------- PR: https://git.openjdk.org/jdk/pull/11874 From mcimadamore at openjdk.org Mon Jan 16 11:56:24 2023 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 16 Jan 2023 11:56:24 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v10] In-Reply-To: References: Message-ID: On Fri, 13 Jan 2023 22:48:59 GMT, Archie L. Cobbs wrote: >> This PR adds a new lint warning category `this-escape`. >> >> It also adds `@SuppressWarnings` annotations as needed to the JDK itself to allow the JDK to continue to compile with `-Xlint:all`. >> >> A 'this' escape warning is generated for a constructor `A()` in a class `A` when the compiler detects that the following situation is _in theory possible:_ >> * Some subclass `B extends A` exists, and `B` is defined in a separate source file (i.e., compilation unit) >> * Some constructor `B()` of `B` invokes `A()` as its superclass constructor >> * During the execution of `A()`, some non-static method of `B.foo()` could get invoked, perhaps indirectly >> >> In the above scenario, `B.foo()` would execute before `A()` has returned and before `B()` has performed any initialization. To the extent `B.foo()` accesses any fields of `B` - all of which are still uninitialized - it is likely to function incorrectly. >> >> Note, when determining if a 'this' escape is possible, the compiler makes no assumptions about code outside of the current compilation unit. It doesn't look outside of the current source file to see what might actually happen when a method is invoked. It does follow method and constructors within the current compilation unit, and applies a simplified union-of-all-possible-branches data flow analysis to see where 'this' could end up. >> >> From my review, virtually all of the warnings generated in the various JDK modules are valid warnings in the sense that a 'this' escape, as defined above, is really and truly possible. However, that doesn't imply that any bugs were found within the JDK - only that the possibility of a certain type of bug exists if certain superclass constructors are used by someone, somewhere, someday. >> >> For several "popular" classes, this PR also adds `@implNote`'s to the offending constructors so that subclass implementors are made aware of the threat. For one example, `TreeMap(Map)` invokes `putAll()` and `put()`. >> >> More details and a couple of motivating examples are given in an included [doc file](https://github.com/archiecobbs/jdk/blob/ThisEscape/src/java.base/share/classes/java/lang/doc-files/ThisEscape.html) that these `@implNote`'s link to. See also the recent thread on `amber-dev` for some background. >> >> Ideally, over time the owners of the various modules would review their `@SuppressWarnings("this-escape")` annotations and determine which other constructors also warranted such an `@implNote`. >> >> Because of all the`@SuppressWarnings` annotations, this PR touches a bunch of different JDK modules. My apologies for that. Adding these annotations was determined to be the more conservative approach, as compared to just excepting `this-escape` from various module builds globally. >> >> **Patch Navigation Guide** >> >> * Non-trivial compiler changes: >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties` >> * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties` >> >> * Javadoc additions of `@implNote`: >> >> * `src/java.base/share/classes/java/io/PipedReader.java` >> * `src/java.base/share/classes/java/io/PipedWriter.java` >> * `src/java.base/share/classes/java/lang/Throwable.java` >> * `src/java.base/share/classes/java/util/ArrayDeque.java` >> * `src/java.base/share/classes/java/util/EnumMap.java` >> * `src/java.base/share/classes/java/util/HashSet.java` >> * `src/java.base/share/classes/java/util/Hashtable.java` >> * `src/java.base/share/classes/java/util/LinkedList.java` >> * `src/java.base/share/classes/java/util/TreeMap.java` >> * `src/java.base/share/classes/java/util/TreeSet.java` >> >> * New unit tests >> * `test/langtools/tools/javac/warnings/ThisEscape/*.java` >> >> * **Everything else** is just adding `@SuppressWarnings("this-escape")` > > Archie L. Cobbs has updated the pull request incrementally with two additional commits since the last revision: > > - Fix bug where field initializer warnings could be incorrectly suppressed. > - Consolidate all the unit tests that generate warnings into one. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 1096: > 1094: > 1095: // Perform the given action within a new scope > 1096: private void visitScoped(boolean promote, Runnable action) { type-variable unused here? ------------- PR: https://git.openjdk.org/jdk/pull/11874 From mcimadamore at openjdk.org Mon Jan 16 12:54:22 2023 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 16 Jan 2023 12:54:22 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v9] In-Reply-To: References: Message-ID: On Fri, 13 Jan 2023 21:28:51 GMT, Archie L. Cobbs wrote: >> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 1088: >> >>> 1086: private void visitLooped(T tree, Consumer visitor) { >>> 1087: visitScoped(tree, false, t -> { >>> 1088: while (true) { >> >> I have also been thinking if the loop analysis could go wild and execute a large, unbound number of times. But it seems from Archie's experiments that this probably won't occur in "normal" code and worst case scenario if that were to occur we can always limit the number of times we will process loops to a set number of times > > The number of times around any single loop is bounded by the number of new references that can possibly be created during the analysis of that loop. > > That number is at most 2 * (1 + 1 + 1 + 1 + N) where N is the number of parameters and/or variables declared in that scope (the 2 is for direct or indirect, and the 1's are for each of the singleton reference types `ThisRef`, `OuterRef`, `ExprRef`, and `ReturnRef`). > > If you have nested scopes A, B, C each with Na, Nb, and Nc variables declared therein (respectively), then the bound would be something like 2 * (1 + 1 + 1 + 1 + Na + (Na * Nb) + (Na * Nb * Nc)) worst case (waving hands here). I have played a bit with the patch, trying to disable certain features. The main reason to deal with loops and recursive calls the way the patch does is to eliminate false positives. If we see a loop, and we can't perform the analysis multiple times (as the PR does), then we'd have to conclude that the loop can be potentially escaping (as we might have missed an local var update). Same goes for recursive calls (e.g. a recursive call would be treated as escaping). Same goes for analyzing invoked methods that fall in the same compilation unit. If we don't do that, more methods might look as "escaping". So, here's what I found: * compiling the JDK with the current patch produces 2376 warnings * disabling support for recursive calls produces 2427 warnings * treating all method calls inside a loop to be escaping produces 2464 warnings * disabling scanning of methods in same compilation unit produces 4317 warnings (Note: the patches I used to do this analysis are a bit blunt, and perhaps can be made a bit less conservative, which might result in less false positives added - I just went for the simplest possible approach, just to test the contribute of each analysis). This seems to suggest that even a blunt approach to deal with recursion and loop does not result in a significant increase of false positives (~2% more). That said, disabling scanning of methods in the same compilation unit results in a big impact in terms of false positive (~100% increase). So, I'm pretty confident that, should performance problems arise, we could probably dial back the analysis not to do loops (or to do them in a bounded way, as Vicente suggest, which is much better of what I tried here) - and that will probably give us the same results we have today (or a very very minor increase of false positives). But scanning of dependent methods in same compilation unit seems to be more or less a must-have. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Mon Jan 16 15:49:28 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Mon, 16 Jan 2023 15:49:28 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v10] In-Reply-To: References: Message-ID: On Mon, 16 Jan 2023 11:53:40 GMT, Maurizio Cimadamore wrote: >> Archie L. Cobbs has updated the pull request incrementally with two additional commits since the last revision: >> >> - Fix bug where field initializer warnings could be incorrectly suppressed. >> - Consolidate all the unit tests that generate warnings into one. > > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 1096: > >> 1094: >> 1095: // Perform the given action within a new scope >> 1096: private void visitScoped(boolean promote, Runnable action) { > > type-variable unused here? Thanks - will fix. ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Mon Jan 16 16:32:25 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Mon, 16 Jan 2023 16:32:25 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v9] In-Reply-To: References: Message-ID: <-vggQR3X6BuroIsmEmI6yohrVGF3MyE-ap7tokjc-7M=.077053ee-fcf9-43db-be53-a9c89ab38a15@github.com> On Mon, 16 Jan 2023 12:51:49 GMT, Maurizio Cimadamore wrote: >> The number of times around any single loop is bounded by the number of new references that can possibly be created during the analysis of that loop. >> >> That number is at most 2 * (1 + 1 + 1 + 1 + N) where N is the number of parameters and/or variables declared in that scope (the 2 is for direct or indirect, and the 1's are for each of the singleton reference types `ThisRef`, `OuterRef`, `ExprRef`, and `ReturnRef`). >> >> If you have nested scopes A, B, C each with Na, Nb, and Nc variables declared therein (respectively), then the bound would be something like 2 * (1 + 1 + 1 + 1 + Na + (Na * Nb) + (Na * Nb * Nc)) worst case (waving hands here). > > I have played a bit with the patch, trying to disable certain features. The main reason to deal with loops and recursive calls the way the patch does is to eliminate false positives. If we see a loop, and we can't perform the analysis multiple times (as the PR does), then we'd have to conclude that the loop can be potentially escaping (as we might have missed an local var update). Same goes for recursive calls (e.g. a recursive call would be treated as escaping). Same goes for analyzing invoked methods that fall in the same compilation unit. If we don't do that, more methods might look as "escaping". > > So, here's what I found: > > * compiling the JDK with the current patch produces 2376 warnings > * disabling support for recursive calls produces 2427 warnings > * treating all method calls inside a loop to be escaping produces 2464 warnings > * disabling scanning of methods in same compilation unit produces 4317 warnings > > (Note: the patches I used to do this analysis are a bit blunt, and perhaps can be made a bit less conservative, which might result in less false positives added - I just went for the simplest possible approach, just to test the contribute of each analysis). > > This seems to suggest that even a blunt approach to deal with recursion and loop does not result in a significant increase of false positives (~2% more). That said, disabling scanning of methods in the same compilation unit results in a big impact in terms of false positive (~100% increase). > > So, I'm pretty confident that, should performance problems arise, we could probably dial back the analysis not to do loops (or to do them in a bounded way, as Vicente suggest, which is much better of what I tried here) - and that will probably give us the same results we have today (or a very very minor increase of false positives). But scanning of dependent methods in same compilation unit seems to be more or less a must-have. Thanks for doing that analysis - very interesting. It looks like you might be counting the "here via invocation" lines as separate warnings. These are really part of the previous `possible 'this' escape` line, e.g.: .../java/awt/Frame.java:429: Note: possible 'this' escape before subclass is fully initialized init(title, null); ^ .../java/awt/Frame.java:460: Note: previous possible 'this' escape happens here via invocation SunToolkit.checkAndSetPolicy(this); ^ Semi-related... I was also curious what would happen if we changed the semantics of the warning from "subclass must be in a separate compilation unit" to "subclass must be in a separate package". I'm not proposing we change this definition, and obviously there are trade-offs in where you draw this boundary, but was curious anywan (at one point I thought it might be worth having an option for this, e.g., with variants like `-Xlint:this-escape` vs. `-Xlint:this-escape:package`, or even `-Xlint:this-escape:module`, etc.). In any case, here are the results: * Warnings for subclass in separate compilation unit: 2093 * Warnings for subclass in separate package: 1334 So a 36% reduction - not too surprising since the JDK includes a bunch of non-public implementation classes. FWIW this is the patch I used: diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java index e81df22b017..f309a4742aa 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java @@ -216,24 +217,24 @@ class ThisEscapeAnalyzer extends TreeScanner { private Lint lint = ThisEscapeAnalyzer.this.lint; private JCClassDecl currentClass; - private boolean privateOuter; + private boolean nonPublicOuter; @Override public void visitClassDef(JCClassDecl tree) { JCClassDecl currentClassPrev = currentClass; - boolean privateOuterPrev = privateOuter; + boolean nonPublicOuterPrev = nonPublicOuter; Lint lintPrev = lint; lint = lint.augment(tree.sym); try { currentClass = tree; - privateOuter |= tree.sym.isAnonymous(); - privateOuter |= (tree.mods.flags & Flags.PRIVATE) != 0; + nonPublicOuter |= tree.sym.isAnonymous(); + nonPublicOuter |= (tree.mods.flags & Flags.PUBLIC) == 0; // Recurse super.visitClassDef(tree); } finally { currentClass = currentClassPrev; - privateOuter = privateOuterPrev; + nonPublicOuter = nonPublicOuterPrev; lint = lintPrev; } } @@ -268,10 +269,10 @@ class ThisEscapeAnalyzer extends TreeScanner { // Determine if this is a constructor we should analyze boolean analyzable = currentClassIsExternallyExtendable() && TreeInfo.isConstructor(tree) && - !tree.sym.isPrivate() && + (tree.sym.isPublic() || (tree.sym.flags() & Flags.PROTECTED) != 0) && !suppressed.contains(tree.sym); - // Determine if this method is "invokable" in an analysis (can't be overridden) + // Determine if this method is "invokable" in an analysis (can't be overridden outside package) boolean invokable = !currentClassIsExternallyExtendable() || TreeInfo.isConstructor(tree) || (tree.mods.flags & (Flags.STATIC | Flags.PRIVATE | Flags.FINAL)) != 0; @@ -286,12 +287,13 @@ class ThisEscapeAnalyzer extends TreeScanner { } } - // Determines if the current class could be extended in some external compilation unit + // Determines if the current class could be extended in some other package private boolean currentClassIsExternallyExtendable() { return !currentClass.sym.isFinal() && + currentClass.sym.isPublic() && !(currentClass.sym.isSealed() && currentClass.permitting.isEmpty()) && !(currentClass.sym.owner.kind == MTH) && - !privateOuter; + !nonPublicOuter; } }.scan(env.tree); ------------- PR: https://git.openjdk.org/jdk/pull/11874 From mcimadamore at openjdk.org Mon Jan 16 17:16:26 2023 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 16 Jan 2023 17:16:26 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v9] In-Reply-To: <-vggQR3X6BuroIsmEmI6yohrVGF3MyE-ap7tokjc-7M=.077053ee-fcf9-43db-be53-a9c89ab38a15@github.com> References: <-vggQR3X6BuroIsmEmI6yohrVGF3MyE-ap7tokjc-7M=.077053ee-fcf9-43db-be53-a9c89ab38a15@github.com> Message-ID: On Mon, 16 Jan 2023 16:29:31 GMT, Archie L. Cobbs wrote: > It looks like you might be counting the "here via invocation" lines as separate warnings. These are really part of the previous `possible 'this' escape` line, e.g.: yes, I really did the simplest possible thing (e.g. just counting the number of escape-this warnings, regardless of their kinds). Perhaps some of my measurements might be skewed as a result - but I think that magnitude-wise they are still telling. > > ``` > .../java/awt/Frame.java:429: Note: possible 'this' escape before subclass is fully initialized > init(title, null); > ^ > .../java/awt/Frame.java:460: Note: previous possible 'this' escape happens here via invocation > SunToolkit.checkAndSetPolicy(this); > ^ > ``` > > Semi-related... I was also curious what would happen if we changed the semantics of the warning from "subclass must be in a separate compilation unit" to "subclass must be in a separate package". To be fair, this is what my brain was reading when you talked about "compilation unit" - but then saw that the code was doing it differently. You see, for "sealed" classes we have a notion of "maintenance domain". E.g. the classes in a `permits` clause of a `sealed` declaration must belong to the same module (if available) or same package (if no module is available). That's how you get the exhaustiveness analysis and all the goodies, by essentially making a close-world assumption on the classes that are passed to javac for a given compilation task. I think it would make a lot of sense to apply these very same boundaries to the escape-this analysis (and, in fact, when looking at warnings coming out of the JDK, I often found false positives that were caused by this). > > I'm not proposing we change this definition, and obviously there are trade-offs in where you draw this boundary, but was curious anywan (at one point I thought it might be worth having an option for this, e.g., with variants like `-Xlint:this-escape` vs. `-Xlint:this-escape:package`, or even `-Xlint:this-escape:module`, etc.). Perhaps - but, as said above, `sealed` already does this by default - so there's a (strong) precedent, I believe, should we want to bend the analysis that way. > > In any case, here are the results: > > * Warnings for subclass in separate compilation unit: 2093 > > * Warnings for subclass in separate package: 1334 > > > So a 36% reduction - not too surprising since the JDK includes a bunch of non-public implementation classes. That corresponds to what I've sampled (unscientifically). ------------- PR: https://git.openjdk.org/jdk/pull/11874 From duke at openjdk.org Mon Jan 16 23:22:00 2023 From: duke at openjdk.org (Archie L. Cobbs) Date: Mon, 16 Jan 2023 23:22:00 GMT Subject: RFR: 8015831: Add lint check for calling overridable methods from a constructor [v11] In-Reply-To: References: Message-ID: > This PR adds a new lint warning category `this-escape`. > > It also adds `@SuppressWarnings` annotations as needed to the JDK itself to allow the JDK to continue to compile with `-Xlint:all`. > > A 'this' escape warning is generated for a constructor `A()` in a class `A` when the compiler detects that the following situation is _in theory possible:_ > * Some subclass `B extends A` exists, and `B` is defined in a separate source file (i.e., compilation unit) > * Some constructor `B()` of `B` invokes `A()` as its superclass constructor > * During the execution of `A()`, some non-static method of `B.foo()` could get invoked, perhaps indirectly > > In the above scenario, `B.foo()` would execute before `A()` has returned and before `B()` has performed any initialization. To the extent `B.foo()` accesses any fields of `B` - all of which are still uninitialized - it is likely to function incorrectly. > > Note, when determining if a 'this' escape is possible, the compiler makes no assumptions about code outside of the current compilation unit. It doesn't look outside of the current source file to see what might actually happen when a method is invoked. It does follow method and constructors within the current compilation unit, and applies a simplified union-of-all-possible-branches data flow analysis to see where 'this' could end up. > > From my review, virtually all of the warnings generated in the various JDK modules are valid warnings in the sense that a 'this' escape, as defined above, is really and truly possible. However, that doesn't imply that any bugs were found within the JDK - only that the possibility of a certain type of bug exists if certain superclass constructors are used by someone, somewhere, someday. > > For several "popular" classes, this PR also adds `@implNote`'s to the offending constructors so that subclass implementors are made aware of the threat. For one example, `TreeMap(Map)` invokes `putAll()` and `put()`. > > More details and a couple of motivating examples are given in an included [doc file](https://github.com/archiecobbs/jdk/blob/ThisEscape/src/java.base/share/classes/java/lang/doc-files/ThisEscape.html) that these `@implNote`'s link to. See also the recent thread on `amber-dev` for some background. > > Ideally, over time the owners of the various modules would review their `@SuppressWarnings("this-escape")` annotations and determine which other constructors also warranted such an `@implNote`. > > Because of all the`@SuppressWarnings` annotations, this PR touches a bunch of different JDK modules. My apologies for that. Adding these annotations was determined to be the more conservative approach, as compared to just excepting `this-escape` from various module builds globally. > > **Patch Navigation Guide** > > * Non-trivial compiler changes: > * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties` > * `src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties` > > * Javadoc additions of `@implNote`: > > * `src/java.base/share/classes/java/io/PipedReader.java` > * `src/java.base/share/classes/java/io/PipedWriter.java` > * `src/java.base/share/classes/java/lang/Throwable.java` > * `src/java.base/share/classes/java/util/ArrayDeque.java` > * `src/java.base/share/classes/java/util/EnumMap.java` > * `src/java.base/share/classes/java/util/HashSet.java` > * `src/java.base/share/classes/java/util/Hashtable.java` > * `src/java.base/share/classes/java/util/LinkedList.java` > * `src/java.base/share/classes/java/util/TreeMap.java` > * `src/java.base/share/classes/java/util/TreeSet.java` > > * New unit tests > * `test/langtools/tools/javac/warnings/ThisEscape/*.java` > > * **Everything else** is just adding `@SuppressWarnings("this-escape")` Archie L. Cobbs has updated the pull request incrementally with three additional commits since the last revision: - Remove unused type variable on method visitScoped(). - Remove expression type filtering; it doesn't seem to be needed. - Clean up unused import. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/11874/files - new: https://git.openjdk.org/jdk/pull/11874/files/0b06dc32..a0b4310d Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=11874&range=10 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=11874&range=09-10 Stats: 21 lines in 2 files changed: 0 ins; 20 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/11874.diff Fetch: git fetch https://git.openjdk.org/jdk pull/11874/head:pull/11874 PR: https://git.openjdk.org/jdk/pull/11874 From jlaskey at openjdk.org Tue Jan 17 18:03:39 2023 From: jlaskey at openjdk.org (Jim Laskey) Date: Tue, 17 Jan 2023 18:03:39 GMT Subject: RFR: JDK-8285932 Implementation of JEP 430 String Templates (Preview) [v34] In-Reply-To: References: Message-ID: <4iErqSLrHHY_Wmv5yztRHFs5v2LGQTjez0TJMfZ_sV0=.0a73c032-240e-4957-ac28-51d93091beae@github.com> On Wed, 11 Jan 2023 14:07:53 GMT, Jim Laskey wrote: >> Enhance the Java programming language with string templates, which are similar to string literals but contain embedded expressions. A string template is interpreted at run time by replacing each expression with the result of evaluating that expression, possibly after further validation and transformation. This is a [preview language feature and API](http://openjdk.java.net/jeps/12). > > Jim Laskey has updated the pull request incrementally with one additional commit since the last revision: > > Update to JDK 21 Still active. ------------- PR: https://git.openjdk.org/jdk/pull/10889 From dholmes at openjdk.org Mon Jan 23 03:24:47 2023 From: dholmes at openjdk.org (David Holmes) Date: Mon, 23 Jan 2023 03:24:47 GMT Subject: [jdk20] RFR: 8290919: Update nroff pages in JDK 20 before RC Message-ID: There was one missing update in javac.1 from: [JDK-8245246](https://bugs.openjdk.org/browse/JDK-8245246): Deprecate -profile option in javac otherwise the change is limited to dropping the "-ea". Thanks. ------------- Commit messages: - Merge branch 'master' into 8290919-manpages - 8290919: Update nroff pages in JDK 20 before RC Changes: https://git.openjdk.org/jdk20/pull/112/files Webrev: https://webrevs.openjdk.org/?repo=jdk20&pr=112&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8290919 Stats: 29 lines in 28 files changed: 1 ins; 0 del; 28 mod Patch: https://git.openjdk.org/jdk20/pull/112.diff Fetch: git fetch https://git.openjdk.org/jdk20 pull/112/head:pull/112 PR: https://git.openjdk.org/jdk20/pull/112 From iris at openjdk.org Mon Jan 23 07:18:06 2023 From: iris at openjdk.org (Iris Clark) Date: Mon, 23 Jan 2023 07:18:06 GMT Subject: [jdk20] RFR: 8290919: Update nroff pages in JDK 20 before RC In-Reply-To: References: Message-ID: On Mon, 23 Jan 2023 02:59:42 GMT, David Holmes wrote: > There was one missing update in javac.1 from: > > [JDK-8245246](https://bugs.openjdk.org/browse/JDK-8245246): Deprecate -profile option in javac > > otherwise the change is limited to dropping the "-ea". > > Thanks. Marked as reviewed by iris (Reviewer). ------------- PR: https://git.openjdk.org/jdk20/pull/112 From alanb at openjdk.org Mon Jan 23 07:35:07 2023 From: alanb at openjdk.org (Alan Bateman) Date: Mon, 23 Jan 2023 07:35:07 GMT Subject: [jdk20] RFR: 8290919: Update nroff pages in JDK 20 before RC In-Reply-To: References: Message-ID: On Mon, 23 Jan 2023 02:59:42 GMT, David Holmes wrote: > There was one missing update in javac.1 from: > > [JDK-8245246](https://bugs.openjdk.org/browse/JDK-8245246): Deprecate -profile option in javac > > otherwise the change is limited to dropping the "-ea". > > Thanks. Marked as reviewed by alanb (Reviewer). ------------- PR: https://git.openjdk.org/jdk20/pull/112 From dholmes at openjdk.org Mon Jan 23 07:39:08 2023 From: dholmes at openjdk.org (David Holmes) Date: Mon, 23 Jan 2023 07:39:08 GMT Subject: [jdk20] RFR: 8290919: Update nroff pages in JDK 20 before RC In-Reply-To: References: Message-ID: On Mon, 23 Jan 2023 07:15:08 GMT, Iris Clark wrote: >> There was one missing update in javac.1 from: >> >> [JDK-8245246](https://bugs.openjdk.org/browse/JDK-8245246): Deprecate -profile option in javac >> >> otherwise the change is limited to dropping the "-ea". >> >> Thanks. > > Marked as reviewed by iris (Reviewer). Thanks for the reviews @irisclark and @AlanBateman ! ------------- PR: https://git.openjdk.org/jdk20/pull/112 From dholmes at openjdk.org Mon Jan 23 07:53:05 2023 From: dholmes at openjdk.org (David Holmes) Date: Mon, 23 Jan 2023 07:53:05 GMT Subject: [jdk20] Integrated: 8290919: Update nroff pages in JDK 20 before RC In-Reply-To: References: Message-ID: On Mon, 23 Jan 2023 02:59:42 GMT, David Holmes wrote: > There was one missing update in javac.1 from: > > [JDK-8245246](https://bugs.openjdk.org/browse/JDK-8245246): Deprecate -profile option in javac > > otherwise the change is limited to dropping the "-ea". > > Thanks. This pull request has now been integrated. Changeset: fd752178 Author: David Holmes URL: https://git.openjdk.org/jdk20/commit/fd752178e364fb5deeec062bef3dde1fea1dcbe3 Stats: 29 lines in 28 files changed: 1 ins; 0 del; 28 mod 8290919: Update nroff pages in JDK 20 before RC Reviewed-by: iris, alanb ------------- PR: https://git.openjdk.org/jdk20/pull/112 From jwilhelm at openjdk.org Mon Jan 23 20:27:19 2023 From: jwilhelm at openjdk.org (Jesper Wilhelmsson) Date: Mon, 23 Jan 2023 20:27:19 GMT Subject: RFR: Merge jdk20 Message-ID: Forwardport JDK 20 -> JDK 21 ------------- Commit messages: - Merge - 8290919: Update nroff pages in JDK 20 before RC The webrevs contain the adjustments done while merging with regards to each parent branch: - master: https://webrevs.openjdk.org/?repo=jdk&pr=12150&range=00.0 - jdk20: https://webrevs.openjdk.org/?repo=jdk&pr=12150&range=00.1 Changes: https://git.openjdk.org/jdk/pull/12150/files Stats: 28 lines in 27 files changed: 1 ins; 0 del; 27 mod Patch: https://git.openjdk.org/jdk/pull/12150.diff Fetch: git fetch https://git.openjdk.org/jdk pull/12150/head:pull/12150 PR: https://git.openjdk.org/jdk/pull/12150 From jwilhelm at openjdk.org Mon Jan 23 21:07:12 2023 From: jwilhelm at openjdk.org (Jesper Wilhelmsson) Date: Mon, 23 Jan 2023 21:07:12 GMT Subject: Integrated: Merge jdk20 In-Reply-To: References: Message-ID: On Mon, 23 Jan 2023 19:52:49 GMT, Jesper Wilhelmsson wrote: > Forwardport JDK 20 -> JDK 21 This pull request has now been integrated. Changeset: 56dc3b08 Author: Jesper Wilhelmsson URL: https://git.openjdk.org/jdk/commit/56dc3b08a62f651835c5bccca987d93ba2bb8961 Stats: 28 lines in 27 files changed: 1 ins; 0 del; 27 mod Merge ------------- PR: https://git.openjdk.org/jdk/pull/12150 From dholmes at openjdk.org Mon Jan 23 23:21:44 2023 From: dholmes at openjdk.org (David Holmes) Date: Mon, 23 Jan 2023 23:21:44 GMT Subject: RFR: 8290918: Initial nroff manpage generation for JDK 21 Message-ID: <_l9LWouUV22whyL4PTf1esOed9cZw1jyKKVBozovayE=.f79dbc18-b48e-4e52-8a16-f9e1b732ce50@github.com> Please review this simple update to the manpage to set the version to 21-ea. This change also corrects a typo in javac.1 that was manually introduced by JDK-8300591 Thanks. ------------- Commit messages: - 8290918: Initial nroff manpage generation for JDK 21 Changes: https://git.openjdk.org/jdk/pull/12154/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=12154&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8290918 Stats: 28 lines in 27 files changed: 0 ins; 0 del; 28 mod Patch: https://git.openjdk.org/jdk/pull/12154.diff Fetch: git fetch https://git.openjdk.org/jdk pull/12154/head:pull/12154 PR: https://git.openjdk.org/jdk/pull/12154 From lancea at openjdk.org Mon Jan 23 23:27:05 2023 From: lancea at openjdk.org (Lance Andersen) Date: Mon, 23 Jan 2023 23:27:05 GMT Subject: RFR: 8290918: Initial nroff manpage generation for JDK 21 In-Reply-To: <_l9LWouUV22whyL4PTf1esOed9cZw1jyKKVBozovayE=.f79dbc18-b48e-4e52-8a16-f9e1b732ce50@github.com> References: <_l9LWouUV22whyL4PTf1esOed9cZw1jyKKVBozovayE=.f79dbc18-b48e-4e52-8a16-f9e1b732ce50@github.com> Message-ID: On Mon, 23 Jan 2023 22:59:22 GMT, David Holmes wrote: > Please review this simple update to the manpage to set the version to 21-ea. > > This change also corrects a typo in javac.1 that was manually introduced by JDK-8300591 > > Thanks. Marked as reviewed by lancea (Reviewer). ------------- PR: https://git.openjdk.org/jdk/pull/12154 From dholmes at openjdk.org Tue Jan 24 00:49:08 2023 From: dholmes at openjdk.org (David Holmes) Date: Tue, 24 Jan 2023 00:49:08 GMT Subject: RFR: 8290918: Initial nroff manpage generation for JDK 21 In-Reply-To: References: <_l9LWouUV22whyL4PTf1esOed9cZw1jyKKVBozovayE=.f79dbc18-b48e-4e52-8a16-f9e1b732ce50@github.com> Message-ID: On Mon, 23 Jan 2023 23:24:06 GMT, Lance Andersen wrote: >> Please review this simple update to the manpage to set the version to 21-ea. >> >> This change also corrects a typo in javac.1 that was manually introduced by JDK-8300591 >> >> Thanks. > > Marked as reviewed by lancea (Reviewer). Thanks for the review @LanceAndersen ------------- PR: https://git.openjdk.org/jdk/pull/12154 From iris at openjdk.org Tue Jan 24 01:32:03 2023 From: iris at openjdk.org (Iris Clark) Date: Tue, 24 Jan 2023 01:32:03 GMT Subject: RFR: 8290918: Initial nroff manpage generation for JDK 21 In-Reply-To: <_l9LWouUV22whyL4PTf1esOed9cZw1jyKKVBozovayE=.f79dbc18-b48e-4e52-8a16-f9e1b732ce50@github.com> References: <_l9LWouUV22whyL4PTf1esOed9cZw1jyKKVBozovayE=.f79dbc18-b48e-4e52-8a16-f9e1b732ce50@github.com> Message-ID: On Mon, 23 Jan 2023 22:59:22 GMT, David Holmes wrote: > Please review this simple update to the manpage to set the version to 21-ea. > > This change also corrects a typo in javac.1 that was manually introduced by JDK-8300591 > > Thanks. Marked as reviewed by iris (Reviewer). ------------- PR: https://git.openjdk.org/jdk/pull/12154 From dholmes at openjdk.org Tue Jan 24 05:42:02 2023 From: dholmes at openjdk.org (David Holmes) Date: Tue, 24 Jan 2023 05:42:02 GMT Subject: RFR: 8290918: Initial nroff manpage generation for JDK 21 In-Reply-To: References: <_l9LWouUV22whyL4PTf1esOed9cZw1jyKKVBozovayE=.f79dbc18-b48e-4e52-8a16-f9e1b732ce50@github.com> Message-ID: On Tue, 24 Jan 2023 01:28:53 GMT, Iris Clark wrote: >> Please review this simple update to the manpage to set the version to 21-ea. >> >> This change also corrects a typo in javac.1 that was manually introduced by JDK-8300591 >> >> Thanks. > > Marked as reviewed by iris (Reviewer). Thanks for the review @irisclark ! ------------- PR: https://git.openjdk.org/jdk/pull/12154 From darcy at openjdk.org Tue Jan 24 05:57:04 2023 From: darcy at openjdk.org (Joe Darcy) Date: Tue, 24 Jan 2023 05:57:04 GMT Subject: RFR: 8290918: Initial nroff manpage generation for JDK 21 In-Reply-To: <_l9LWouUV22whyL4PTf1esOed9cZw1jyKKVBozovayE=.f79dbc18-b48e-4e52-8a16-f9e1b732ce50@github.com> References: <_l9LWouUV22whyL4PTf1esOed9cZw1jyKKVBozovayE=.f79dbc18-b48e-4e52-8a16-f9e1b732ce50@github.com> Message-ID: On Mon, 23 Jan 2023 22:59:22 GMT, David Holmes wrote: > Please review this simple update to the manpage to set the version to 21-ea. > > This change also corrects a typo in javac.1 that was manually introduced by JDK-8300591 > > Thanks. Marked as reviewed by darcy (Reviewer). ------------- PR: https://git.openjdk.org/jdk/pull/12154 From dholmes at openjdk.org Tue Jan 24 06:31:11 2023 From: dholmes at openjdk.org (David Holmes) Date: Tue, 24 Jan 2023 06:31:11 GMT Subject: RFR: 8290918: Initial nroff manpage generation for JDK 21 In-Reply-To: References: <_l9LWouUV22whyL4PTf1esOed9cZw1jyKKVBozovayE=.f79dbc18-b48e-4e52-8a16-f9e1b732ce50@github.com> Message-ID: On Tue, 24 Jan 2023 05:54:44 GMT, Joe Darcy wrote: >> Please review this simple update to the manpage to set the version to 21-ea. >> >> This change also corrects a typo in javac.1 that was manually introduced by JDK-8300591 >> >> Thanks. > > Marked as reviewed by darcy (Reviewer). Thanks for the review @jddarcy ! I think that suffices for this trivial change. ------------- PR: https://git.openjdk.org/jdk/pull/12154 From dholmes at openjdk.org Tue Jan 24 06:31:13 2023 From: dholmes at openjdk.org (David Holmes) Date: Tue, 24 Jan 2023 06:31:13 GMT Subject: Integrated: 8290918: Initial nroff manpage generation for JDK 21 In-Reply-To: <_l9LWouUV22whyL4PTf1esOed9cZw1jyKKVBozovayE=.f79dbc18-b48e-4e52-8a16-f9e1b732ce50@github.com> References: <_l9LWouUV22whyL4PTf1esOed9cZw1jyKKVBozovayE=.f79dbc18-b48e-4e52-8a16-f9e1b732ce50@github.com> Message-ID: On Mon, 23 Jan 2023 22:59:22 GMT, David Holmes wrote: > Please review this simple update to the manpage to set the version to 21-ea. > > This change also corrects a typo in javac.1 that was manually introduced by JDK-8300591 > > Thanks. This pull request has now been integrated. Changeset: 6dd8723f Author: David Holmes URL: https://git.openjdk.org/jdk/commit/6dd8723f66a22e626d98c74cff0b0b344a62626d Stats: 28 lines in 27 files changed: 0 ins; 0 del; 28 mod 8290918: Initial nroff manpage generation for JDK 21 Reviewed-by: lancea, iris, darcy ------------- PR: https://git.openjdk.org/jdk/pull/12154 From dnguyen at openjdk.org Tue Jan 24 20:57:43 2023 From: dnguyen at openjdk.org (Damon Nguyen) Date: Tue, 24 Jan 2023 20:57:43 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update Message-ID: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Open l10n drop. Files have been updated with translated versions. Whitespace tool has been ran on files. All tests passed ------------- Commit messages: - Remove currency symbol entries - Remove whitespace using tool - Remove double quotes generated by translation tool - Revert translation's removal of text - Update files for localization Changes: https://git.openjdk.org/jdk20/pull/116/files Webrev: https://webrevs.openjdk.org/?repo=jdk20&pr=116&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8300719 Stats: 1030 lines in 81 files changed: 218 ins; 115 del; 697 mod Patch: https://git.openjdk.org/jdk20/pull/116.diff Fetch: git fetch https://git.openjdk.org/jdk20 pull/116/head:pull/116 PR: https://git.openjdk.org/jdk20/pull/116 From dnguyen at openjdk.org Tue Jan 24 21:08:11 2023 From: dnguyen at openjdk.org (Damon Nguyen) Date: Tue, 24 Jan 2023 21:08:11 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update In-Reply-To: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: <4tI9y6FpAFrOiS4N4joygZHAHvPm-Ka2D9_3F8pyD6o=.fbb62ba6-4658-46b5-96f8-307ab3b41f81@github.com> On Tue, 24 Jan 2023 20:50:00 GMT, Damon Nguyen wrote: > Open l10n drop. Files have been updated with translated versions. Whitespace tool has been ran on files. > All tests passed @prrace @wangweij @naotoj @JoeWang-Java @plummercj @alexeysemenyukoracle Could you review the changes from this localization drop? ------------- PR: https://git.openjdk.org/jdk20/pull/116 From dnguyen at openjdk.org Tue Jan 24 21:48:11 2023 From: dnguyen at openjdk.org (Damon Nguyen) Date: Tue, 24 Jan 2023 21:48:11 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update In-Reply-To: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: On Tue, 24 Jan 2023 20:50:00 GMT, Damon Nguyen wrote: > Open l10n drop. Files have been updated with translated versions. Whitespace tool has been ran on files. > All tests passed @magicus @LanceAndersen @jonathan-gibbons @pavelrappo @dougxc @lahodaj Could you review the changes from this localization drop for the areas you're familiar with? ------------- PR: https://git.openjdk.org/jdk20/pull/116 From cjplummer at openjdk.org Tue Jan 24 22:05:10 2023 From: cjplummer at openjdk.org (Chris Plummer) Date: Tue, 24 Jan 2023 22:05:10 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update In-Reply-To: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: On Tue, 24 Jan 2023 20:50:00 GMT, Damon Nguyen wrote: > Open l10n drop. Files have been updated with translated versions. Whitespace tool has been ran on files. > All tests passed jdk.console and jdk.management.agent changes look good. ------------- Marked as reviewed by cjplummer (Reviewer). PR: https://git.openjdk.org/jdk20/pull/116 From dnguyen at openjdk.org Tue Jan 24 22:12:26 2023 From: dnguyen at openjdk.org (Damon Nguyen) Date: Tue, 24 Jan 2023 22:12:26 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v2] In-Reply-To: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: > Open l10n drop. Files have been updated with translated versions. Whitespace tool has been ran on files. > All tests passed Damon Nguyen has updated the pull request incrementally with one additional commit since the last revision: Change German help of jar command ------------- Changes: - all: https://git.openjdk.org/jdk20/pull/116/files - new: https://git.openjdk.org/jdk20/pull/116/files/4ced04fb..a2528015 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk20&pr=116&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk20&pr=116&range=00-01 Stats: 1 line in 1 file changed: 0 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jdk20/pull/116.diff Fetch: git fetch https://git.openjdk.org/jdk20 pull/116/head:pull/116 PR: https://git.openjdk.org/jdk20/pull/116 From naoto at openjdk.org Tue Jan 24 22:24:15 2023 From: naoto at openjdk.org (Naoto Sato) Date: Tue, 24 Jan 2023 22:24:15 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v2] In-Reply-To: References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: On Tue, 24 Jan 2023 22:12:26 GMT, Damon Nguyen wrote: >> Open l10n drop. Files have been updated with translated versions. Whitespace tool has been ran on files. >> All tests passed > > Damon Nguyen has updated the pull request incrementally with one additional commit since the last revision: > > Change German help of jar command Changes requested by naoto (Reviewer). src/jdk.jconsole/share/classes/sun/tools/jconsole/resources/messages_zh_CN.properties line 174: > 172: MBEANS_TAB_UNSUBSCRIBE_NOTIFICATIONS_BUTTON=\u53D6\u6D88\u8BA2\u9605(&U) > 173: MBEANS_TAB_UNSUBSCRIBE_NOTIFICATIONS_BUTTON_TOOLTIP=\u505C\u6B62\u76D1\u542C\u901A\u77E5 > 174: MANAGE_HOTSPOT_MBEANS_IN_COLON_=\u7BA1\u7406\u4EE5\u4E0B\u4F4D\u7F6E\u7684 HotSpot MBean: This looks like a prefix, so instead of removing the space, it should be replaced with `\u0020` like other locations. Also, it seems that other l10n files (de, ja) do not seem to have spaces in the first place. src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_de.properties line 38: > 36: resource.post-msi-script=Auszuf\u00FChrendes Skript nach dem Erstellen der MSI-Datei f\u00FCr das EXE-Installationsprogramm > 37: resource.wxl-file=WiX-Lokalisierungsdatei > 38: resource.wxl-file-name=MsiInstallerStrings_en.wxl Shouldn't this be `de`? src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_ja.properties line 38: > 36: resource.post-msi-script=exe\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9\u306Emsi\u30D5\u30A1\u30A4\u30EB\u304C\u4F5C\u6210\u3055\u308C\u305F\u5F8C\u306B\u5B9F\u884C\u3059\u308B\u30B9\u30AF\u30EA\u30D7\u30C8 > 37: resource.wxl-file=WiX\u30ED\u30FC\u30AB\u30EA\u30BC\u30FC\u30B7\u30E7\u30F3\u30FB\u30D5\u30A1\u30A4\u30EB > 38: resource.wxl-file-name=MsiInstallerStrings_en.wxl Shouldn't this be `ja`? src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_zh_CN.properties line 38: > 36: resource.post-msi-script=\u5728\u4E3A exe \u5B89\u88C5\u7A0B\u5E8F\u521B\u5EFA msi \u6587\u4EF6\u4E4B\u540E\u8981\u8FD0\u884C\u7684\u811A\u672C > 37: resource.wxl-file=WiX \u672C\u5730\u5316\u6587\u4EF6 > 38: resource.wxl-file-name=MsiInstallerStrings_en.wxl Shouldn't this be `zh_CN`? src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_zh_CN.properties line 63: > 61: # written authorization of the copyright holder. > 62: > 63: CNY=\uffe5 Do not remove this. ------------- PR: https://git.openjdk.org/jdk20/pull/116 From dnguyen at openjdk.org Tue Jan 24 22:24:16 2023 From: dnguyen at openjdk.org (Damon Nguyen) Date: Tue, 24 Jan 2023 22:24:16 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v2] In-Reply-To: References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: On Tue, 24 Jan 2023 22:05:55 GMT, Naoto Sato wrote: >> Damon Nguyen has updated the pull request incrementally with one additional commit since the last revision: >> >> Change German help of jar command > > src/jdk.jconsole/share/classes/sun/tools/jconsole/resources/messages_zh_CN.properties line 174: > >> 172: MBEANS_TAB_UNSUBSCRIBE_NOTIFICATIONS_BUTTON=\u53D6\u6D88\u8BA2\u9605(&U) >> 173: MBEANS_TAB_UNSUBSCRIBE_NOTIFICATIONS_BUTTON_TOOLTIP=\u505C\u6B62\u76D1\u542C\u901A\u77E5 >> 174: MANAGE_HOTSPOT_MBEANS_IN_COLON_=\u7BA1\u7406\u4EE5\u4E0B\u4F4D\u7F6E\u7684 HotSpot MBean: > > This looks like a prefix, so instead of removing the space, it should be replaced with `\u0020` like other locations. > Also, it seems that other l10n files (de, ja) do not seem to have spaces in the first place. OK, I can make the manual edit for this > src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_zh_CN.properties line 38: > >> 36: resource.post-msi-script=\u5728\u4E3A exe \u5B89\u88C5\u7A0B\u5E8F\u521B\u5EFA msi \u6587\u4EF6\u4E4B\u540E\u8981\u8FD0\u884C\u7684\u811A\u672C >> 37: resource.wxl-file=WiX \u672C\u5730\u5316\u6587\u4EF6 >> 38: resource.wxl-file-name=MsiInstallerStrings_en.wxl > > Shouldn't this be `zh_CN`? The translation tool seems to use the English source file's file name here, so it's replaced. I will handle these 3 occurrences now. I thought I handled all occurrences of this, but these 3 slipped in ------------- PR: https://git.openjdk.org/jdk20/pull/116 From dnguyen at openjdk.org Tue Jan 24 22:33:24 2023 From: dnguyen at openjdk.org (Damon Nguyen) Date: Tue, 24 Jan 2023 22:33:24 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v3] In-Reply-To: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: > Open l10n drop. Files have been updated with translated versions. Whitespace tool has been ran on files. > All tests passed Damon Nguyen has updated the pull request incrementally with one additional commit since the last revision: Change localization codes. Add CNY back ------------- Changes: - all: https://git.openjdk.org/jdk20/pull/116/files - new: https://git.openjdk.org/jdk20/pull/116/files/a2528015..40291c61 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk20&pr=116&range=02 - incr: https://webrevs.openjdk.org/?repo=jdk20&pr=116&range=01-02 Stats: 4 lines in 4 files changed: 1 ins; 0 del; 3 mod Patch: https://git.openjdk.org/jdk20/pull/116.diff Fetch: git fetch https://git.openjdk.org/jdk20 pull/116/head:pull/116 PR: https://git.openjdk.org/jdk20/pull/116 From dnguyen at openjdk.org Tue Jan 24 22:33:28 2023 From: dnguyen at openjdk.org (Damon Nguyen) Date: Tue, 24 Jan 2023 22:33:28 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v2] In-Reply-To: References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: On Tue, 24 Jan 2023 22:12:02 GMT, Naoto Sato wrote: >> Damon Nguyen has updated the pull request incrementally with one additional commit since the last revision: >> >> Change German help of jar command > > src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_de.properties line 38: > >> 36: resource.post-msi-script=Auszuf\u00FChrendes Skript nach dem Erstellen der MSI-Datei f\u00FCr das EXE-Installationsprogramm >> 37: resource.wxl-file=WiX-Lokalisierungsdatei >> 38: resource.wxl-file-name=MsiInstallerStrings_en.wxl > > Shouldn't this be `de`? Changed back similar to with zh_CN > src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_ja.properties line 38: > >> 36: resource.post-msi-script=exe\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9\u306Emsi\u30D5\u30A1\u30A4\u30EB\u304C\u4F5C\u6210\u3055\u308C\u305F\u5F8C\u306B\u5B9F\u884C\u3059\u308B\u30B9\u30AF\u30EA\u30D7\u30C8 >> 37: resource.wxl-file=WiX\u30ED\u30FC\u30AB\u30EA\u30BC\u30FC\u30B7\u30E7\u30F3\u30FB\u30D5\u30A1\u30A4\u30EB >> 38: resource.wxl-file-name=MsiInstallerStrings_en.wxl > > Shouldn't this be `ja`? Changed back similar to with zh_CN ------------- PR: https://git.openjdk.org/jdk20/pull/116 From dnguyen at openjdk.org Tue Jan 24 22:33:29 2023 From: dnguyen at openjdk.org (Damon Nguyen) Date: Tue, 24 Jan 2023 22:33:29 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v3] In-Reply-To: References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: On Tue, 24 Jan 2023 22:14:36 GMT, Naoto Sato wrote: >> Damon Nguyen has updated the pull request incrementally with one additional commit since the last revision: >> >> Change localization codes. Add CNY back > > src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_zh_CN.properties line 63: > >> 61: # written authorization of the copyright holder. >> 62: >> 63: CNY=\uffe5 > > Do not remove this. Added back. Thanks for catching this! ------------- PR: https://git.openjdk.org/jdk20/pull/116 From prr at openjdk.org Tue Jan 24 22:44:13 2023 From: prr at openjdk.org (Phil Race) Date: Tue, 24 Jan 2023 22:44:13 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v2] In-Reply-To: References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: On Tue, 24 Jan 2023 22:12:26 GMT, Damon Nguyen wrote: >> Open l10n drop. Files have been updated with translated versions. Whitespace tool has been ran on files. >> All tests passed > > Damon Nguyen has updated the pull request incrementally with one additional commit since the last revision: > > Change German help of jar command Removing the trailing white space seems OK in the desktop resources. I checked the base (English) version of the files and none of them have trailing white space so it seems unlikely it is significant. ------------- Marked as reviewed by prr (Reviewer). PR: https://git.openjdk.org/jdk20/pull/116 From jlu at openjdk.org Tue Jan 24 22:44:14 2023 From: jlu at openjdk.org (Justin Lu) Date: Tue, 24 Jan 2023 22:44:14 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v3] In-Reply-To: References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: On Tue, 24 Jan 2023 22:20:22 GMT, Damon Nguyen wrote: >> src/jdk.jconsole/share/classes/sun/tools/jconsole/resources/messages_zh_CN.properties line 174: >> >>> 172: MBEANS_TAB_UNSUBSCRIBE_NOTIFICATIONS_BUTTON=\u53D6\u6D88\u8BA2\u9605(&U) >>> 173: MBEANS_TAB_UNSUBSCRIBE_NOTIFICATIONS_BUTTON_TOOLTIP=\u505C\u6B62\u76D1\u542C\u901A\u77E5 >>> 174: MANAGE_HOTSPOT_MBEANS_IN_COLON_=\u7BA1\u7406\u4EE5\u4E0B\u4F4D\u7F6E\u7684 HotSpot MBean: >> >> This looks like a prefix, so instead of removing the space, it should be replaced with `\u0020` like other locations. >> Also, it seems that other l10n files (de, ja) do not seem to have spaces in the first place. > > OK, I can make the manual edit for this This change was made because it was compared to the original messages.properties. In that file, the respective line is given as `MANAGE_HOTSPOT_MBEANS_IN_COLON_=Manage Hotspot MBeans in:` with no trailing space. That's why in this file, to ensure consistency, the trailing space was stripped. I think either this space should be removed, or all 4 (en, ja, de, zh) should have the `\u0020` appended. I agree that since it is a prefix it would make sense for a space to be there, but there is no guarantee that what comes after, or even the code that loads the .properties file does not already handles that necessary space. Should the space remain removed like in the English source file and the other l10n files, or do you think all 4 should be changed to add `\u0020`? ------------- PR: https://git.openjdk.org/jdk20/pull/116 From joehw at openjdk.org Tue Jan 24 22:59:07 2023 From: joehw at openjdk.org (Joe Wang) Date: Tue, 24 Jan 2023 22:59:07 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v3] In-Reply-To: References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: <8IAAljdZ35sxC22s2SeFdCTX5xmx83YUFr8dwOYtXzA=.028e67c7-0969-4204-b843-0c0f2d79574f@github.com> On Tue, 24 Jan 2023 22:33:24 GMT, Damon Nguyen wrote: >> Open l10n drop. Files have been updated with translated versions. Whitespace tool has been ran on files. >> All tests passed > > Damon Nguyen has updated the pull request incrementally with one additional commit since the last revision: > > Change localization codes. Add CNY back Marked as reviewed by joehw (Reviewer). java.xml changes look good to me. Thanks. ------------- PR: https://git.openjdk.org/jdk20/pull/116 From naoto at openjdk.org Tue Jan 24 22:59:08 2023 From: naoto at openjdk.org (Naoto Sato) Date: Tue, 24 Jan 2023 22:59:08 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v3] In-Reply-To: References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: On Tue, 24 Jan 2023 22:40:55 GMT, Justin Lu wrote: >> OK, I can make the manual edit for this > > This change was made because it was compared to the original messages.properties. In that file, the respective line is given as `MANAGE_HOTSPOT_MBEANS_IN_COLON_=Manage Hotspot MBeans in:` with no trailing space. That's why in this file, to ensure consistency, the trailing space was stripped. > > I think either this space should be removed, or all 4 (en, ja, de, zh) should have the `\u0020` appended. I agree that since it is a prefix it would make sense for a space to be there, but there is no guarantee that what comes after, or even the code that loads the .properties file does not already handles that necessary space. > > Should the space remain removed like in the English source file and the other l10n files, or do you think all 4 should be changed to add `\u0020`? Confirmed that the message is for a label (`sun.tools.jconsole.LabeledComponent`), followed by a Component, so no space seems needed in each file. Sorry for the false alarm. ------------- PR: https://git.openjdk.org/jdk20/pull/116 From dnguyen at openjdk.org Tue Jan 24 22:59:08 2023 From: dnguyen at openjdk.org (Damon Nguyen) Date: Tue, 24 Jan 2023 22:59:08 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v3] In-Reply-To: References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: On Tue, 24 Jan 2023 22:49:20 GMT, Naoto Sato wrote: >> This change was made because it was compared to the original messages.properties. In that file, the respective line is given as `MANAGE_HOTSPOT_MBEANS_IN_COLON_=Manage Hotspot MBeans in:` with no trailing space. That's why in this file, to ensure consistency, the trailing space was stripped. >> >> I think either this space should be removed, or all 4 (en, ja, de, zh) should have the `\u0020` appended. I agree that since it is a prefix it would make sense for a space to be there, but there is no guarantee that what comes after, or even the code that loads the .properties file does not already handles that necessary space. >> >> Should the space remain removed like in the English source file and the other l10n files, or do you think all 4 should be changed to add `\u0020`? > > Confirmed that the message is for a label (`sun.tools.jconsole.LabeledComponent`), followed by a Component, so no space seems needed in each file. Sorry for the false alarm. Ok I left this change out of my most recent update just in case. I addressed all the other comments I believe. Thanks! ------------- PR: https://git.openjdk.org/jdk20/pull/116 From asemenyuk at openjdk.org Tue Jan 24 22:59:12 2023 From: asemenyuk at openjdk.org (Alexey Semenyuk) Date: Tue, 24 Jan 2023 22:59:12 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v3] In-Reply-To: References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: On Tue, 24 Jan 2023 22:33:24 GMT, Damon Nguyen wrote: >> Open l10n drop. Files have been updated with translated versions. Whitespace tool has been ran on files. >> All tests passed > > Damon Nguyen has updated the pull request incrementally with one additional commit since the last revision: > > Change localization codes. Add CNY back src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_de.wxl line 2: > 1: > 2: Please revert the value of the `Culture` attribute. src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_ja.wxl line 2: > 1: > 2: Please revert the value of the `Culture` attribute. src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_zh_CN.wxl line 2: > 1: > 2: Please revert the value of the `Culture` attribute. ------------- PR: https://git.openjdk.org/jdk20/pull/116 From jlu at openjdk.org Tue Jan 24 23:06:14 2023 From: jlu at openjdk.org (Justin Lu) Date: Tue, 24 Jan 2023 23:06:14 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v3] In-Reply-To: References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: On Tue, 24 Jan 2023 22:33:24 GMT, Damon Nguyen wrote: >> Open l10n drop. Files have been updated with translated versions. Whitespace tool has been ran on files. >> All tests passed > > Damon Nguyen has updated the pull request incrementally with one additional commit since the last revision: > > Change localization codes. Add CNY back src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins_ja.properties line 62: > 60: dedup-legal-notices.usage=\ --dedup-legal-notices [error-if-not-same-content]\n \u3059\u3079\u3066\u306E\u6CD5\u5F8B\u4E0A\u306E\u6CE8\u610F\u70B9\u306E\u91CD\u8907\u3092\u9664\u5916\u3057\u307E\u3059\u3002\n error-if-not-same-content\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u308B\u5834\u5408\u3001\n \u540C\u3058\u30D5\u30A1\u30A4\u30EB\u540D\u306E2\u3064\u306E\u30D5\u30A1\u30A4\u30EB\u304C\u7570\u306A\u3063\u3066\u3044\u308B\u3068\n \u30A8\u30E9\u30FC\u306B\u306A\u308A\u307E\u3059\u3002 > 61: > 62: exclude-files.argument=\u9664\u5916\u3059\u308B\u30D5\u30A1\u30A4\u30EB\u306E It seems like the translation process added a space here, but it does not appear in the original. This should be removed. src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins_zh_CN.properties line 194: > 192: main.plugin.module=\u63D2\u4EF6\u6A21\u5757 > 193: > 194: main.plugin.category=\u7C7B\u522B Same as above. ------------- PR: https://git.openjdk.org/jdk20/pull/116 From asemenyuk at openjdk.org Tue Jan 24 23:19:12 2023 From: asemenyuk at openjdk.org (Alexey Semenyuk) Date: Tue, 24 Jan 2023 23:19:12 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v3] In-Reply-To: References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: <53tinlttCmtNrOBaz7F54bKSeftrurnsr9OVoQzzjC8=.191b9195-e775-4b4b-8811-d34789cec36e@github.com> On Tue, 24 Jan 2023 22:33:24 GMT, Damon Nguyen wrote: >> Open l10n drop. Files have been updated with translated versions. Whitespace tool has been ran on files. >> All tests passed > > Damon Nguyen has updated the pull request incrementally with one additional commit since the last revision: > > Change localization codes. Add CNY back Changes requested by asemenyuk (Reviewer). src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_zh_CN.wxl line 2: > 1: > 2: Please revert the value of the Culture attribute. ------------- PR: https://git.openjdk.org/jdk20/pull/116 From dnguyen at openjdk.org Tue Jan 24 23:38:23 2023 From: dnguyen at openjdk.org (Damon Nguyen) Date: Tue, 24 Jan 2023 23:38:23 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v4] In-Reply-To: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: > Open l10n drop. Files have been updated with translated versions. Whitespace tool has been ran on files. > All tests passed Damon Nguyen has updated the pull request incrementally with one additional commit since the last revision: Remove trailing whitespace ------------- Changes: - all: https://git.openjdk.org/jdk20/pull/116/files - new: https://git.openjdk.org/jdk20/pull/116/files/40291c61..fc32c37f Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk20&pr=116&range=03 - incr: https://webrevs.openjdk.org/?repo=jdk20&pr=116&range=02-03 Stats: 2 lines in 2 files changed: 0 ins; 0 del; 2 mod Patch: https://git.openjdk.org/jdk20/pull/116.diff Fetch: git fetch https://git.openjdk.org/jdk20 pull/116/head:pull/116 PR: https://git.openjdk.org/jdk20/pull/116 From dnguyen at openjdk.org Tue Jan 24 23:56:23 2023 From: dnguyen at openjdk.org (Damon Nguyen) Date: Tue, 24 Jan 2023 23:56:23 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v5] In-Reply-To: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: > Open l10n drop. Files have been updated with translated versions. Whitespace tool has been ran on files. > All tests passed Damon Nguyen has updated the pull request incrementally with one additional commit since the last revision: Revert culture attribute ------------- Changes: - all: https://git.openjdk.org/jdk20/pull/116/files - new: https://git.openjdk.org/jdk20/pull/116/files/fc32c37f..616b2502 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk20&pr=116&range=04 - incr: https://webrevs.openjdk.org/?repo=jdk20&pr=116&range=03-04 Stats: 3 lines in 3 files changed: 0 ins; 0 del; 3 mod Patch: https://git.openjdk.org/jdk20/pull/116.diff Fetch: git fetch https://git.openjdk.org/jdk20 pull/116/head:pull/116 PR: https://git.openjdk.org/jdk20/pull/116 From dnguyen at openjdk.org Tue Jan 24 23:59:13 2023 From: dnguyen at openjdk.org (Damon Nguyen) Date: Tue, 24 Jan 2023 23:59:13 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v3] In-Reply-To: References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: On Tue, 24 Jan 2023 23:02:58 GMT, Justin Lu wrote: >> Damon Nguyen has updated the pull request incrementally with one additional commit since the last revision: >> >> Change localization codes. Add CNY back > > src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins_ja.properties line 62: > >> 60: dedup-legal-notices.usage=\ --dedup-legal-notices [error-if-not-same-content]\n \u3059\u3079\u3066\u306E\u6CD5\u5F8B\u4E0A\u306E\u6CE8\u610F\u70B9\u306E\u91CD\u8907\u3092\u9664\u5916\u3057\u307E\u3059\u3002\n error-if-not-same-content\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u308B\u5834\u5408\u3001\n \u540C\u3058\u30D5\u30A1\u30A4\u30EB\u540D\u306E2\u3064\u306E\u30D5\u30A1\u30A4\u30EB\u304C\u7570\u306A\u3063\u3066\u3044\u308B\u3068\n \u30A8\u30E9\u30FC\u306B\u306A\u308A\u307E\u3059\u3002 >> 61: >> 62: exclude-files.argument=\u9664\u5916\u3059\u308B\u30D5\u30A1\u30A4\u30EB\u306E > > It seems like the translation process added a space here, but it does not appear in the original. This should be removed. Removed both instances of the extra trailing whitespace. > src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins_zh_CN.properties line 194: > >> 192: main.plugin.module=\u63D2\u4EF6\u6A21\u5757 >> 193: >> 194: main.plugin.category=\u7C7B\u522B > > Same as above. Addressed as above ------------- PR: https://git.openjdk.org/jdk20/pull/116 From dnguyen at openjdk.org Tue Jan 24 23:59:17 2023 From: dnguyen at openjdk.org (Damon Nguyen) Date: Tue, 24 Jan 2023 23:59:17 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v2] In-Reply-To: References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: On Tue, 24 Jan 2023 22:55:43 GMT, Alexey Semenyuk wrote: >> Damon Nguyen has updated the pull request incrementally with one additional commit since the last revision: >> >> Change German help of jar command > > src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_de.wxl line 2: > >> 1: >> 2: > > Please revert the value of the `Culture` attribute. I resolved this for the German, Japanese, and Chinese files in the latest commit. > src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_ja.wxl line 2: > >> 1: >> 2: > > Please revert the value of the `Culture` attribute. Resolved in recent commit ------------- PR: https://git.openjdk.org/jdk20/pull/116 From dnguyen at openjdk.org Tue Jan 24 23:59:19 2023 From: dnguyen at openjdk.org (Damon Nguyen) Date: Tue, 24 Jan 2023 23:59:19 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v3] In-Reply-To: <53tinlttCmtNrOBaz7F54bKSeftrurnsr9OVoQzzjC8=.191b9195-e775-4b4b-8811-d34789cec36e@github.com> References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> <53tinlttCmtNrOBaz7F54bKSeftrurnsr9OVoQzzjC8=.191b9195-e775-4b4b-8811-d34789cec36e@github.com> Message-ID: On Tue, 24 Jan 2023 23:16:02 GMT, Alexey Semenyuk wrote: >> Damon Nguyen has updated the pull request incrementally with one additional commit since the last revision: >> >> Change localization codes. Add CNY back > > src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_zh_CN.wxl line 2: > >> 1: >> 2: > > Please revert the value of the Culture attribute. Resolved in recent commit ------------- PR: https://git.openjdk.org/jdk20/pull/116 From asemenyuk at openjdk.org Wed Jan 25 00:12:09 2023 From: asemenyuk at openjdk.org (Alexey Semenyuk) Date: Wed, 25 Jan 2023 00:12:09 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v5] In-Reply-To: References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: On Tue, 24 Jan 2023 23:56:23 GMT, Damon Nguyen wrote: >> Open l10n drop. Files have been updated with translated versions. Whitespace tool has been ran on files. >> All tests passed > > Damon Nguyen has updated the pull request incrementally with one additional commit since the last revision: > > Revert culture attribute jpackage changes look good ------------- Marked as reviewed by asemenyuk (Reviewer). PR: https://git.openjdk.org/jdk20/pull/116 From jlu at openjdk.org Wed Jan 25 01:11:15 2023 From: jlu at openjdk.org (Justin Lu) Date: Wed, 25 Jan 2023 01:11:15 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v5] In-Reply-To: References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: On Tue, 24 Jan 2023 23:56:23 GMT, Damon Nguyen wrote: >> Open l10n drop. Files have been updated with translated versions. Whitespace tool has been ran on files. >> All tests passed > > Damon Nguyen has updated the pull request incrementally with one additional commit since the last revision: > > Revert culture attribute Marked as reviewed by jlu (Author). ------------- PR: https://git.openjdk.org/jdk20/pull/116 From duke at openjdk.org Wed Jan 25 08:20:13 2023 From: duke at openjdk.org (danielpeintner) Date: Wed, 25 Jan 2023 08:20:13 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v2] In-Reply-To: References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: On Tue, 24 Jan 2023 22:12:26 GMT, Damon Nguyen wrote: >> Open l10n drop. Files have been updated with translated versions. Whitespace tool has been ran on files. >> All tests passed > > Damon Nguyen has updated the pull request incrementally with one additional commit since the last revision: > > Change German help of jar command src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_de.properties line 111: > 109: main.help.opt.main.update=\ -u, --update Ein vorhandenes JAR-Archiv aktualisieren > 110: main.help.opt.main.extract=\ -x, --extract Benannte (oder alle) Dateien aus dem Archiv extrahieren > 111: main.help.opt.main.describe-module=\ -d, --describe-module Gibt den Moduldeskriptor oder automatischen Modulnamen aus Just because I stumbled over this commit. I think the line should be translated as follows: `Gibt die Modulbeschreibung oder den automatischen Modulnamen aus` ------------- PR: https://git.openjdk.org/jdk20/pull/116 From lancea at openjdk.org Wed Jan 25 13:45:21 2023 From: lancea at openjdk.org (Lance Andersen) Date: Wed, 25 Jan 2023 13:45:21 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v5] In-Reply-To: References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: On Tue, 24 Jan 2023 23:56:23 GMT, Damon Nguyen wrote: >> Open l10n drop. Files have been updated with translated versions. Whitespace tool has been ran on files. >> All tests passed > > Damon Nguyen has updated the pull request incrementally with one additional commit since the last revision: > > Revert culture attribute Marked as reviewed by lancea (Reviewer). ------------- PR: https://git.openjdk.org/jdk20/pull/116 From ihse at openjdk.org Wed Jan 25 13:56:21 2023 From: ihse at openjdk.org (Magnus Ihse Bursie) Date: Wed, 25 Jan 2023 13:56:21 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v5] In-Reply-To: References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: <-Mjbn1ko2InJOzXLccieEzU8h4bypdm9vTzHdmtA-JQ=.2e1f4d59-e30e-434a-8e62-25777adb3a07@github.com> On Tue, 24 Jan 2023 23:56:23 GMT, Damon Nguyen wrote: >> Open l10n drop. Files have been updated with translated versions. Whitespace tool has been ran on files. >> All tests passed > > Damon Nguyen has updated the pull request incrementally with one additional commit since the last revision: > > Revert culture attribute I skimmed through this, basically looking for trailing white space changes only, and it generally looks okay. Note that some of these trailing whitespace fixes has been independently address in mainline. Forward-porting this might involve some (virtual) conflicts. It is also impossible to see in the Github interface if you are introducing *new* trailing white spaces in the added texts. I hope you are not, and that you have verified this. ------------- Marked as reviewed by ihse (Reviewer). PR: https://git.openjdk.org/jdk20/pull/116 From naoto at openjdk.org Wed Jan 25 16:55:04 2023 From: naoto at openjdk.org (Naoto Sato) Date: Wed, 25 Jan 2023 16:55:04 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v5] In-Reply-To: References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: On Tue, 24 Jan 2023 23:56:23 GMT, Damon Nguyen wrote: >> Open l10n drop. Files have been updated with translated versions. Whitespace tool has been ran on files. >> All tests passed > > Damon Nguyen has updated the pull request incrementally with one additional commit since the last revision: > > Revert culture attribute LGTM ------------- Marked as reviewed by naoto (Reviewer). PR: https://git.openjdk.org/jdk20/pull/116 From weijun at openjdk.org Wed Jan 25 17:36:38 2023 From: weijun at openjdk.org (Weijun Wang) Date: Wed, 25 Jan 2023 17:36:38 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v5] In-Reply-To: References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: <_THK1t7SrTRqoW0o0gfgmCo1Ea1WfgdfeB7jNJDKUKk=.05512373-8cb2-41d3-a71f-589075240bb7@github.com> On Tue, 24 Jan 2023 23:56:23 GMT, Damon Nguyen wrote: >> Open l10n drop. Files have been updated with translated versions. Whitespace tool has been ran on files. >> All tests passed > > Damon Nguyen has updated the pull request incrementally with one additional commit since the last revision: > > Revert culture attribute src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap_zh_CN.properties line 32: > 30: err.bad.constant.pool=\u8BFB\u53D6{0}\u7684\u5E38\u91CF\u6C60\u65F6\u51FA\u9519: {1} > 31: err.class.not.found=\u627E\u4E0D\u5230\u7C7B: {0} > 32: err.crash=\u51FA\u73B0\u4E25\u91CD\u7684\u5185\u90E8\u9519\u8BEF\uFF1A{0}\n\u8BF7\u586B\u5199 Bug \u62A5\u544A\uFF0C\u5E76\u5305\u62EC\u4EE5\u4E0B\u4FE1\u606F\uFF1A\n{1} While personally I like to see Chinese-style punctuation marks (Ex: `?`) used in Chinese contexts instead of their English-style ones (Ex: `:`), it's only updated on this single line and all the others are still using the English-style. There should be a general rule on which style we should use throughout all display messages. ------------- PR: https://git.openjdk.org/jdk20/pull/116 From dnguyen at openjdk.org Wed Jan 25 17:47:19 2023 From: dnguyen at openjdk.org (Damon Nguyen) Date: Wed, 25 Jan 2023 17:47:19 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v6] In-Reply-To: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: > Open l10n drop. Files have been updated with translated versions. Whitespace tool has been ran on files. > All tests passed Damon Nguyen has updated the pull request incrementally with one additional commit since the last revision: Revert translated punctuation ------------- Changes: - all: https://git.openjdk.org/jdk20/pull/116/files - new: https://git.openjdk.org/jdk20/pull/116/files/616b2502..4222df9a Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk20&pr=116&range=05 - incr: https://webrevs.openjdk.org/?repo=jdk20&pr=116&range=04-05 Stats: 1 line in 1 file changed: 0 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jdk20/pull/116.diff Fetch: git fetch https://git.openjdk.org/jdk20 pull/116/head:pull/116 PR: https://git.openjdk.org/jdk20/pull/116 From dnguyen at openjdk.org Wed Jan 25 17:51:20 2023 From: dnguyen at openjdk.org (Damon Nguyen) Date: Wed, 25 Jan 2023 17:51:20 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v7] In-Reply-To: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: <5QDH5Zhiji1PTh-833JdIopABeDoDCLA5e-u1Q3pkUE=.98a38bd3-3e52-4b51-9287-dc70454c4b89@github.com> > Open l10n drop. Files have been updated with translated versions. Whitespace tool has been ran on files. > All tests passed Damon Nguyen has updated the pull request incrementally with one additional commit since the last revision: Revert one more punctuation ------------- Changes: - all: https://git.openjdk.org/jdk20/pull/116/files - new: https://git.openjdk.org/jdk20/pull/116/files/4222df9a..9a5b45a2 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk20&pr=116&range=06 - incr: https://webrevs.openjdk.org/?repo=jdk20&pr=116&range=05-06 Stats: 1 line in 1 file changed: 0 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jdk20/pull/116.diff Fetch: git fetch https://git.openjdk.org/jdk20 pull/116/head:pull/116 PR: https://git.openjdk.org/jdk20/pull/116 From weijun at openjdk.org Wed Jan 25 17:52:21 2023 From: weijun at openjdk.org (Weijun Wang) Date: Wed, 25 Jan 2023 17:52:21 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v5] In-Reply-To: References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: On Tue, 24 Jan 2023 23:56:23 GMT, Damon Nguyen wrote: >> Open l10n drop. Files have been updated with translated versions. Whitespace tool has been ran on files. >> All tests passed > > Damon Nguyen has updated the pull request incrementally with one additional commit since the last revision: > > Revert culture attribute src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_zh_CN.properties line 113: > 111: doclet.inheritDocWithinInappropriateTag=\u4E0D\u80FD\u5728\u6B64\u6807\u8BB0\u4E2D\u4F7F\u7528 @inheritDoc > 112: doclet.inheritDocNoDoc=\u88AB\u8986\u76D6\u7684\u65B9\u6CD5\u4E0D\u8BB0\u5F55\u5F02\u5E38\u9519\u8BEF\u7C7B\u578B {0} > 113: doclet.throwsInheritDocUnsupported=\u4E0D\u662F\u7531\u65B9\u6CD5\u58F0\u660E\u7684 exception-type \u7C7B\u578B\u53C2\u6570\u4E0D\u652F\u6301 @inheritDoc\uFF1B\u76F4\u63A5\u8BB0\u5F55\u6B64\u7C7B\u5F02\u5E38\u9519\u8BEF\u7C7B\u578B Should `exception-type` be translated? ------------- PR: https://git.openjdk.org/jdk20/pull/116 From dnguyen at openjdk.org Wed Jan 25 18:03:54 2023 From: dnguyen at openjdk.org (Damon Nguyen) Date: Wed, 25 Jan 2023 18:03:54 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v5] In-Reply-To: References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: On Wed, 25 Jan 2023 17:49:59 GMT, Weijun Wang wrote: >> Damon Nguyen has updated the pull request incrementally with one additional commit since the last revision: >> >> Revert culture attribute > > src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_zh_CN.properties line 113: > >> 111: doclet.inheritDocWithinInappropriateTag=\u4E0D\u80FD\u5728\u6B64\u6807\u8BB0\u4E2D\u4F7F\u7528 @inheritDoc >> 112: doclet.inheritDocNoDoc=\u88AB\u8986\u76D6\u7684\u65B9\u6CD5\u4E0D\u8BB0\u5F55\u5F02\u5E38\u9519\u8BEF\u7C7B\u578B {0} >> 113: doclet.throwsInheritDocUnsupported=\u4E0D\u662F\u7531\u65B9\u6CD5\u58F0\u660E\u7684 exception-type \u7C7B\u578B\u53C2\u6570\u4E0D\u652F\u6301 @inheritDoc\uFF1B\u76F4\u63A5\u8BB0\u5F55\u6B64\u7C7B\u5F02\u5E38\u9519\u8BEF\u7C7B\u578B > > Should `exception-type` be translated? The translation tool didn't seem to translate this. Either because it couldn't or because it somehow missed it. I'm not sure which, but I'm open to replacing this with a translation suggestion you have. Or I can leave it as is. > src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap_zh_CN.properties line 32: > >> 30: err.bad.constant.pool=\u8BFB\u53D6{0}\u7684\u5E38\u91CF\u6C60\u65F6\u51FA\u9519: {1} >> 31: err.class.not.found=\u627E\u4E0D\u5230\u7C7B: {0} >> 32: err.crash=\u51FA\u73B0\u4E25\u91CD\u7684\u5185\u90E8\u9519\u8BEF\uFF1A{0}\n\u8BF7\u586B\u5199 Bug \u62A5\u544A\uFF0C\u5E76\u5305\u62EC\u4EE5\u4E0B\u4FE1\u606F\uFF1A\n{1} > > While personally I like to see Chinese-style punctuation marks (Ex: `?`) used in Chinese contexts instead of their English-style ones (Ex: `:`), it's only updated on this single line and all the others are still using the English-style. > > There should be a general rule on which style we should use throughout all display messages. Updated the punctuation (colons and comma) to be more consistent throughout the file. ------------- PR: https://git.openjdk.org/jdk20/pull/116 From weijun at openjdk.org Wed Jan 25 18:03:55 2023 From: weijun at openjdk.org (Weijun Wang) Date: Wed, 25 Jan 2023 18:03:55 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v5] In-Reply-To: References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: On Wed, 25 Jan 2023 17:56:15 GMT, Damon Nguyen wrote: >> src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_zh_CN.properties line 113: >> >>> 111: doclet.inheritDocWithinInappropriateTag=\u4E0D\u80FD\u5728\u6B64\u6807\u8BB0\u4E2D\u4F7F\u7528 @inheritDoc >>> 112: doclet.inheritDocNoDoc=\u88AB\u8986\u76D6\u7684\u65B9\u6CD5\u4E0D\u8BB0\u5F55\u5F02\u5E38\u9519\u8BEF\u7C7B\u578B {0} >>> 113: doclet.throwsInheritDocUnsupported=\u4E0D\u662F\u7531\u65B9\u6CD5\u58F0\u660E\u7684 exception-type \u7C7B\u578B\u53C2\u6570\u4E0D\u652F\u6301 @inheritDoc\uFF1B\u76F4\u63A5\u8BB0\u5F55\u6B64\u7C7B\u5F02\u5E38\u9519\u8BEF\u7C7B\u578B >> >> Should `exception-type` be translated? > > The translation tool didn't seem to translate this. Either because it couldn't or because it somehow missed it. I'm not sure which, but I'm open to replacing this with a translation suggestion you have. Or I can leave it as is. I'm not sure either. You can ask a javadoc expert whether this is a proper noun or just plain English. I noticed it's also not translated in the Japanese version but the German version has translated it. >> src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap_zh_CN.properties line 32: >> >>> 30: err.bad.constant.pool=\u8BFB\u53D6{0}\u7684\u5E38\u91CF\u6C60\u65F6\u51FA\u9519: {1} >>> 31: err.class.not.found=\u627E\u4E0D\u5230\u7C7B: {0} >>> 32: err.crash=\u51FA\u73B0\u4E25\u91CD\u7684\u5185\u90E8\u9519\u8BEF\uFF1A{0}\n\u8BF7\u586B\u5199 Bug \u62A5\u544A\uFF0C\u5E76\u5305\u62EC\u4EE5\u4E0B\u4FE1\u606F\uFF1A\n{1} >> >> While personally I like to see Chinese-style punctuation marks (Ex: `?`) used in Chinese contexts instead of their English-style ones (Ex: `:`), it's only updated on this single line and all the others are still using the English-style. >> >> There should be a general rule on which style we should use throughout all display messages. > > Updated the punctuation (colons and comma) to be more consistent throughout the file. Looks good now. ------------- PR: https://git.openjdk.org/jdk20/pull/116 From jjg at openjdk.org Wed Jan 25 18:24:55 2023 From: jjg at openjdk.org (Jonathan Gibbons) Date: Wed, 25 Jan 2023 18:24:55 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v7] In-Reply-To: <5QDH5Zhiji1PTh-833JdIopABeDoDCLA5e-u1Q3pkUE=.98a38bd3-3e52-4b51-9287-dc70454c4b89@github.com> References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> <5QDH5Zhiji1PTh-833JdIopABeDoDCLA5e-u1Q3pkUE=.98a38bd3-3e52-4b51-9287-dc70454c4b89@github.com> Message-ID: On Wed, 25 Jan 2023 17:51:20 GMT, Damon Nguyen wrote: >> Open l10n drop. Files have been updated with translated versions. Whitespace tool has been ran on files. >> All tests passed > > Damon Nguyen has updated the pull request incrementally with one additional commit since the last revision: > > Revert one more punctuation I don't see anything absurdly wrong in the jdk.compiler files. ------------- Marked as reviewed by jjg (Reviewer). PR: https://git.openjdk.org/jdk20/pull/116 From weijun at openjdk.org Wed Jan 25 18:58:57 2023 From: weijun at openjdk.org (Weijun Wang) Date: Wed, 25 Jan 2023 18:58:57 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v7] In-Reply-To: <5QDH5Zhiji1PTh-833JdIopABeDoDCLA5e-u1Q3pkUE=.98a38bd3-3e52-4b51-9287-dc70454c4b89@github.com> References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> <5QDH5Zhiji1PTh-833JdIopABeDoDCLA5e-u1Q3pkUE=.98a38bd3-3e52-4b51-9287-dc70454c4b89@github.com> Message-ID: On Wed, 25 Jan 2023 17:51:20 GMT, Damon Nguyen wrote: >> Open l10n drop. Files have been updated with translated versions. Whitespace tool has been ran on files. >> All tests passed > > Damon Nguyen has updated the pull request incrementally with one additional commit since the last revision: > > Revert one more punctuation zh_cn translations look fine. Thanks. ------------- Marked as reviewed by weijun (Reviewer). PR: https://git.openjdk.org/jdk20/pull/116 From prappo at openjdk.org Wed Jan 25 20:06:53 2023 From: prappo at openjdk.org (Pavel Rappo) Date: Wed, 25 Jan 2023 20:06:53 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v5] In-Reply-To: References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: On Wed, 25 Jan 2023 18:00:33 GMT, Weijun Wang wrote: >> The translation tool didn't seem to translate this. Either because it couldn't or because it somehow missed it. I'm not sure which, but I'm open to replacing this with a translation suggestion you have. Or I can leave it as is. > > I'm not sure either. You can ask a javadoc expert whether this is a proper noun or just plain English. I noticed it's also not translated in the Japanese version but the German version has translated it. It's not a noun. It's an adjective that I had to synthesize for extra clarity and closeness to Java Language Specification (JLS). The English version of that entry is as follows: doclet.throwsInheritDocUnsupported=@inheritDoc is not supported for exception-type type parameters \ that are not declared by a method; document such exception types directly JLS _8.4.6. Method Throws_ defines BNF which conveniently labels elements, a list of which may appear in the `throws` clause, as `ExceptionType`. To make it more English-like and separate two otherwise consecutive occurrences of "type" in that sentence, I split the words with a hyphen and lower-cased them: exception-type. @jonathan-gibbons thoughts? ------------- PR: https://git.openjdk.org/jdk20/pull/116 From dnguyen at openjdk.org Wed Jan 25 22:02:45 2023 From: dnguyen at openjdk.org (Damon Nguyen) Date: Wed, 25 Jan 2023 22:02:45 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v8] In-Reply-To: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: > Open l10n drop. Files have been updated with translated versions. Whitespace tool has been ran on files. > All tests passed Damon Nguyen has updated the pull request incrementally with one additional commit since the last revision: Update German translation ------------- Changes: - all: https://git.openjdk.org/jdk20/pull/116/files - new: https://git.openjdk.org/jdk20/pull/116/files/9a5b45a2..35829a25 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk20&pr=116&range=07 - incr: https://webrevs.openjdk.org/?repo=jdk20&pr=116&range=06-07 Stats: 1 line in 1 file changed: 0 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jdk20/pull/116.diff Fetch: git fetch https://git.openjdk.org/jdk20 pull/116/head:pull/116 PR: https://git.openjdk.org/jdk20/pull/116 From dnguyen at openjdk.org Wed Jan 25 22:19:34 2023 From: dnguyen at openjdk.org (Damon Nguyen) Date: Wed, 25 Jan 2023 22:19:34 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v2] In-Reply-To: References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: On Wed, 25 Jan 2023 08:17:26 GMT, danielpeintner wrote: >> Damon Nguyen has updated the pull request incrementally with one additional commit since the last revision: >> >> Change German help of jar command > > src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_de.properties line 111: > >> 109: main.help.opt.main.update=\ -u, --update Ein vorhandenes JAR-Archiv aktualisieren >> 110: main.help.opt.main.extract=\ -x, --extract Benannte (oder alle) Dateien aus dem Archiv extrahieren >> 111: main.help.opt.main.describe-module=\ -d, --describe-module Gibt den Moduldeskriptor oder automatischen Modulnamen aus > > Just because I stumbled over this commit. I think the line should be translated as follows: > > `Gibt die Modulbeschreibung oder den automatischen Modulnamen aus` Resolved ------------- PR: https://git.openjdk.org/jdk20/pull/116 From jjg at openjdk.org Wed Jan 25 22:41:34 2023 From: jjg at openjdk.org (Jonathan Gibbons) Date: Wed, 25 Jan 2023 22:41:34 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v5] In-Reply-To: References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: On Wed, 25 Jan 2023 20:03:48 GMT, Pavel Rappo wrote: >> I'm not sure either. You can ask a javadoc expert whether this is a proper noun or just plain English. I noticed it's also not translated in the Japanese version but the German version has translated it. > > It's not a noun. It's an adjective that I had to synthesize for extra clarity and closeness to Java Language Specification (JLS). The English version of that entry is as follows: > > doclet.throwsInheritDocUnsupported=@inheritDoc is not supported for exception-type type parameters \ > that are not declared by a method; document such exception types directly > > JLS _8.4.6. Method Throws_ defines BNF which conveniently labels elements, a list of which may appear in the `throws` clause, as `ExceptionType`. To make it more English-like and separate two otherwise consecutive occurrences of "type" in that sentence, I split the words with a hyphen and lower-cased them: exception-type. > > @jonathan-gibbons thoughts? While the text is technically correct, it may not be as clear as it could be to all folk that will read this message for whom English is not their primary language. I would suggest translating the phrase as if it were something like @inheritDoc is not supported for type parameters that are exception types and not declared by a method and secondarily, changing the English resource to something like that as well. ------------- PR: https://git.openjdk.org/jdk20/pull/116 From dnguyen at openjdk.org Wed Jan 25 22:56:59 2023 From: dnguyen at openjdk.org (Damon Nguyen) Date: Wed, 25 Jan 2023 22:56:59 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v9] In-Reply-To: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: > Open l10n drop. Files have been updated with translated versions. Whitespace tool has been ran on files. > All tests passed Damon Nguyen has updated the pull request incrementally with one additional commit since the last revision: Replace exception-type ------------- Changes: - all: https://git.openjdk.org/jdk20/pull/116/files - new: https://git.openjdk.org/jdk20/pull/116/files/35829a25..53a86ef2 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk20&pr=116&range=08 - incr: https://webrevs.openjdk.org/?repo=jdk20&pr=116&range=07-08 Stats: 1 line in 1 file changed: 0 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jdk20/pull/116.diff Fetch: git fetch https://git.openjdk.org/jdk20 pull/116/head:pull/116 PR: https://git.openjdk.org/jdk20/pull/116 From dnguyen at openjdk.org Wed Jan 25 22:56:59 2023 From: dnguyen at openjdk.org (Damon Nguyen) Date: Wed, 25 Jan 2023 22:56:59 GMT Subject: [jdk20] RFR: 8300719: JDK 20 RDP2 L10n resource files update [v5] In-Reply-To: References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: On Wed, 25 Jan 2023 22:38:38 GMT, Jonathan Gibbons wrote: >> It's not a noun. It's an adjective that I had to synthesize for extra clarity and closeness to Java Language Specification (JLS). The English version of that entry is as follows: >> >> doclet.throwsInheritDocUnsupported=@inheritDoc is not supported for exception-type type parameters \ >> that are not declared by a method; document such exception types directly >> >> JLS _8.4.6. Method Throws_ defines BNF which conveniently labels elements, a list of which may appear in the `throws` clause, as `ExceptionType`. To make it more English-like and separate two otherwise consecutive occurrences of "type" in that sentence, I split the words with a hyphen and lower-cased them: exception-type. >> >> @jonathan-gibbons thoughts? > > While the text is technically correct, it may not be as clear as it could be to all folk that will read this message for whom English is not their primary language. > > I would suggest translating the phrase as if it were something like > > @inheritDoc is not supported for type parameters that are exception types and not declared by a method > > > and secondarily, changing the English resource to something like that as well. Updated this line with `exception-type` translated. Hopefully this will be addressed in future drops with changes to the translation tool after some bug fixes. ------------- PR: https://git.openjdk.org/jdk20/pull/116 From dnguyen at openjdk.org Thu Jan 26 22:36:39 2023 From: dnguyen at openjdk.org (Damon Nguyen) Date: Thu, 26 Jan 2023 22:36:39 GMT Subject: [jdk20] Integrated: 8300719: JDK 20 RDP2 L10n resource files update In-Reply-To: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> References: <0fuTtDy_5ZjAaxfJV75WRG8xQ76Tj-oM5hdYpG-yfkk=.a4ce241d-52a8-422a-9e1e-40de0afa78cb@github.com> Message-ID: On Tue, 24 Jan 2023 20:50:00 GMT, Damon Nguyen wrote: > Open l10n drop. Files have been updated with translated versions. Whitespace tool has been ran on files. > All tests passed This pull request has now been integrated. Changeset: a67b1e77 Author: Damon Nguyen Committer: Naoto Sato URL: https://git.openjdk.org/jdk20/commit/a67b1e77d33339f5db36c6d15bac0423a31eb5ee Stats: 1023 lines in 82 files changed: 218 ins; 114 del; 691 mod 8300719: JDK 20 RDP2 L10n resource files update Reviewed-by: cjplummer, naoto, prr, joehw, asemenyuk, jlu, lancea, ihse, jjg, weijun ------------- PR: https://git.openjdk.org/jdk20/pull/116 From jwilhelm at openjdk.org Fri Jan 27 21:08:40 2023 From: jwilhelm at openjdk.org (Jesper Wilhelmsson) Date: Fri, 27 Jan 2023 21:08:40 GMT Subject: RFR: Merge jdk20 Message-ID: <7o8i6xuRhpJrSJJg2EUyu-JPcawJAytTWS3yHX3PZd0=.0157940a-bbb2-4dc0-a645-5cde446d5052@github.com> Forwardport JDK 20 -> JDK 21 ------------- Commit messages: - Merge remote-tracking branch 'jdk20/master' into Merge_jdk20 - 8301206: Fix issue with LocaleData after JDK-8300719 - 8300953: ClassDesc::ofInternalName missing @since tag - 8300719: JDK 20 RDP2 L10n resource files update The webrevs contain the adjustments done while merging with regards to each parent branch: - master: https://webrevs.openjdk.org/?repo=jdk&pr=12267&range=00.0 - jdk20: https://webrevs.openjdk.org/?repo=jdk&pr=12267&range=00.1 Changes: https://git.openjdk.org/jdk/pull/12267/files Stats: 1078 lines in 85 files changed: 220 ins; 114 del; 744 mod Patch: https://git.openjdk.org/jdk/pull/12267.diff Fetch: git fetch https://git.openjdk.org/jdk pull/12267/head:pull/12267 PR: https://git.openjdk.org/jdk/pull/12267 From jwilhelm at openjdk.org Fri Jan 27 22:49:26 2023 From: jwilhelm at openjdk.org (Jesper Wilhelmsson) Date: Fri, 27 Jan 2023 22:49:26 GMT Subject: Integrated: Merge jdk20 In-Reply-To: <7o8i6xuRhpJrSJJg2EUyu-JPcawJAytTWS3yHX3PZd0=.0157940a-bbb2-4dc0-a645-5cde446d5052@github.com> References: <7o8i6xuRhpJrSJJg2EUyu-JPcawJAytTWS3yHX3PZd0=.0157940a-bbb2-4dc0-a645-5cde446d5052@github.com> Message-ID: On Fri, 27 Jan 2023 21:00:03 GMT, Jesper Wilhelmsson wrote: > Forwardport JDK 20 -> JDK 21 This pull request has now been integrated. Changeset: 5c59de52 Author: Jesper Wilhelmsson URL: https://git.openjdk.org/jdk/commit/5c59de52a31da937663ad2cef055213489b0516e Stats: 1078 lines in 85 files changed: 220 ins; 114 del; 744 mod Merge ------------- PR: https://git.openjdk.org/jdk/pull/12267 From ihse at openjdk.org Sat Jan 28 21:11:19 2023 From: ihse at openjdk.org (Magnus Ihse Bursie) Date: Sat, 28 Jan 2023 21:11:19 GMT Subject: RFR: 8298044: Fix hidden but significant trailing whitespace in properties files for langtools code In-Reply-To: References: Message-ID: On Fri, 2 Dec 2022 16:36:22 GMT, Magnus Ihse Bursie wrote: > According to [the specification](https://docs.oracle.com/en/java/javase/19/docs/api/java.base/java/util/Properties.html#load(java.io.Reader)) trailing whitespaces in the values of properties files are (somewhat surprisingly) actually significant. > > We have multiple files in the JDK with trailing whitespaces in the values. For most of this files, this is likely incorrect and due to oversight, but in a few cases it might actually be intended (like "The value is: "). > > After a discussion in the PR for [JDK-8295729](https://bugs.openjdk.org/browse/JDK-8295729), the consensus was to replace valid trailing spaces with the corresponding unicode sequence, `\u0020`. (And of course remove non-wanted trailing spaces.) > > Doing so has a dual benefit: > > 1) It makes it clear to everyone reading the code that there is a trailing space and it is intended > > 2) It will allow us to remove all actual trailing space characters, and turn on the corresponding check in jcheck to keep the properties files, just like all other source code files, free of trailing spaces. > > Ultimately, the call of whether a trailing space is supposed to be there, or is a bug, lies with the respective component teams owning these files. Thus I have split up the set of properties files with trailing spaces in several groups, to match the JDK teams, and open a JBS issue for each of them. This issue is for code I believe belongs with the langtools team. Bot-Keep-Alive-Ping ------------- PR: https://git.openjdk.org/jdk/pull/11487