-
Notifications
You must be signed in to change notification settings - Fork 5.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
8015831: Add lint check for calling overridable methods from a constructor #11874
Conversation
Warning B duplicates warning A if the stack trace of A is a prefix of the stack trace of B. For example, if constructor Foo(int x) has a leak, and constructor Foo() invokes this(0), then emitting a warning for Foo() would be redundant.
…structor") annotations.
Agreed - I originally thought this was harder but actually the containing module is easy to access. I've prototyped this now in a new |
FYI, based on discussions & feedback I'm making the warning less aggressive. We'll now only warn when a subclass could exist outside of the current module, instead of outside the current compilation unit (i.e., source file). FWIW this reduces the warning count in the JDK itself from 2093 to 1334 (36% reduction). In the future we can consider tightening this up, but for now this will be a more conservative way to introduce the new warning to the world. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm OK with the last version, @archiecobbs thanks a lot for the patience and continuous effort
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the latest version too with improved boundary detection.
Moving forward, if we plan to add other complex analyses like this one, we should maybe think to add them as a separate compilation step, rather than adding them in Flow (which might be problematic as parts of Flow are also used as part of Attr. e.g. to infer lambda thrown types).
Thanks for the careful reviews.
Agreed. Perhaps there could be a new phase of compliation |
The CSR also needs a review from a compiler-dev engineer as well if anyone is interested... thanks. |
some comments on the CSR:
|
@archiecobbs This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply add a new comment to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration! |
/pingbot |
@archiecobbs Unknown command |
@archiecobbs This change now passes all automated pre-integration checks. ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details. After integration, the commit message for the final commit will be:
You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed. At the time when this comment was updated there had been 896 new commits pushed to the
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details. As you do not have Committer status in this project an existing Committer must agree to sponsor your change. Possible candidates are the reviewers of this PR (@magicus, @vicente-romero-oracle, @mcimadamore) but any other Committer may sponsor as well. ➡️ To flag this PR as ready for integration with the above commit message, type |
/integrate |
@archiecobbs |
/sponsor |
Going to push as commit 8f5bb53.
Your commit was automatically rebased without conflicts. |
@vicente-romero-oracle @archiecobbs Pushed as commit 8f5bb53. 💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored. |
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 classA
when the compiler detects that the following situation is in theory possible:B extends A
exists, andB
is defined in a separate source file (i.e., compilation unit)B()
ofB
invokesA()
as its superclass constructorA()
, some non-static method ofB.foo()
could get invoked, perhaps indirectlyIn the above scenario,
B.foo()
would execute beforeA()
has returned and beforeB()
has performed any initialization. To the extentB.foo()
accesses any fields ofB
- 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)
invokesputAll()
andput()
.More details and a couple of motivating examples are given in an included doc file that these
@implNote
's link to. See also the recent thread onamber-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 exceptingthis-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")
Progress
Issues
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk pull/11874/head:pull/11874
$ git checkout pull/11874
Update a local copy of the PR:
$ git checkout pull/11874
$ git pull https://git.openjdk.org/jdk pull/11874/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 11874
View PR using the GUI difftool:
$ git pr show -t 11874
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/11874.diff