-
Notifications
You must be signed in to change notification settings - Fork 5.8k
8306729: Add nominal descriptors of modules and packages to Constants API #13615
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
👋 Welcome back asotona! A progress list of the required criteria for merging this PR into |
Webrevs
|
src/java.base/share/classes/java/lang/constant/PackageDescImpl.java
Outdated
Show resolved
Hide resolved
/** | ||
* Validates the correctness of a binary package name. In particular checks for the presence of | ||
* invalid characters in the name. | ||
* | ||
* @param name the package name | ||
* @return the package name passed if valid | ||
* @throws IllegalArgumentException if the package name is invalid | ||
*/ | ||
public static String validateBinaryPackageName(String name) { | ||
for (int i=0; i<name.length(); i++) { | ||
char ch = name.charAt(i); | ||
if (ch == ';' || ch == '[' || ch == '/') | ||
throw new IllegalArgumentException("Invalid package name: " + name); | ||
} | ||
return name; | ||
} | ||
|
||
/** | ||
* Validates the correctness of an internal package name. | ||
* In particular checks for the presence of invalid characters in the name. | ||
* | ||
* @param name the package name | ||
* @return the package name passed if valid | ||
* @throws IllegalArgumentException if the package name is invalid | ||
*/ | ||
public static String validateInternalPackageName(String name) { | ||
for (int i=0; i<name.length(); i++) { | ||
char ch = name.charAt(i); | ||
if (ch == ';' || ch == '[' || ch == '.') | ||
throw new IllegalArgumentException("Invalid package name: " + name); | ||
} | ||
return name; | ||
} | ||
|
||
/** | ||
* Validates the correctness of a module name. In particular checks for the presence of | ||
* invalid characters in the name. | ||
* | ||
* {@jvms 4.2.3} Module and Package Names | ||
* | ||
* @param name the module name | ||
* @return the module name passed if valid | ||
* @throws IllegalArgumentException if the module name is invalid | ||
*/ | ||
public static String validateModuleName(String name) { | ||
for (int i=name.length() - 1; i >= 0; i--) { | ||
char ch = name.charAt(i); | ||
if ((ch >= '\u0000' && ch <= '\u001F') | ||
|| ((ch == '\\' || ch == ':' || ch =='@') && (i == 0 || name.charAt(--i) != '\\'))) | ||
throw new IllegalArgumentException("Invalid module name: " + name); | ||
} | ||
return name; | ||
} |
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.
If these are performance sensitive or get used a lot, should there be an array of flags indexed by the byte/char to indicate the valid cases?
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.
It is just a range check and three escaped characters check. The range check can be implemented bit-wise and escaped check may be by a switch case, however I don't think there would be any performance benefits.
src/java.base/share/classes/java/lang/constant/ModuleDescImpl.java
Outdated
Show resolved
Hide resolved
src/java.base/share/classes/java/lang/constant/ConstantUtils.java
Outdated
Show resolved
Hide resolved
src/java.base/share/classes/java/lang/constant/package-info.java
Outdated
Show resolved
Hide resolved
Note that other |
Records were only added in Java 16; the constant API was added in 12, so this is not a reason not to use records. But performing validation in constructors is better than in factory methods, to avoid code paths that potentially create invalid instances. |
Performing validation in constructors I see as a blocker for potential performance optimisations from trusted code within the Custom Records are very well designed exactly for this purpose and I'm not aware of any reason to don't use them. |
BTW: for example |
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.
A side note: I notice that the type names are linked with @linkplain
in this package mixed with some @link
. I'm not sure if it's intentional as type names are generally used @link
or @code
.
src/java.base/share/classes/java/lang/constant/PackageDesc.java
Outdated
Show resolved
Hide resolved
src/java.base/share/classes/java/lang/constant/PackageDesc.java
Outdated
Show resolved
Hide resolved
src/java.base/share/classes/java/lang/constant/PackageDesc.java
Outdated
Show resolved
Hide resolved
src/java.base/share/classes/java/lang/constant/PackageDesc.java
Outdated
Show resolved
Hide resolved
src/java.base/share/classes/java/lang/constant/PackageDesc.java
Outdated
Show resolved
Hide resolved
src/java.base/share/classes/java/lang/constant/package-info.java
Outdated
Show resolved
Hide resolved
Co-authored-by: Mandy Chung <mandy.chung@oracle.com>
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 wonder if packageName()
and packageInternalName()
methods can simply be name()
and internalName()
as the type name is PackageDesc
and package
prefix seems to be unnecessary. Similarly, moduleName()
can be name()
. Have this be discussed and rejected?
src/java.base/share/classes/java/lang/constant/PackageDesc.java
Outdated
Show resolved
Hide resolved
src/java.base/share/classes/java/lang/constant/PackageDesc.java
Outdated
Show resolved
Hide resolved
src/java.base/share/classes/java/lang/constant/PackageDesc.java
Outdated
Show resolved
Hide resolved
src/java.base/share/classes/java/lang/constant/PackageDesc.java
Outdated
Show resolved
Hide resolved
src/java.base/share/classes/java/lang/constant/PackageDesc.java
Outdated
Show resolved
Hide resolved
Have we considered moving the Impl classes into a non-public area such as |
Co-authored-by: Mandy Chung <mandy.chung@oracle.com>
I've searched the history of Classfile API discussions and it actually wasn't discussed. |
I don't see much of a problem to keep the non-public classes in |
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 update. Two typos. please do make docs
to verify the output.
src/java.base/share/classes/java/lang/constant/PackageDesc.java
Outdated
Show resolved
Hide resolved
src/java.base/share/classes/java/lang/constant/PackageDesc.java
Outdated
Show resolved
Hide resolved
char ch = name.charAt(i); | ||
if ((ch >= '\u0000' && ch <= '\u001F') | ||
|| ((ch == '\\' || ch == ':' || ch =='@') && (i == 0 || name.charAt(--i) != '\\'))) | ||
throw new IllegalArgumentException("Invalid module name: " + name); |
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.
test/jdk/java/lang/module/ModuleNames.java has tables of legal and illegal module names, including tests that escape backslash, @, and :. It might be useful to run these tests on this method.
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've updated ModuleDescTest
with all the positive and negative cases from test/jdk/java/lang/module/ModuleNames.java
, except for the empty name.
Thanks for the review.
I keep pondering if this API should allow creating JLS 6.5.3. Meaning of Module Names and Package Names
The module system will reject a The module system rejects the unnamed package in a named module. |
Co-authored-by: Mandy Chung <mandy.chung@oracle.com>
Discussed with @briangoetz offline. We can let For example, if we had a constructor in So this PR is good to go. |
@asotona 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 147 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 |
/integrate |
Going to push as commit c8f3756.
Your commit was automatically rebased without conflicts. |
Constants API already provides models for all loadable constants to help programs manipulating class files and modelling bytecode instructions. However no models of module and package constants are provided by Constants API. Every program manipulating class files must implement own models and validation of modules and packages constants.
This pul request adds
java.lang.constant.ModuleDesc
andjava.lang.constant.PackageDesc
to the Constants API.Classfile API will follow up and remove its internal implementations of
PackageDesc
andModuleDesc
.Please review this pull request and attached CSR.
Thank you,
Adam
Progress
Issues
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/13615/head:pull/13615
$ git checkout pull/13615
Update a local copy of the PR:
$ git checkout pull/13615
$ git pull https://git.openjdk.org/jdk.git pull/13615/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 13615
View PR using the GUI difftool:
$ git pr show -t 13615
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/13615.diff
Webrev
Link to Webrev Comment