Removed NioBits and NioBitsFields.  Plus improving some javadocs and a
few other minor tweaks.
diff --git a/datasketches-memory-java17/src/main/java/module-info.java b/datasketches-memory-java17/src/main/java/module-info.java
new file mode 100644
index 0000000..ed6cf80
--- /dev/null
+++ b/datasketches-memory-java17/src/main/java/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+@SuppressWarnings("javadoc")
+module org.apache.datasketches.memory {
+    requires java.base;
+    requires java.logging;
+    requires jdk.unsupported;
+    requires jdk.incubator.foreign;
+    exports org.apache.datasketches.memory.internal;
+}
diff --git a/datasketches-memory-java11/src/main/java/org/apache/datasketches/memory/internal/NioBitsFields.java b/datasketches-memory-java17/src/main/java/org/apache/datasketches/memory/internal/Dummy.java
similarity index 62%
rename from datasketches-memory-java11/src/main/java/org/apache/datasketches/memory/internal/NioBitsFields.java
rename to datasketches-memory-java17/src/main/java/org/apache/datasketches/memory/internal/Dummy.java
index 633c685..aefdcba 100644
--- a/datasketches-memory-java11/src/main/java/org/apache/datasketches/memory/internal/NioBitsFields.java
+++ b/datasketches-memory-java17/src/main/java/org/apache/datasketches/memory/internal/Dummy.java
@@ -20,14 +20,8 @@
 package org.apache.datasketches.memory.internal;
 
 /**
- * Extracts version-dependent field names into standalone class.
- * Some field names in the VM internal class have changed in
- * later versions. The appropriate class will be loaded by the class loader
- * depending on the Java version that is used.
- * For more information, see: https://openjdk.java.net/jeps/238
+ * Temporary class & placeholder. It may not be needed.
  */
-class NioBitsFields {
-    static String COUNT_FIELD_NAME = "COUNT";
-    static String RESERVED_MEMORY_FIELD_NAME = "RESERVED_MEMORY";
-    static String TOTAL_CAPACITY_FIELD_NAME = "TOTAL_CAPACITY";
+public class Dummy {
+
 }
diff --git a/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/NioBitsTest.java b/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/NioBitsTest.java
deleted file mode 100644
index b0fa1e7..0000000
--- a/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/NioBitsTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.datasketches.memory.test;
-
-import static org.testng.Assert.assertEquals;
-
-import org.testng.annotations.Test;
-
-/**
- * @author Lee Rhodes
- */
-@SuppressWarnings("javadoc")
-public class NioBitsTest {
-
-  @Test
-  public void checkGetAtomicFields() {
-    //testing this beyond 2GB may not work on JVMs < 8GB.
-    //This should be checked manually
-   // long cap = 1024L + Integer.MAX_VALUE;
-    long cap = 1L << 10;
-    printStats();
-    ReflectUtil.reserveMemory(cap, cap);
-    printStats();
-    ReflectUtil. unreserveMemory(cap, cap);
-    printStats();
-  }
-
-  @Test
-  public void checkPageCount() {
-    assertEquals(ReflectUtil.pageCount(0), 0);
-    assertEquals(ReflectUtil.pageCount(1), 1);
-  }
-
-  private static void printStats() {
-    long count = ReflectUtil.getDirectAllocationsCount();
-    long resMem = ReflectUtil.getReservedMemory();
-    long totCap = ReflectUtil.getTotalCapacity();
-    String s = String.format("%,10d\t%,15d\t%,15d", count, resMem, totCap);
-    println(s);
-  }
-
-  @Test
-  public void printlnTest() {
-    println("PRINTING: " + this.getClass().getName());
-  }
-
-  /**
-   * @param s value to print
-   */
-  static void println(final String s) {
-    //System.out.println(s); //disable here
-  }
-
-}
diff --git a/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/ReflectUtil.java b/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/ReflectUtil.java
index 85aa569..79bdc39 100644
--- a/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/ReflectUtil.java
+++ b/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/ReflectUtil.java
@@ -36,13 +36,10 @@
   static final Class<?> BASE_STATE;
   static final Class<?> BASE_WRITABLE_MEMORY_IMPL;
   static final Class<?> ALLOCATE_DIRECT_MAP;
-  static final Class<?> NIO_BITS;
+  //static final Class<?> UNSAFE_UTIL;
 
   static final Method CHECK_VALID; //BaseStateImpl
-  static final Method GET_DIRECT_ALLOCATIONS_COUNT; //NioBits
   static final Method GET_NATIVE_BASE_OFFSET; //BaseStateImpl
-  static final Method GET_RESERVED_MEMORY; //NioBits
-  static final Method GET_TOTAL_CAPACITY; //NioBits
   static final Method GET_UNSAFE_OBJECT; //BaseStateImpl
   static final Method IS_BB_TYPE; //BaseStateImpl
   static final Method IS_BUFFER_TYPE; //BaseStateImpl
@@ -54,9 +51,6 @@
   static final Method IS_NON_NATIVE_TYPE; //BaseStateImpl
   static final Method IS_READ_ONLY_TYPE; //BaseStateImpl
   static final Method IS_REGION_TYPE; //BaseStateImpl
-  static final Method PAGE_COUNT; //NioBits
-  static final Method RESERVE_MEMORY; //NioBits
-  static final Method UNRESERVE_MEMORY; //NioBits
   static final Method WRAP_DIRECT; //BaseWritableMemoryImpl
 
   static {
@@ -66,19 +60,10 @@
         getClass("org.apache.datasketches.memory.internal.BaseWritableMemoryImpl");
     ALLOCATE_DIRECT_MAP =
         getClass("org.apache.datasketches.memory.internal.AllocateDirectMap");
-    NIO_BITS =
-        getClass("org.apache.datasketches.memory.internal.NioBits");
-
     CHECK_VALID =
         getMethod(BASE_STATE, "checkValid", (Class<?>[])null); //not static
-    GET_DIRECT_ALLOCATIONS_COUNT =
-        getMethod(NIO_BITS, "getDirectAllocationsCount", (Class<?>[])null); //static
     GET_NATIVE_BASE_OFFSET =
         getMethod(BASE_STATE, "getNativeBaseOffset", (Class<?>[])null);
-    GET_RESERVED_MEMORY =
-        getMethod(NIO_BITS, "getReservedMemory", (Class<?>[])null); //static
-    GET_TOTAL_CAPACITY =
-        getMethod(NIO_BITS, "getTotalCapacity", (Class<?>[])null); //static
     GET_UNSAFE_OBJECT =
         getMethod(BASE_STATE, "getUnsafeObject", (Class<?>[])null); //not static
     IS_BB_TYPE =
@@ -101,12 +86,6 @@
         getMethod(BASE_STATE, "isReadOnlyType", (Class<?>[])null); //not static
     IS_REGION_TYPE =
         getMethod(BASE_STATE, "isRegionType", (Class<?>[])null); //not static
-    PAGE_COUNT =
-        getMethod(NIO_BITS, "pageCount", long.class); //static
-    RESERVE_MEMORY =
-        getMethod(NIO_BITS, "reserveMemory", long.class, long.class); //static
-    UNRESERVE_MEMORY =
-        getMethod(NIO_BITS, "unreserveMemory", long.class, long.class); //static
     WRAP_DIRECT =
         getMethod(BASE_WRITABLE_MEMORY_IMPL,
             "wrapDirect", long.class, ByteOrder.class, MemoryRequestServer.class);  //static method
@@ -220,14 +199,6 @@
     }
   }
 
-  static long getDirectAllocationsCount() {
-    try {
-      return (long) GET_DIRECT_ALLOCATIONS_COUNT.invoke(null);
-    } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
-      throw new RuntimeException(e);
-    }
-  }
-
   static long getNativeBaseOffset(final Object target) {
     try {
       return (long) GET_NATIVE_BASE_OFFSET.invoke(target);
@@ -236,22 +207,6 @@
     }
   }
 
-  static long getReservedMemory() {
-    try {
-      return (long) GET_RESERVED_MEMORY.invoke(null);
-    } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
-      throw new RuntimeException(e);
-    }
-  }
-
-  static long getTotalCapacity() {
-    try {
-      return (long) GET_TOTAL_CAPACITY.invoke(null);
-    } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
-      throw new RuntimeException(e);
-    }
-  }
-
   static Object getUnsafeObject(final Object target) {
     try {
       return GET_UNSAFE_OBJECT.invoke(target);
@@ -340,28 +295,4 @@
     }
   }
 
-  static int pageCount(final long bytes) {
-    try {
-      return (int) PAGE_COUNT.invoke(null, bytes);
-    } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
-      throw new RuntimeException(e);
-    }
-  }
-
-  static void reserveMemory(final long allocationSize, final long capacity) {
-    try {
-     RESERVE_MEMORY.invoke(null, allocationSize, capacity);
-    } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
-      throw new RuntimeException(e);
-    }
-  }
-
-  static void unreserveMemory(final long allocationSize, final long capacity) {
-    try {
-      UNRESERVE_MEMORY.invoke(null, allocationSize, capacity);
-    } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
-      throw new RuntimeException(e);
-    }
-  }
-
 }
diff --git a/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/ZeroCapacityTest.java b/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/ZeroCapacityTest.java
index 28914b3..aa491b0 100644
--- a/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/ZeroCapacityTest.java
+++ b/datasketches-memory-java8-tests/src/test/java/org/apache/datasketches/memory/test/ZeroCapacityTest.java
@@ -19,8 +19,6 @@
 
 package org.apache.datasketches.memory.test;
 
-import static org.testng.Assert.assertEquals;
-
 import java.nio.ByteBuffer;
 
 import org.apache.datasketches.memory.Memory;
@@ -38,13 +36,12 @@
   @SuppressWarnings({ "unused", "resource" })
   @Test
   public void checkZeroCapacity() throws Exception {
-    WritableMemory wmem = WritableMemory.allocate(0);
-    assertEquals(wmem.getCapacity(), 0);
-
-    Memory mem1 = Memory.wrap(new byte[0]);
-    Memory mem2 = Memory.wrap(ByteBuffer.allocate(0));
-    Memory mem3 = Memory.wrap(ByteBuffer.allocateDirect(0));
-    Memory reg = mem3.region(0, 0);
+    WritableMemory.allocate(0);
+    Memory.wrap(new byte[0]);
+    Memory.wrap(ByteBuffer.allocate(0));
+    Memory.wrap(ByteBuffer.allocateDirect(0));
+    Memory mem = WritableMemory.allocate(8);
+    mem.region(0, 0);
     WritableHandle wh = null;
     try {
       wh = WritableMemory.allocateDirect(0);
@@ -55,16 +52,4 @@
     }
   }
 
-  @Test
-  public void printlnTest() {
-    //println("PRINTING: "+this.getClass().getName());
-  }
-
-  /**
-   * @param s value to print
-   */
-  static void println(String s) {
-    //System.out.println(s); //disable here
-  }
-
 }
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/Memory.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/Memory.java
index 71ac7a5..f25de32 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/Memory.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/Memory.java
@@ -62,7 +62,7 @@
   static Memory wrap(ByteBuffer byteBuffer, ByteOrder byteOrder) {
     Objects.requireNonNull(byteBuffer, "byteBuffer must not be null");
     Objects.requireNonNull(byteOrder, "byteOrder must not be null");
-    negativeCheck(byteBuffer.capacity(), "byteBuffer");
+    negativeCheck(byteBuffer.capacity(), "byteBuffer.capacity()");
     return BaseWritableMemoryImpl.wrapByteBuffer(byteBuffer, true, byteOrder, null);
   }
 
@@ -81,9 +81,9 @@
 
   /**
    * Maps the specified portion of the given file into <i>Memory</i> for read operations.
-   * @param file the given file to map. It must be non-null and readable.
+   * @param file the given file to map. It must be non-null,readable and length &ge; 0.
    * @param fileOffsetBytes the position in the given file in bytes. It must not be negative.
-   * @param capacityBytes the size of the mapped memory. It must not be negative.
+   * @param capacityBytes the size of the mapped memory. It must be &ge; 0.
    * @param byteOrder the byte order to be used for the mapped memory. It must be non-null.
    * @return <i>MapHandle</i> for managing the mapped memory.
    * Please read Javadocs for {@link Handle}.
@@ -92,6 +92,7 @@
     Objects.requireNonNull(file, "file must be non-null.");
     Objects.requireNonNull(byteOrder, "byteOrder must be non-null.");
     if (!file.canRead()) { throw new IllegalArgumentException("file must be readable."); }
+    negativeCheck(file.length(), "file.length()");
     negativeCheck(fileOffsetBytes, "fileOffsetBytes");
     negativeCheck(capacityBytes, "capacityBytes");
     return (MapHandle) BaseWritableMemoryImpl.wrapMap(file, fileOffsetBytes, capacityBytes, true, byteOrder);
@@ -164,7 +165,7 @@
   //ACCESS PRIMITIVE HEAP ARRAYS for readOnly
   /**
    * Wraps the given primitive array for read operations assuming native byte order.
-   * @param array the given primitive array.
+   * @param array the given primitive array. It must be non-null and with length &ge; 0.
    * @return a new <i>Memory</i> for read operations
    */
   static Memory wrap(byte[] array) {
@@ -184,9 +185,9 @@
 
   /**
    * Wraps the given primitive array for read operations with the given byte order.
-   * @param array the given primitive array.
+   * @param array the given primitive array. It must be non-null and length &ge; 0.
    * @param offsetBytes the byte offset into the given array
-   * @param lengthBytes the number of bytes to include from the given array
+   * @param lengthBytes the number of bytes to include from the given array, it must be &ge; 0.
    * @param byteOrder the byte order to be used
    * @return a new <i>Memory</i> for read operations
    */
@@ -201,7 +202,7 @@
 
   /**
    * Wraps the given primitive array for read operations assuming native byte order.
-   * @param array the given primitive array.
+   * @param array the given primitive array. It must be non-null and length &ge; 0.
    * @return a new <i>Memory</i> for read operations
    */
   static Memory wrap(boolean[] array) {
@@ -212,7 +213,7 @@
 
   /**
    * Wraps the given primitive array for read operations assuming native byte order.
-   * @param array the given primitive array.
+   * @param array the given primitive array. It must be non-null and length &ge; 0.
    * @return a new <i>Memory</i> for read operations
    */
   static Memory wrap(char[] array) {
@@ -223,7 +224,7 @@
 
   /**
    * Wraps the given primitive array for read operations assuming native byte order.
-   * @param array the given primitive array.
+   * @param array the given primitive array. It must be non-null and length &ge; 0.
    * @return a new <i>Memory</i> for read operations
    */
   static Memory wrap(short[] array) {
@@ -234,7 +235,7 @@
 
   /**
    * Wraps the given primitive array for read operations assuming native byte order.
-   * @param array the given primitive array.
+   * @param array the given primitive array. It must be non-null and length &ge; 0.
    * @return a new <i>Memory</i> for read operations
    */
   static Memory wrap(int[] array) {
@@ -245,7 +246,7 @@
 
   /**
    * Wraps the given primitive array for read operations assuming native byte order.
-   * @param array the given primitive array.
+   * @param array the given primitive array. It must be non-null and length &ge; 0.
    * @return a new <i>Memory</i> for read operations
    */
   static Memory wrap(long[] array) {
@@ -256,7 +257,7 @@
 
   /**
    * Wraps the given primitive array for read operations assuming native byte order.
-   * @param array the given primitive array.
+   * @param array the given primitive array. It must be non-null and length &ge; 0.
    * @return a new <i>Memory</i> for read operations
    */
   static Memory wrap(float[] array) {
@@ -267,7 +268,7 @@
 
   /**
    * Wraps the given primitive array for read operations assuming native byte order.
-   * @param array the given primitive array.
+   * @param array the given primitive array. It must be non-null and length &ge; 0.
    * @return a new <i>Memory</i> for read operations
    */
   static Memory wrap(double[] array) {
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/WritableMemory.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/WritableMemory.java
index 6866862..14023e1 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/WritableMemory.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/WritableMemory.java
@@ -20,6 +20,7 @@
 package org.apache.datasketches.memory;
 
 import static org.apache.datasketches.memory.internal.Util.negativeCheck;
+import static org.apache.datasketches.memory.internal.Util.zeroCheck;
 
 import java.io.File;
 import java.nio.ByteBuffer;
@@ -73,7 +74,7 @@
   static WritableMemory writableWrap(ByteBuffer byteBuffer, ByteOrder byteOrder, MemoryRequestServer memReqSvr) {
     Objects.requireNonNull(byteBuffer, "byteBuffer must be non-null");
     Objects.requireNonNull(byteOrder, "byteOrder must be non-null");
-    negativeCheck(byteBuffer.capacity(), "byteBuffer");
+    negativeCheck(byteBuffer.capacity(), "byteBuffer.capacity()");
     if (byteBuffer.isReadOnly()) { throw new ReadOnlyException("byteBuffer must be writable."); }
     return BaseWritableMemoryImpl.wrapByteBuffer(byteBuffer, false, byteOrder, memReqSvr);
   }
@@ -98,7 +99,7 @@
    * <i>WritableMemory.map(...)</i>.
    * @param file the given file to map. It must be non-null, writable and length &ge; 0.
    * @param fileOffsetBytes the position in the given file in bytes. It must not be negative.
-   * @param capacityBytes the size of the mapped Memory. It must not be negative.
+   * @param capacityBytes the size of the mapped Memory. It must be &ge; 0.
    * @param byteOrder the byte order to be used for the given file. It must be non-null.
    * @return WritableMapHandle for managing the mapped Memory.
    * Please read Javadocs for {@link Handle}.
@@ -123,7 +124,7 @@
    * It is the responsibility of the using application to clear this memory, if required,
    * and to call <i>close()</i> when done.</p>
    *
-   * @param capacityBytes the size of the desired memory in bytes. It must be &ge; 0.
+   * @param capacityBytes the size of the desired memory in bytes. It must be &gt; 0.
    * @return WritableHandle for this off-heap resource.
    * Please read Javadocs for {@link Handle}.
    */
@@ -139,7 +140,7 @@
    * It is the responsibility of the using application to clear this memory, if required,
    * and to call <i>close()</i> when done.</p>
    *
-   * @param capacityBytes the size of the desired memory in bytes. It must be &ge; 0.
+   * @param capacityBytes the size of the desired memory in bytes. It must be &gt; 0.
    * @param byteOrder the given byte order. It must be non-null.
    * @param memReqSvr A user-specified MemoryRequestServer, which may be null.
    * This is a callback mechanism for a user client of direct memory to request more memory.
@@ -148,7 +149,7 @@
    */
   static WritableHandle allocateDirect(long capacityBytes, ByteOrder byteOrder, MemoryRequestServer memReqSvr) {
     Objects.requireNonNull(byteOrder, "byteOrder must be non-null");
-    negativeCheck(capacityBytes, "capacityBytes");
+    zeroCheck(capacityBytes, "capacityBytes");
     return BaseWritableMemoryImpl.wrapDirect(capacityBytes, byteOrder, memReqSvr);
   }
 
@@ -163,7 +164,7 @@
    * </ul>
    *
    * @param offsetBytes the starting offset with respect to this object. It must be &ge; 0.
-   * @param capacityBytes the capacity of the returned object in bytes. It must be &ge; 0.
+   * @param capacityBytes the capacity of the returned object in bytes. It must be &gt; 0.
    * @return a new <i>WritableMemory</i> representing the defined writable region.
    */
   default WritableMemory writableRegion(long offsetBytes, long capacityBytes) {
@@ -181,7 +182,7 @@
    * </ul>
    *
    * @param offsetBytes the starting offset with respect to this object. It must be &ge; 0.
-   * @param capacityBytes the capacity of the returned object in bytes. It must be &ge; 0.
+   * @param capacityBytes the capacity of the returned object in bytes. It must be &gt; 0.
    * @param byteOrder the given byte order. It must be non-null.
    * @return a new <i>WritableMemory</i> representing the defined writable region.
    */
@@ -263,7 +264,7 @@
    *
    * <p><b>Note:</b> Always qualify this method with the class name, e.g.,
    * <i>WritableMemory.wrap(...)</i>.
-   * @param array the given primitive array. It must be non-null.
+   * @param array the given primitive array. It must be non-null, with length &ge; 0.
    * @return a new WritableMemory for write operations on the given primitive array.
    */
   static WritableMemory writableWrap(byte[] array) {
@@ -275,7 +276,7 @@
    *
    * <p><b>Note:</b> Always qualify this method with the class name, e.g.,
    * <i>WritableMemory.wrap(...)</i>.
-   * @param array the given primitive array. It must be non-null.
+   * @param array the given primitive array. It must be non-null, with length &ge; 0
    * @param byteOrder the byte order to be used. It must be non-null.
    * @return a new WritableMemory for write operations on the given primitive array.
    */
@@ -325,7 +326,7 @@
 
   /**
    * Wraps the given primitive array for write operations assuming native byte order.
-   * @param array the given primitive array. It must be non-null.
+   * @param array the given primitive array. It must be non-null with length &ge; 0.
    * @return a new WritableMemory for write operations on the given primitive array.
    */
   static WritableMemory writableWrap(boolean[] array) {
@@ -336,7 +337,7 @@
 
   /**
    * Wraps the given primitive array for write operations assuming native byte order.
-   * @param array the given primitive array.
+   * @param array the given primitive array. It must be non-null with length &ge; 0.
    * @return a new WritableMemory for write operations on the given primitive array.
    */
   static WritableMemory writableWrap(char[] array) {
@@ -347,7 +348,7 @@
 
   /**
    * Wraps the given primitive array for write operations assuming native byte order.
-   * @param array the given primitive array.
+   * @param array the given primitive array. It must be non-null with length &ge; 0.
    * @return a new WritableMemory for write operations on the given primitive array.
    */
   static WritableMemory writableWrap(short[] array) {
@@ -358,7 +359,7 @@
 
   /**
    * Wraps the given primitive array for write operations assuming native byte order.
-   * @param array the given primitive array.
+   * @param array the given primitive array. It must be non-null with length &ge; 0.
    * @return a new WritableMemory for write operations on the given primitive array.
    */
   static WritableMemory writableWrap(int[] array) {
@@ -369,7 +370,7 @@
 
   /**
    * Wraps the given primitive array for write operations assuming native byte order.
-   * @param array the given primitive array.
+   * @param array the given primitive array. It must be non-null with length &ge; 0.
    * @return a new WritableMemory for write operations on the given primitive array.
    */
   static WritableMemory writableWrap(long[] array) {
@@ -380,7 +381,7 @@
 
   /**
    * Wraps the given primitive array for write operations assuming native byte order.
-   * @param array the given primitive array.
+   * @param array the given primitive array. It must be non-null with length &ge; 0.
    * @return a new WritableMemory for write operations on the given primitive array.
    */
   static WritableMemory writableWrap(float[] array) {
@@ -391,7 +392,7 @@
 
   /**
    * Wraps the given primitive array for write operations assuming native byte order.
-   * @param array the given primitive array.
+   * @param array the given primitive array. It must be non-null with length &ge; 0.
    * @return a new WritableMemory for write operations on the given primitive array.
    */
   static WritableMemory writableWrap(double[] array) {
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirect.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirect.java
index 72fdd6b..336b39a 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirect.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirect.java
@@ -48,17 +48,15 @@
   AllocateDirect(final long capacityBytes) {
     //round up to multiple of 8 bytes
     final long allocationSize = ((capacityBytes & 7L) > 0L) ? ((capacityBytes >>> 3) + 1L) << 3 : capacityBytes;
-    NioBits.reserveMemory(allocationSize, capacityBytes);
 
     final long nativeAddress;
     try {
       nativeAddress = unsafe.allocateMemory(allocationSize);
     } catch (final OutOfMemoryError err) {
-      NioBits.unreserveMemory(allocationSize, capacityBytes);
       throw new RuntimeException(err);
     }
     nativeBaseOffset = nativeAddress;
-    deallocator = new Deallocator(nativeAddress, allocationSize, capacityBytes);
+    deallocator = new Deallocator(nativeAddress, allocationSize);
     cleaner = new MemoryCleaner(this, deallocator);
   }
 
@@ -89,15 +87,13 @@
     //This is the only place the actual native address is kept for use by unsafe.freeMemory();
     private final long nativeAddress;
     private final long allocationSize;
-    private final long capacity;
     private final StepBoolean valid = new StepBoolean(true); //only place for this
 
-    Deallocator(final long nativeAddress, final long allocationSize, final long capacity) {
+    Deallocator(final long nativeAddress, final long allocationSize) {
       BaseStateImpl.currentDirectMemoryAllocations_.incrementAndGet();
-      BaseStateImpl.currentDirectMemoryAllocated_.addAndGet(capacity);
+      BaseStateImpl.currentDirectMemoryAllocated_.addAndGet(allocationSize);
       this.nativeAddress = nativeAddress;
       this.allocationSize = allocationSize;
-      this.capacity = capacity;
       assert (nativeAddress != 0);
     }
 
@@ -117,9 +113,8 @@
           LOG.warning("A WritableHandle was not closed manually");
         }
         unsafe.freeMemory(nativeAddress);
-        NioBits.unreserveMemory(allocationSize, capacity);
         BaseStateImpl.currentDirectMemoryAllocations_.decrementAndGet();
-        BaseStateImpl.currentDirectMemoryAllocated_.addAndGet(-capacity);
+        BaseStateImpl.currentDirectMemoryAllocated_.addAndGet(-allocationSize);
         return true;
       }
       return false;
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirectMap.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirectMap.java
index d8356c9..997e7e0 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirectMap.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirectMap.java
@@ -34,7 +34,7 @@
 import org.apache.datasketches.memory.Map;
 import org.apache.datasketches.memory.MemoryCloseException;
 
-import sun.nio.ch.FileChannelImpl;
+import sun.nio.ch.FileChannelImpl; //java.base/
 
 /**
  * Allocates direct memory used to memory map files for read operations.
@@ -127,8 +127,8 @@
   public void load() {
     madvise();
     // Performance optimization. Read a byte from each page to bring it into memory.
-    final int ps = NioBits.pageSize();
-    final int count = NioBits.pageCount(capacityBytes);
+    final int ps = UnsafeUtil.PAGE_SIZE;
+    final int count = (int)UnsafeUtil.pageCount(capacityBytes);
     long offset = nativeBaseOffset;
     for (int i = 0; i < count; i++) {
       unsafe.getByte(offset);
@@ -139,7 +139,7 @@
   @Override
   public boolean isLoaded() {
     try {
-      final int pageCount = NioBits.pageCount(capacityBytes);
+      final int pageCount = (int)UnsafeUtil.pageCount(capacityBytes);
       return (boolean) MAPPED_BYTE_BUFFER_ISLOADED0_METHOD
           //isLoaded0 is effectively static, so ZERO_READ_ONLY_DIRECT_BYTE_BUFFER is not modified
           .invoke(AccessByteBuffer.ZERO_READ_ONLY_DIRECT_BYTE_BUFFER,
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BaseWritableMemoryImpl.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BaseWritableMemoryImpl.java
index ad397b0..1b495f6 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BaseWritableMemoryImpl.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BaseWritableMemoryImpl.java
@@ -30,6 +30,7 @@
 import static org.apache.datasketches.memory.internal.UnsafeUtil.checkBounds;
 import static org.apache.datasketches.memory.internal.UnsafeUtil.unsafe;
 import static org.apache.datasketches.memory.internal.Util.negativeCheck;
+import static org.apache.datasketches.memory.internal.Util.zeroCheck;
 
 import java.io.File;
 import java.io.IOException;
@@ -74,7 +75,7 @@
     EMPTY_BYTES = new byte[1024];
   }
 
-  //Pass-through ctor
+  //Pass-through constructor
   BaseWritableMemoryImpl(final Object unsafeObj, final long nativeBaseOffset,
       final long regionOffset, final long capacityBytes) {
     super(unsafeObj, nativeBaseOffset, regionOffset, capacityBytes);
@@ -82,7 +83,7 @@
 
   /**
    * The static constructor that chooses the correct Heap leaf node based on the byte order.
-   * @param arr the primitive heap array being wrapped
+   * @param arr the primitive heap array being wrapped. It must be non-null with length &ge; 0.
    * @param offsetBytes the offset bytes into the array (independent of array type).
    * @param lengthBytes the length of the wrapped region.
    * @param localReadOnly the requested read-only status
@@ -92,6 +93,8 @@
    */
   public static BaseWritableMemoryImpl wrapHeapArray(final Object arr, final long offsetBytes, final long lengthBytes,
       final boolean localReadOnly, final ByteOrder byteOrder, final MemoryRequestServer memReqSvr) {
+    Objects.requireNonNull(arr, "array must be non-null");
+    negativeCheck(lengthBytes, "lengthBytes");
     final int typeId = localReadOnly ? READONLY : 0;
     return Util.isNativeByteOrder(byteOrder)
         ? new HeapWritableMemoryImpl(arr, offsetBytes, lengthBytes, typeId, memReqSvr)
@@ -120,9 +123,9 @@
 
   /**
    * The static constructor that chooses the correct Map leaf node based on the byte order.
-   * @param file the file being wrapped.
+   * @param file the file being wrapped. It must be non-null with length &gt; 0.
    * @param fileOffsetBytes the file offset bytes
-   * @param capacityBytes the requested capacity of the memory mapped region
+   * @param capacityBytes the requested capacity of the memory mapped region. It must be &gt; 0
    * @param localReadOnly the requested read-only state
    * @param byteOrder the requested byte-order
    * @return this class constructed via the leaf node.
@@ -130,6 +133,8 @@
   @SuppressWarnings("resource")
   public static WritableMapHandle wrapMap(final File file, final long fileOffsetBytes,
       final long capacityBytes, final boolean localReadOnly, final ByteOrder byteOrder) {
+    Objects.requireNonNull(file, "file must be non-null");
+    zeroCheck(capacityBytes, "capacityBytes");
     final AllocateDirectWritableMap dirWMap =
         new AllocateDirectWritableMap(file, fileOffsetBytes, capacityBytes, localReadOnly);
     final int typeId = (dirWMap.resourceReadOnly || localReadOnly) ? READONLY : 0;
@@ -143,7 +148,7 @@
 
   /**
    * The static constructor that chooses the correct Direct leaf node based on the byte order.
-   * @param capacityBytes the requested capacity for the Direct (off-heap) memory
+   * @param capacityBytes the requested capacity for the Direct (off-heap) memory.  It must be &ge; 0.
    * @param byteOrder the requested byte order
    * @param memReqSvr the requested MemoryRequestServer, which may be null
    * @return this class constructed via the leaf node.
@@ -151,6 +156,7 @@
   @SuppressWarnings("resource")
   public static WritableHandle wrapDirect(final long capacityBytes,
       final ByteOrder byteOrder, final MemoryRequestServer memReqSvr) {
+    negativeCheck(capacityBytes, "capacityBytes");
     final AllocateDirect direct = new AllocateDirect(capacityBytes);
     final int typeId = 0; //direct is never read-only on construction
     final BaseWritableMemoryImpl wmem = Util.isNativeByteOrder(byteOrder)
@@ -176,12 +182,12 @@
 
   WritableMemory writableRegionImpl(final long offsetBytes, final long capacityBytes,
       final boolean localReadOnly, final ByteOrder byteOrder) {
+    negativeCheck(offsetBytes, "offsetBytes");
+    negativeCheck(capacityBytes, "capacityBytes");
+    Objects.requireNonNull(byteOrder, "byteOrder must be non-null.");
     if (isReadOnly() && !localReadOnly) {
       throw new ReadOnlyException("Writable region of a read-only Memory is not allowed.");
     }
-    negativeCheck(offsetBytes, "offsetBytes must be >= 0");
-    negativeCheck(capacityBytes, "capacityBytes must be >= 0");
-    Objects.requireNonNull(byteOrder, "byteOrder must be non-null.");
     checkValidAndBounds(offsetBytes, capacityBytes);
     final boolean readOnly = isReadOnly() || localReadOnly;
     return toWritableRegion(offsetBytes, capacityBytes, readOnly, byteOrder);
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/NioBits.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/NioBits.java
deleted file mode 100644
index 62827ac..0000000
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/NioBits.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.datasketches.memory.internal;
-
-import static org.apache.datasketches.memory.internal.UnsafeUtil.unsafe;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.concurrent.atomic.AtomicLong;
-
-/**
- * Provide linkage to java.nio.Bits.
- *
- * @author Lee Rhodes
- */
-@SuppressWarnings("restriction")
-final class NioBits {
-  private static final Class<?> NIO_BITS_CLASS;
-  private static final Method NIO_BITS_RESERVE_MEMORY_METHOD;
-  private static final Method NIO_BITS_UNRESERVE_MEMORY_METHOD;
-
-  private static final AtomicLong nioBitsCount;
-  private static final AtomicLong nioBitsReservedMemory;
-  private static final AtomicLong nioBitsTotalCapacity;
-
-  private static int pageSize = unsafe.pageSize();
-  private static final long maxDBBMemory;
-  private static final boolean isPageAligned;
-
-  static {
-    try {
-      isPageAligned = VirtualMachineMemory.getIsPageAligned();
-      maxDBBMemory = VirtualMachineMemory.getMaxDBBMemory();
-
-      NIO_BITS_CLASS = Class.forName("java.nio.Bits");
-
-      NIO_BITS_RESERVE_MEMORY_METHOD = NIO_BITS_CLASS
-          .getDeclaredMethod("reserveMemory", long.class, int.class); //JD16 requires (long, long)
-      NIO_BITS_RESERVE_MEMORY_METHOD.setAccessible(true);
-
-      NIO_BITS_UNRESERVE_MEMORY_METHOD = NIO_BITS_CLASS
-          .getDeclaredMethod("unreserveMemory", long.class, int.class); //JD16 requires (long, long)
-      NIO_BITS_UNRESERVE_MEMORY_METHOD.setAccessible(true);
-
-      final Field countField = NIO_BITS_CLASS.getDeclaredField(NioBitsFields.COUNT_FIELD_NAME);
-      countField.setAccessible(true);
-      nioBitsCount = (AtomicLong) (countField.get(null));
-
-      final Field reservedMemoryField = NIO_BITS_CLASS.getDeclaredField(NioBitsFields.RESERVED_MEMORY_FIELD_NAME);
-      reservedMemoryField.setAccessible(true);
-      nioBitsReservedMemory = (AtomicLong) (reservedMemoryField.get(null));
-
-      final Field totalCapacityField = NIO_BITS_CLASS.getDeclaredField(NioBitsFields.TOTAL_CAPACITY_FIELD_NAME);
-      totalCapacityField.setAccessible(true);
-      nioBitsTotalCapacity = (AtomicLong) (totalCapacityField.get(null));
-
-    } catch (final ClassNotFoundException | NoSuchMethodException |  IllegalAccessException
-        | IllegalArgumentException | SecurityException |  NoSuchFieldException e) {
-      throw new RuntimeException("Could not acquire java.nio.Bits class: " + e.getClass());
-    }
-  }
-
-  private NioBits() { }
-
-  static long getDirectAllocationsCount() { //tested via reflection
-    return nioBitsCount.get();
-  }
-
-  static long getReservedMemory() { //tested via reflection
-    return nioBitsReservedMemory.get();
-  }
-
-  static long getTotalCapacity() { //tested via reflection
-    return nioBitsTotalCapacity.get();
-  }
-
-  static int pageSize() {
-    return pageSize;
-  }
-
-  static int pageCount(final long bytes) {
-    return (int)((bytes + pageSize()) - 1L) / pageSize();
-  }
-
-  static long getMaxDirectByteBufferMemory() { //tested via reflection
-    return maxDBBMemory;
-  }
-
-  static boolean isPageAligned() {
-    return isPageAligned;
-  }
-
-  //RESERVE & UNRESERVE BITS MEMORY TRACKING COUNTERS
-  // Comment from java.nio.Bits.java ~ line 705:
-  // -XX:MaxDirectMemorySize limits the total capacity rather than the
-  // actual memory usage, which will differ when buffers are page aligned.
-  static void reserveMemory(final long allocationSize, final long capacity) {
-    reserveUnreserve(allocationSize, capacity, NIO_BITS_RESERVE_MEMORY_METHOD);
-  }
-
-  static void unreserveMemory(final long allocationSize, final long capacity) {
-    reserveUnreserve(allocationSize, capacity, NIO_BITS_UNRESERVE_MEMORY_METHOD);
-  }
-
-  private static void reserveUnreserve(long allocationSize, long capacity, final Method method) {
-    Util.zeroCheck(capacity, "capacity");
-    // 1GB is a pretty "safe" limit.
-    final long chunkSizeLimit = 1L << 30;
-    try {
-      while (capacity > 0) {
-        final long chunk = Math.min(capacity, chunkSizeLimit);
-        if (capacity == chunk) {
-          method.invoke(null, allocationSize, (int) capacity); //JDK 16 remove cast to int
-        } else {
-          method.invoke(null, chunk, (int) chunk); //JDK 16 remove cast to int
-        }
-        capacity -= chunk;
-        allocationSize -= chunk;
-      }
-    } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
-      throw new RuntimeException(
-          "Could not invoke java.nio.Bits.unreserveMemory(...) OR java.nio.Bits.reserveMemory(...): "
-          + "allocationSize = " + allocationSize + ", capacity = " + capacity, e);
-    }
-  }
-}
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/NioBitsFields.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/NioBitsFields.java
deleted file mode 100644
index 56f1e20..0000000
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/NioBitsFields.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.datasketches.memory.internal;
-
-/**
- * Extracts version-dependent field names into standalone class.
- * Some field names in the VM internal class have changed in
- * later versions. The appropriate class will be loaded by the class loader
- * depending on the Java version that is used.
- * For more information, see: https://openjdk.java.net/jeps/238
- */
-class NioBitsFields {
-    static String COUNT_FIELD_NAME = "count";
-    static String RESERVED_MEMORY_FIELD_NAME = "reservedMemory";
-    static String TOTAL_CAPACITY_FIELD_NAME = "totalCapacity";
-}
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/UnsafeUtil.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/UnsafeUtil.java
index bee1c05..67c1975 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/UnsafeUtil.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/UnsafeUtil.java
@@ -37,6 +37,7 @@
 
   //not an indicator of whether compressed references are used.
   public static final int ADDRESS_SIZE;
+  public static final int PAGE_SIZE;
 
   //For 64-bit JVMs: these offsets vary depending on coop: 16 for JVM <= 32GB; 24 for JVM > 32GB.
   // Making this constant long-typed, rather than int, to exclude possibility of accidental overflow
@@ -102,6 +103,7 @@
     //4 on 32-bit systems. 4 on 64-bit systems < 32GB, otherwise 8.
     //This alone is not an indicator of compressed ref (coop)
     ADDRESS_SIZE = unsafe.addressSize();
+    PAGE_SIZE = unsafe.pageSize();
 
     ARRAY_BOOLEAN_BASE_OFFSET = unsafe.arrayBaseOffset(boolean[].class);
     ARRAY_BYTE_BASE_OFFSET = unsafe.arrayBaseOffset(byte[].class);
@@ -189,6 +191,10 @@
     }
   }
 
+  public static long pageCount(final long bytes) {
+    return (int)((bytes + PAGE_SIZE) - 1L) / PAGE_SIZE;
+  }
+
   /**
    * Assert the requested offset and length against the allocated size.
    * The invariants equation is: {@code 0 <= reqOff <= reqLen <= reqOff + reqLen <= allocSize}.
diff --git a/datasketches-memory-java9/src/main/java/module-info.java b/datasketches-memory-java9/src/main/java/module-info.java
index 78c9ce2..990b45d 100644
--- a/datasketches-memory-java9/src/main/java/module-info.java
+++ b/datasketches-memory-java9/src/main/java/module-info.java
@@ -22,5 +22,5 @@
     requires java.logging;
     requires jdk.unsupported;
 
-    exports org.apache.datasketches.memory;
+    exports org.apache.datasketches.memory.internal;
 }
diff --git a/datasketches-memory-java9/src/main/java/org/apache/datasketches/memory/internal/NioBitsFields.java b/datasketches-memory-java9/src/main/java/org/apache/datasketches/memory/internal/NioBitsFields.java
deleted file mode 100644
index 56f1e20..0000000
--- a/datasketches-memory-java9/src/main/java/org/apache/datasketches/memory/internal/NioBitsFields.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.datasketches.memory.internal;
-
-/**
- * Extracts version-dependent field names into standalone class.
- * Some field names in the VM internal class have changed in
- * later versions. The appropriate class will be loaded by the class loader
- * depending on the Java version that is used.
- * For more information, see: https://openjdk.java.net/jeps/238
- */
-class NioBitsFields {
-    static String COUNT_FIELD_NAME = "count";
-    static String RESERVED_MEMORY_FIELD_NAME = "reservedMemory";
-    static String TOTAL_CAPACITY_FIELD_NAME = "totalCapacity";
-}