Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8298854

Specification of some restricted methods is incorrect

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P3 P3
    • 20
    • core-libs
    • 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 of IllegalCallerException;
      • 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)" },

            mcimadamore Maurizio Cimadamore
            mcimadamore Maurizio Cimadamore
            Jorn Vernee
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: