-
CSR
-
Resolution: Approved
-
P3
-
None
-
minimal
-
This is about rectifying some minor javadoc inconsistencies. The underlying implementation is unchanged.
-
Java API
-
SE
Summary
The javadoc for restricted methods is inconsistent and should be rectified.
Problem
Some methods in the Foreign Function & Memory API are restricted. Restricted method can be called, with a warning, unless a JDK specific command line option (--enable-native-access) is passed on the command line. In the new iteration of JEP 434, we have updated the package-level description of restricted methods to spell out more clearly that the command line option is JDK specific (by moving this text into an @implNote
).
Sadly, all the @throws
clauses of the restricted methods in the FFM API still refer to the command line option. Moreover, one method (ValueLayout.OfAddess::asUnbounded) is missing the @throws clause
, and another method (an overload of MemorySegment::ofAddress
) is missing the restricted method narrative text.
Solution
The solution is to make the javadoc for all restricted methods consistent:
- include a small one-liner
@throws
clause re. possibility ofIllegalCallerException
; - Keep the discussion re.
--enable-native-access
in an implementation note in the package-level javadoc; - Add narrative text in all restricted methods; and
- Add throws clauses to all restricted methods.
Specification
A diff of the changes is included below:
diff --git a/src/java.base/share/classes/java/lang/foreign/Linker.java b/src/java.base/share/classes/java/lang/foreign/Linker.java
index 4789292de03..6e83806a038 100644
--- a/src/java.base/share/classes/java/lang/foreign/Linker.java
+++ b/src/java.base/share/classes/java/lang/foreign/Linker.java
@@ -180,9 +180,7 @@ public sealed interface Linker permits AbstractLinker {
*
* @return a linker for the ABI associated with the OS and processor where the Java runtime is currently executing.
* @throws UnsupportedOperationException if the underlying native platform is not supported.
- * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
- * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or
- * {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
+ * @throws IllegalCallerException If the caller is in a module that does not have native access enabled.
*/
@CallerSensitive
static Linker nativeLinker() {
diff --git a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java
index 76c2de64242..a1da55b8c0e 100644
--- a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java
+++ b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java
@@ -1065,9 +1065,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
* @param byteSize the size (in bytes) of the returned native segment.
* @return a zero-length native segment with the given address and size.
* @throws IllegalArgumentException if {@code byteSize < 0}.
- * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
- * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or
- * {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
+ * @throws IllegalCallerException If the caller is in a module that does not have native access enabled.
*/
@CallerSensitive
static MemorySegment ofAddress(long address, long byteSize) {
@@ -1088,7 +1086,10 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
* {@snippet lang = java:
* ofAddress(address, byteSize, scope, null);
*}
- *
+ * This method is <a href="package-summary.html#restricted"><em>restricted</em></a>.
+ * Restricted methods are unsafe, and, if used incorrectly, their use might crash
+ * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on
+ * restricted methods, and use safe and supported functionalities, where possible.
* @param address the returned segment's address.
* @param byteSize the desired size.
* @param scope the scope associated with the returned native segment.
@@ -1097,9 +1098,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
* @throws IllegalStateException if {@code scope} is not {@linkplain SegmentScope#isAlive() alive}.
* @throws WrongThreadException if this method is called from a thread {@code T},
* such that {@code scope.isAccessibleBy(T) == false}.
- * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
- * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or
- * {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
+ * @throws IllegalCallerException If the caller is in a module that does not have native access enabled.
*/
@CallerSensitive
@ForceInline
@@ -1140,9 +1139,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
* @throws IllegalStateException if {@code scope} is not {@linkplain SegmentScope#isAlive() alive}.
* @throws WrongThreadException if this method is called from a thread {@code T},
* such that {@code scope.isAccessibleBy(T) == false}.
- * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
- * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or
- * {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
+ * @throws IllegalCallerException If the caller is in a module that does not have native access enabled.
*/
@CallerSensitive
static MemorySegment ofAddress(long address, long byteSize, SegmentScope scope, Runnable cleanupAction) {
diff --git a/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java b/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java
index 50575f6b106..b2c5711922a 100644
--- a/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java
+++ b/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java
@@ -189,9 +189,7 @@ public interface SymbolLookup {
* @param scope the scope associated with symbols obtained from the returned lookup.
* @return a new symbol lookup suitable to find symbols in a library with the given name.
* @throws IllegalArgumentException if {@code name} does not identify a valid library.
- * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
- * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
- * {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
+ * @throws IllegalCallerException If the caller is in a module that does not have native access enabled.
*/
@CallerSensitive
static SymbolLookup libraryLookup(String name, SegmentScope scope) {
@@ -215,9 +213,7 @@ public interface SymbolLookup {
* @param scope the scope associated with symbols obtained from the returned lookup.
* @return a new symbol lookup suitable to find symbols in a library with the given path.
* @throws IllegalArgumentException if {@code path} does not point to a valid library.
- * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
- * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
- * {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
+ * @throws IllegalCallerException If the caller is in a module that does not have native access enabled.
*/
@CallerSensitive
static SymbolLookup libraryLookup(Path path, SegmentScope scope) {
diff --git a/src/java.base/share/classes/java/lang/foreign/VaList.java b/src/java.base/share/classes/java/lang/foreign/VaList.java
index 0f6dd9fef47..4d8fab97575 100644
--- a/src/java.base/share/classes/java/lang/foreign/VaList.java
+++ b/src/java.base/share/classes/java/lang/foreign/VaList.java
@@ -247,9 +247,7 @@ public sealed interface VaList permits WinVaList, SysVVaList, LinuxAArch64VaList
* @throws WrongThreadException if this method is called from a thread {@code T},
* such that {@code scope.isAccessibleBy(T) == false}.
* @throws UnsupportedOperationException if the underlying native platform is not supported.
- * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
- * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or
- * {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
+ * @throws IllegalCallerException If the caller is in a module that does not have native access enabled.
*/
@CallerSensitive
static VaList ofAddress(long address, SegmentScope scope) {
diff --git a/src/java.base/share/classes/java/lang/foreign/ValueLayout.java b/src/java.base/share/classes/java/lang/foreign/ValueLayout.java
index f9a62419598..9ff1f08d7b9 100644
--- a/src/java.base/share/classes/java/lang/foreign/ValueLayout.java
+++ b/src/java.base/share/classes/java/lang/foreign/ValueLayout.java
@@ -424,6 +424,7 @@ public sealed interface ValueLayout extends MemoryLayout {
* restricted methods, and use safe and supported functionalities, where possible.
*
* @return an unbounded address layout with same characteristics as this layout.
+ * @throws IllegalCallerException If the caller is in a module that does not have native access enabled.
* @see #isUnbounded()
*/
@CallerSensitive
diff --git a/test/jdk/java/foreign/handles/lookup_module/handle/lookup/MethodHandleLookup.java b/test/jdk/java/foreign/handles/lookup_module/handle/lookup/MethodHandleLookup.java
index 6bd7121c651..62014baf8af 100644
--- a/test/jdk/java/foreign/handles/lookup_module/handle/lookup/MethodHandleLookup.java
+++ b/test/jdk/java/foreign/handles/lookup_module/handle/lookup/MethodHandleLookup.java
@@ -50,9 +50,15 @@ public class MethodHandleLookup {
return new Object[][]{
{ MethodHandles.lookup().findStatic(Linker.class, "nativeLinker",
MethodType.methodType(Linker.class)), "Linker::nativeLinker" },
+ { MethodHandles.lookup().findStatic(MemorySegment.class, "ofAddress",
+ MethodType.methodType(MemorySegment.class, long.class, long.class)),
+ "MemorySegment::ofAddress/2" },
{ MethodHandles.lookup().findStatic(MemorySegment.class, "ofAddress",
MethodType.methodType(MemorySegment.class, long.class, long.class, SegmentScope.class)),
- "MemorySegment::ofAddressNative" },
+ "MemorySegment::ofAddress/3" },
+ { MethodHandles.lookup().findStatic(MemorySegment.class, "ofAddress",
+ MethodType.methodType(MemorySegment.class, long.class, long.class, SegmentScope.class, Runnable.class)),
+ "MemorySegment::ofAddress/4" },
{ MethodHandles.lookup().findStatic(SymbolLookup.class, "libraryLookup",
MethodType.methodType(SymbolLookup.class, String.class, SegmentScope.class)),
"SymbolLookup::libraryLookup(String)" },
- csr of
-
JDK-8298797 Specification of some restricted methods is incorrect
-
- Resolved
-