< prev index next >

src/java.base/share/classes/sun/nio/ch/NativeSocketAddress.java

Print this page
@@ -23,68 +23,58 @@
   * questions.
   */
  
  package sun.nio.ch;
  
+ import java.lang.invoke.VarHandle;
  import java.net.Inet4Address;
  import java.net.Inet6Address;
  import java.net.InetAddress;
  import java.net.InetSocketAddress;
  import java.net.ProtocolFamily;
  import java.net.SocketException;
  import java.net.StandardProtocolFamily;
  import java.net.UnknownHostException;
  import java.nio.channels.UnsupportedAddressTypeException;
- 
+ import jdk.incubator.foreign.MemoryAddress;
+ import jdk.incubator.foreign.MemoryHandles;
+ import jdk.incubator.foreign.MemoryLayouts;
+ import jdk.incubator.foreign.MemorySegment;
  import jdk.internal.access.JavaNetInetAddressAccess;
  import jdk.internal.access.SharedSecrets;
- import jdk.internal.misc.Unsafe;
- import jdk.internal.util.ArraysSupport;
+ import jdk.internal.sys.in6_h;
+ import jdk.internal.sys.in_h;
  
  /**
   * A native socket address that is the union of struct sockaddr, struct sockaddr_in,
   * and struct sockaddr_in6.
   *
   * This class is not thread safe.
   */
- class NativeSocketAddress {
+ final class NativeSocketAddress {
      private static final JavaNetInetAddressAccess JNINA = SharedSecrets.getJavaNetInetAddressAccess();
-     private static final Unsafe UNSAFE = Unsafe.getUnsafe();
-     private static final long ARRAY_BASE_OFFSET = UNSAFE.arrayBaseOffset(byte[].class);
  
      private static final int AF_INET  = AFINET();
      private static final int AF_INET6 = AFINET6();
  
-     private static final int SIZEOF_SOCKADDR4     = sizeofSockAddr4();
-     private static final int SIZEOF_SOCKADDR6     = sizeofSockAddr6();
-     private static final int SIZEOF_SOCKETADDRESS = Math.max(SIZEOF_SOCKADDR4, SIZEOF_SOCKADDR6);
-     private static final int SIZEOF_FAMILY        = sizeofFamily();
-     private static final int OFFSET_FAMILY        = offsetFamily();
-     private static final int OFFSET_SIN4_PORT     = offsetSin4Port();
-     private static final int OFFSET_SIN4_ADDR     = offsetSin4Addr();
-     private static final int OFFSET_SIN6_PORT     = offsetSin6Port();
-     private static final int OFFSET_SIN6_ADDR     = offsetSin6Addr();
-     private static final int OFFSET_SIN6_SCOPE_ID = offsetSin6ScopeId();
-     private static final int OFFSET_SIN6_FLOWINFO = offsetSin6FlowInfo();
- 
-     // SOCKETADDRESS
-     private final long address;
- 
-     long address() {
-         return address;
+     final long address() {
+         return address.toRawLongValue();
      }
  
-     NativeSocketAddress() {
-         long base = UNSAFE.allocateMemory(SIZEOF_SOCKETADDRESS);
-         UNSAFE.setMemory(base, SIZEOF_SOCKETADDRESS, (byte) 0);
-         this.address = base;
+     private final MemorySegment segment;
+     private final MemoryAddress address;
+ 
+     private NativeSocketAddress() {
+         segment = allocateNative(in6_h.Csockaddr_in6.sizeof());
+         segment.fill((byte) 0x00);
+         address = segment.baseAddress();
      }
  
      /**
       * Allocate an array of native socket addresses.
       */
-     static NativeSocketAddress[] allocate(int count) {
+     static final NativeSocketAddress[] allocate(int count) {
          NativeSocketAddress[] array = new NativeSocketAddress[count];
          for (int i = 0; i < count; i++) {
              try {
                  array[i] = new NativeSocketAddress();
              } catch (OutOfMemoryError e) {

@@ -96,251 +86,154 @@
      }
  
      /**
       * Free all non-null native socket addresses in the given array.
       */
-     static void freeAll(NativeSocketAddress[] array) {
+     static final void freeAll(NativeSocketAddress[] array) {
          for (int i = 0; i < array.length; i++) {
              NativeSocketAddress sa = array[i];
              if (sa != null) {
-                 UNSAFE.freeMemory(sa.address);
+                 sa.segment.close();
              }
          }
      }
  
+     private static final VarHandle sin_family = MemoryHandles.asUnsigned(in_h.Csockaddr_in.sin_family$VH(), int.class);
+     private static final VarHandle sin6_family = MemoryHandles.asUnsigned(in6_h.Csockaddr_in6.sin6_family$VH(), int.class);
+ 
      /**
       * Encodes the given InetSocketAddress into this socket address.
       * @param protocolFamily protocol family
       * @param isa the InetSocketAddress to encode
       * @return the size of the socket address (sizeof sockaddr or sockaddr6)
       * @throws UnsupportedAddressTypeException if the address type is not supported
       */
-     int encode(ProtocolFamily protocolFamily, InetSocketAddress isa) {
+     final int encode(ProtocolFamily protocolFamily, InetSocketAddress isa) {
          if (protocolFamily == StandardProtocolFamily.INET) {
              // struct sockaddr
              InetAddress ia = isa.getAddress();
              if (!(ia instanceof Inet4Address))
                  throw new UnsupportedAddressTypeException();
-             putFamily(AF_INET);
-             putAddress(AF_INET, ia);
-             putPort(AF_INET, isa.getPort());
-             return SIZEOF_SOCKADDR4;
+             sin_family.set(address, AF_INET);
+             in_h.Csockaddr_in.sin_port$set(address, (short) isa.getPort());
+             in_h.Cin_addr.s_addr$set(in_h.Csockaddr_in.sin_addr$addr(address),
+                                      JNINA.addressValue((Inet4Address) ia));
+             return (int) in_h.Csockaddr_in.sizeof();
          } else {
              // struct sockaddr6
-             putFamily(AF_INET6);
-             putAddress(AF_INET6, isa.getAddress());
-             putPort(AF_INET6, isa.getPort());
-             UNSAFE.putInt(address + OFFSET_SIN6_FLOWINFO, 0);
-             return SIZEOF_SOCKADDR6;
+             sin6_family.set(address, AF_INET6);
+             in6_h.Csockaddr_in6.sin6_port$set(address, (short) isa.getPort());
+             in6_h.Csockaddr_in6.sin6_flowinfo$set(address, 0);
+             setSin6Address(in6_h.Csockaddr_in6.sin6_addr$addr(address).segment(), isa.getAddress());
+             in6_h.Csockaddr_in6.sin6_scope_id$set(address, scopeidFromAddress(isa.getAddress()));
+             return (int) in6_h.Csockaddr_in6.sizeof();
          }
      }
  
      /**
       * Return an InetSocketAddress to represent the socket address in this buffer.
       * @throws SocketException if the socket address is not AF_INET or AF_INET6
       */
-     InetSocketAddress decode() throws SocketException {
-         int family = family();
+     final InetSocketAddress decode() throws SocketException {
+         int family = (int) sin_family.get(address);
          if (family != AF_INET && family != AF_INET6)
              throw new SocketException("Socket family not recognized");
          return new InetSocketAddress(address(family), port(family));
      }
  
-     /**
-      * Find a mismatch between this and another socket address
-      * @return the byte offset of the first mismatch or -1 if no mismatch
-      */
-     private int mismatch(NativeSocketAddress other) {
-         int i = ArraysSupport.vectorizedMismatch(null,
-                 this.address,
-                 null,
-                 other.address,
-                 SIZEOF_SOCKETADDRESS,
-                 ArraysSupport.LOG2_ARRAY_BYTE_INDEX_SCALE);
-         if (i >= 0)
-             return i;
-         i = SIZEOF_SOCKETADDRESS - ~i;
-         for (; i < SIZEOF_SOCKETADDRESS; i++) {
-             if (UNSAFE.getByte(this.address + i) != UNSAFE.getByte(other.address + i)) {
-                 return i;
-             }
-         }
-         return -1;
-     }
- 
      @Override
      public boolean equals(Object other) {
-         if (other instanceof NativeSocketAddress) {
-             return mismatch((NativeSocketAddress) other) < 0;
-         } else {
+         if (!(other instanceof NativeSocketAddress))
              return false;
-         }
+         NativeSocketAddress that = (NativeSocketAddress) other;
+         return this.segment.mismatch(that.segment) == -1;
      }
  
+     private static final VarHandle BYTE_HANDLE = MemoryLayouts.JAVA_BYTE.varHandle(byte.class);
+ 
      @Override
      public int hashCode() {
          int h = 0;
-         for (int offset = 0; offset < SIZEOF_SOCKETADDRESS; offset++) {
-             h = 31 * h + UNSAFE.getByte(address + offset);
+         final MemoryAddress addr = segment.baseAddress();
+         for (int i = 0 ; i < segment.byteSize() ; i++) {
+             h = 31 * h + (byte) BYTE_HANDLE.get(addr.addOffset(i));
          }
          return h;
      }
  
      @Override
      public String toString() {
-         int family = family();
+         int family = in_h.Csockaddr_in.sin_family$get(address);
          if (family == AF_INET || family == AF_INET6) {
              return ((family == AF_INET) ? "AF_INET" : "AF_INET6")
                      + ", address=" + address(family) + ", port=" + port(family);
          } else {
              return "<unknown>";
          }
      }
  
-     /**
-      * Return the value of the sa_family field.
-      */
-     private int family() {
-         if (SIZEOF_FAMILY == 1) {
-             return UNSAFE.getByte(address + OFFSET_FAMILY);
-         } else if (SIZEOF_FAMILY == 2) {
-             return UNSAFE.getShort(address + OFFSET_FAMILY);
-         } else {
-             throw new InternalError();
-         }
-     }
- 
-     /**
-      * Stores the given family in the sa_family field.
-      */
-     private void putFamily(int family) {
-         if (SIZEOF_FAMILY == 1) {
-             UNSAFE.putByte(address + OFFSET_FAMILY, (byte) family);
-         } else if (SIZEOF_FAMILY == 2) {
-             UNSAFE.putShort(address + OFFSET_FAMILY, (short) family);
-         } else {
-             throw new InternalError();
-         }
-     }
+     private static final VarHandle sin_port = MemoryHandles.asUnsigned(in_h.Csockaddr_in.sin_port$VH(), int.class);
+     private static final VarHandle sin6_port = MemoryHandles.asUnsigned(in6_h.Csockaddr_in6.sin6_port$VH(), int.class);
  
      /**
       * Return the value of the sin_port or sin6_port field. These fields are
       * stored in network order.
       */
-     private int port(int family) {
-         byte b1, b2;
-         if (family == AF_INET) {
-             b1 = UNSAFE.getByte(address + OFFSET_SIN4_PORT);
-             b2 = UNSAFE.getByte(address + OFFSET_SIN4_PORT + 1);
-         } else {
-             b1 = UNSAFE.getByte(address + OFFSET_SIN6_PORT);
-             b2 = UNSAFE.getByte(address + OFFSET_SIN6_PORT + 1);
-         }
-         return (Byte.toUnsignedInt(b1) << 8) + Byte.toUnsignedInt(b2);
-     }
- 
-     /**
-      * Stores the given port number in the sin_port or sin6_port field. The
-      * port is stored in network order.
-      */
-     private void putPort(int family, int port) {
-         byte b1 = (byte) ((port >> 8) & 0xff);
-         byte b2 = (byte) ((port >> 0) & 0xff);
+     private final int port(int family) {
          if (family == AF_INET) {
-             UNSAFE.putByte(address + OFFSET_SIN4_PORT, b1);
-             UNSAFE.putByte(address + OFFSET_SIN4_PORT + 1, b2);
+             return (int) sin_port.get(address);
          } else {
-             UNSAFE.putByte(address + OFFSET_SIN6_PORT, b1);
-             UNSAFE.putByte(address + OFFSET_SIN6_PORT + 1, b2);
+             return (int) sin6_port.get(address);
          }
      }
  
      /**
       * Return an InetAddress to represent the value of the address in the
       * sin4_addr or sin6_addr fields. For IPv6 addresses, the Inet6Address is
       * created with the sin6_scope_id in the sockaddr_in6 structure.
       */
-     private InetAddress address(int family) {
-         int len;
-         int offset;
-         int scope_id;
+     private final InetAddress address(int family) {
          if (family == AF_INET) {
-             len = 4;
-             offset = OFFSET_SIN4_ADDR;
-             scope_id = 0;
+             return JNINA.getByAddress(
+                     in_h.Cin_addr.s_addr$get(in_h.Csockaddr_in.sin_addr$addr(address)));
          } else {
-             len = 16;
-             offset = OFFSET_SIN6_ADDR;
-             scope_id = UNSAFE.getInt(address + OFFSET_SIN6_SCOPE_ID);
-         }
-         byte[] bytes = new byte[len];
-         UNSAFE.copyMemory(null, address + offset, bytes, ARRAY_BASE_OFFSET, len);
-         try {
-             if (scope_id == 0) {
-                 return InetAddress.getByAddress(bytes);
-             } else {
-                 return Inet6Address.getByAddress(null, bytes, scope_id);
-             }
-         } catch (UnknownHostException e) {
-             throw new InternalError(e);
+             return JNINA.getByAddress(
+                     in6_h.Cin6_addr.__u6_addr$addr(in6_h.Csockaddr_in6.sin6_addr$addr(address)).segment().toByteArray(),
+                     in6_h.Csockaddr_in6.sin6_scope_id$get(address)
+             );
          }
      }
  
-     /**
-      * Stores the given InetAddress in the sin_addr or sin6_addr/sin6_scope_id
-      * fields. For IPv6 addresses, the sin6_addr will be popluated with an
-      * IPv4-mapped IPv6 address when the given InetAddress is an IPv4 address.
-      */
-     private void putAddress(int family, InetAddress ia) {
-         if (family == AF_INET) {
-             // IPv4 address
-             putAddress(address + OFFSET_SIN4_ADDR, (Inet4Address) ia);
+     private static final VarHandle ADDR_HANDLE = MemoryHandles.withOffset(MemoryLayouts.BITS_32_BE.varHandle(int.class), 12);
+     private static final void setSin6Address(MemorySegment seg, InetAddress ia) {
+         if (ia instanceof Inet4Address) { // IPv4-mapped IPv6 address
+             seg.fill((byte) 0x00).asSlice(10, 2).fill((byte) 0xFF);
+             ADDR_HANDLE.set(seg.baseAddress(), JNINA.addressValue((Inet4Address) ia));
          } else {
-             int scope_id;
-             if (ia instanceof Inet4Address) {
-                 // IPv4-mapped IPv6 address
-                 UNSAFE.setMemory(address + OFFSET_SIN6_ADDR, 10, (byte) 0);
-                 UNSAFE.putByte(address + OFFSET_SIN6_ADDR + 10, (byte) 0xff);
-                 UNSAFE.putByte(address + OFFSET_SIN6_ADDR + 11, (byte) 0xff);
-                 putAddress(address + OFFSET_SIN6_ADDR + 12, (Inet4Address) ia);
-                 scope_id = 0;
-             } else {
-                 // IPv6 address
-                 var inet6Address = (Inet6Address) ia;
-                 putAddress(address + OFFSET_SIN6_ADDR, inet6Address);
-                 scope_id = inet6Address.getScopeId();
-             }
-             UNSAFE.putInt(address + OFFSET_SIN6_SCOPE_ID, scope_id);
+             seg.copyFrom(MemorySegment.ofArray(JNINA.addressBytes((Inet6Address) ia)));
          }
      }
  
-     private static void putAddress(long address, Inet4Address ia) {
-         int ipAddress = JNINA.addressValue(ia);
-         // network order
-         UNSAFE.putByte(address + 0, (byte) ((ipAddress >>> 24) & 0xFF));
-         UNSAFE.putByte(address + 1, (byte) ((ipAddress >>> 16) & 0xFF));
-         UNSAFE.putByte(address + 2, (byte) ((ipAddress >>> 8) & 0xFF));
-         UNSAFE.putByte(address + 3, (byte) (ipAddress & 0xFF));
+     private static final int scopeidFromAddress(InetAddress ia) {
+         if (ia instanceof Inet4Address)
+             return 0;
+         return ((Inet6Address) ia).getScopeId();
      }
  
-     private static void putAddress(long address, Inet6Address ia) {
-         byte[] bytes = JNINA.addressBytes(ia);
-         UNSAFE.copyMemory(bytes, ARRAY_BASE_OFFSET, null, address, 16);
+     private static final jdk.internal.misc.Unsafe UNSAFE = jdk.internal.misc.Unsafe.getUnsafe();
+     private static final MemorySegment allocateNative(long byteSize) {
+         long base = UNSAFE.allocateMemory(byteSize);
+         return jdk.internal.foreign.NativeMemorySegmentImpl.makeNativeSegmentUnchecked(
+                 MemoryAddress.ofLong(base),
+                 byteSize,
+                 null,
+                 () -> UNSAFE.freeMemory(base),
+                 null);
      }
  
      private static native int AFINET();
      private static native int AFINET6();
-     private static native int sizeofSockAddr4();
-     private static native int sizeofSockAddr6();
-     private static native int sizeofFamily();
-     private static native int offsetFamily();
-     private static native int offsetSin4Port();
-     private static native int offsetSin4Addr();
-     private static native int offsetSin6Port();
-     private static native int offsetSin6Addr();
-     private static native int offsetSin6ScopeId();
-     private static native int offsetSin6FlowInfo();
  
      static {
          IOUtil.load();
      }
  }
< prev index next >