JDK-8283527 : Update java.nio buffers to use sealed classes
  • Type: CSR
  • Component: core-libs
  • Sub-Component: java.nio
  • Priority: P4
  • Status: Draft
  • Resolution: Unresolved
  • Fix Versions: 19
  • Submitted: 2022-03-22
  • Updated: 2022-03-22
Related Reports
CSR :  
Relates :  
Description
Summary
-------

Change the `java.nio.Buffer` hierarchy to be sealed.

Problem
-------

Buffers are not sealed which it would be appropriate for them to be as they are a closed abstraction.

Solution
--------

In the `java.nio.Buffer` class tree, convert the subclassed buffer classes to sealed and the non-subclassed classes to final.

Specification
-------------

    --- a/src/java.base/share/classes/java/nio/Buffer.java
    +++ b/src/java.base/share/classes/java/nio/Buffer.java
    @@ -189,11 +189,13 @@
      * @author Mark Reinhold
      * @author JSR-51 Expert Group
      * @since 1.4
      */
     
    -public abstract class Buffer {
    +public abstract sealed class Buffer
    +    permits ByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer,
    +        LongBuffer, ShortBuffer {
         // Cached unsafe-access object
         static final Unsafe UNSAFE = Unsafe.getUnsafe();
     
         static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess();
     
    --- a/src/java.base/share/classes/java/nio/ByteBufferAs-X-Buffer.java.template
    +++ b/src/java.base/share/classes/java/nio/ByteBufferAs-X-Buffer.java.template
    @@ -29,12 +29,20 @@
     
     import java.util.Objects;
     import jdk.internal.access.foreign.MemorySegmentProxy;
     import jdk.internal.misc.Unsafe;
     
    +#if[rw]
    +sealed
    +#else[rw]
    +final
    +#end[rw]
     class ByteBufferAs$Type$Buffer$RW$$BO$                  // package-private
         extends {#if[ro]?ByteBufferAs}$Type$Buffer{#if[ro]?$BO$}
    +#if[rw]
    +    permits ByteBufferAs$Type$BufferR$BO$
    +#end[rw]
     {
     
     #if[rw]
     
         protected final ByteBuffer bb;
    
    --- a/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template
    +++ b/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template
    @@ -35,17 +35,25 @@
     import jdk.internal.misc.VM;
     import jdk.internal.ref.Cleaner;
     import sun.nio.ch.DirectBuffer;
     
     
    +#if[rw]
    +sealed
    +#else[rw]
    +final
    +#end[rw]
     class Direct$Type$Buffer$RW$$BO$
     #if[rw]
         extends {#if[byte]?Mapped$Type$Buffer:$Type$Buffer}
     #else[rw]
         extends Direct$Type$Buffer$BO$
     #end[rw]
         implements DirectBuffer
    +#if[rw]
    +    permits Direct$Type$BufferR$BO$
    +#end[rw]
     {
     
     #if[rw]
     
         // Cached unaligned-access capability
    
    --- a/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template
    +++ b/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template
    @@ -38,12 +38,20 @@
      * read/write class, overriding the mutation methods to throw a {@link
      * ReadOnlyBufferException} and overriding the view-buffer methods to return an
      * instance of this class rather than of the superclass.
     #end[rw]
      */
    +#if[rw]
    +sealed
    +#else[rw]
    +final
    +#end[rw]
     class Heap$Type$Buffer$RW$
         extends {#if[ro]?Heap}$Type$Buffer
    +#if[rw]
    +    permits Heap$Type$BufferR
    +#end[rw]
     {
     #if[rw]
         // Cached array base offset
         private static final long ARRAY_BASE_OFFSET = UNSAFE.arrayBaseOffset($type$[].class);
     
    --- a/src/java.base/share/classes/java/nio/MappedByteBuffer.java
    +++ b/src/java.base/share/classes/java/nio/MappedByteBuffer.java
    @@ -68,12 +68,13 @@
      * @author Mark Reinhold
      * @author JSR-51 Expert Group
      * @since 1.4
      */
     
    -public abstract class MappedByteBuffer
    +public abstract sealed class MappedByteBuffer
         extends ByteBuffer
    +    permits DirectByteBuffer
     {
     
         // This is a little bit backwards: By rights MappedByteBuffer should be a
         // subclass of DirectByteBuffer, but to keep the spec clear and simple, and
         // for optimization purposes, it's easier to do it the other way around.
    --- a/src/java.base/share/classes/java/nio/StringCharBuffer.java
    
    +++ b/src/java.base/share/classes/java/nio/StringCharBuffer.java
    @@ -27,11 +27,11 @@
     
     import java.util.Objects;
     
     // ## If the sequence is a string, use reflection to share its array
     
    -class StringCharBuffer                                  // package-private
    +final class StringCharBuffer                                  // package-private
         extends CharBuffer
     {
         CharSequence str;
     
         StringCharBuffer(CharSequence s, int start, int end) { // package-private
    
    --- a/src/java.base/share/classes/java/nio/X-Buffer.java.template
    +++ b/src/java.base/share/classes/java/nio/X-Buffer.java.template
    @@ -262,13 +262,23 @@
      * @author Mark Reinhold
      * @author JSR-51 Expert Group
      * @since 1.4
      */
     
    -public abstract class $Type$Buffer
    +public abstract sealed class $Type$Buffer
         extends Buffer
         implements Comparable<$Type$Buffer>{#if[char]?, Appendable, CharSequence, Readable}
    +    permits
    +#if[byte]
    +    Heap$Type$Buffer, MappedByteBuffer
    +#else[byte]
    +#if[char]
    +    StringCharBuffer,
    +#end[char]
    +    Heap$Type$Buffer, Direct$Type$BufferS, Direct$Type$BufferU,
    +    ByteBufferAs$Type$BufferB, ByteBufferAs$Type$BufferL
    +#end[byte]
     {
         // Cached array base offset
         private static final long ARRAY_BASE_OFFSET = UNSAFE.arrayBaseOffset($type$[].class);
     
         // These fields are declared here rather than in Heap-X-Buffer in order to