-
Notifications
You must be signed in to change notification settings - Fork 6.1k
8164714: Constructor.newInstance creates instance of inner class with null outer class #23875
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
Conversation
… null outer class
|
👋 Welcome back liach! A progress list of the required criteria for merging this PR into |
|
@liach 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 76 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. ➡️ To integrate this PR with the above commit message to the |
Webrevs
|
…osing-this-null-check
| * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. | ||
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | ||
| * | ||
| * This code is free software; you can redistribute it and/or modify it |
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.
why changing this test?
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.
CP differences when Objects.requireNonNull is emitted
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.
then we should add the bug id to the test
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 noted https://bugs.openjdk.org/browse/JDK-8292275 also changed many tests that this patch has changed but did not add the bug id. Is the bug id only to indicate which bug's regression is a test testing against?
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.
Jtreg supports the -bug: option to run matching tests.
Adding the bugid is an aid in verifying bugs. If it was missed being added earlier it can be added now. But it is unlikely it will be missed by anyone.
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 don't think this test is associated to the inner class feature - it is just that the outputs this test is testing against is too closely tied to irrelevant implementation details.
| "java/lang/Object", | ||
| "java/lang/String", | ||
| "T6887895", | ||
| "T6887895$Test" |
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.
not sure why this test is changed
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.
Now Objects is used for requireNonNull
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.
we should then add the bug id to the test
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.
looks sensible
| /** Return tree simulating the assignment {@code this.this$n = this$n}. | ||
| */ | ||
| JCStatement initOuterThis(int pos, VarSymbol rhs) { | ||
| /** Return tree simulating null checking outer this and assigning. */ |
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.
probably this comment should state that the assignment is generated or not depending on the value of argument stores
…osing-this-null-check
…osing-this-null-check
| make.Ident(rhs)).setType(lhs.erasure(types))); | ||
| sourceExp).setType(lhs.erasure(types)); | ||
| } else { | ||
| Assert.check(nullCheckOuterThis); |
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.
This code seems repeated twice. Perhaps you could first create the expression (which could be null checked or not) and then use that expression to store in the this$0 field (if needed).
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.
Thanks for the comment. Done.
|
The compiler changes look good - and I think more generally this looks like a good enforcement to do in the generated code (also in perspective, consider what's coming in Valhalla). |
|
Thanks for the reviews! I will also deliver the release note shortly. /integrate |
|
Going to push as commit 60544a1.
Your commit was automatically rebased without conflicts. |
The Java Language Specification anticipates that inner classes always have non-null enclosing instances. It ensures the non-nullness by enforcing null checks at the use sites that provides immediately enclosing instances to inner class constructors, such as for super invocations, or an
outer.new Inner()invocation.However, the translations do not require a null check in the actual constructor, when the immediately enclosing instance is received through a mandated parameter and stored into a synthetic field or discarded. As a result, class file constructs, such as core reflection, method handles, or arbitrary class files can pass in
nullfor the immediately enclosing instance, and later execution may fail with NPE by chance if any enclosing instance is used.This patch proposes to add a null check against the "outer this" in inner class constructors that call a superclass constructor, including when the "outer this" is discarded immediately thereafter (#4966) for consistency. This null check will be emitted regardless of source or target versions. This change is considered an implementation artifact like the synthetic field that captures the enclosing instance; as a result, there is no JLS change.
The reason for this eager NPE decision is that there is no compatibility of such NPE behaviors - any evolution of the inner classes constructed with null enclosing instances may suddenly start using an enclosing instance and fail with NPE. Therefore, there's no compatibility aspect in such out-of-spec usages of passing
nullas immediately enclosing instance, and this null check can be considered such an evolution.Progress
Issues
Reviewers
Reviewing
Using
gitCheckout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/23875/head:pull/23875$ git checkout pull/23875Update a local copy of the PR:
$ git checkout pull/23875$ git pull https://git.openjdk.org/jdk.git pull/23875/headUsing Skara CLI tools
Checkout this PR locally:
$ git pr checkout 23875View PR using the GUI difftool:
$ git pr show -t 23875Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/23875.diff
Using Webrev
Link to Webrev Comment