You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datasketches.apache.org by le...@apache.org on 2023/02/24 06:14:29 UTC

[datasketches-memory] branch addJavadocThrows created (now 5c83fec)

This is an automated email from the ASF dual-hosted git repository.

leerho pushed a change to branch addJavadocThrows
in repository https://gitbox.apache.org/repos/asf/datasketches-memory.git


      at 5c83fec  Fine tuning of checkValid() and checkThread()

This branch includes the following new commits:

     new 5c83fec  Fine tuning of checkValid() and checkThread()

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datasketches.apache.org
For additional commands, e-mail: commits-help@datasketches.apache.org


[datasketches-memory] 01/01: Fine tuning of checkValid() and checkThread()

Posted by le...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

leerho pushed a commit to branch addJavadocThrows
in repository https://gitbox.apache.org/repos/asf/datasketches-memory.git

commit 5c83fec59800d3b4ddebd5a60b88a3d9c348209a
Author: Lee Rhodes <le...@users.noreply.github.com>
AuthorDate: Thu Feb 23 22:14:15 2023 -0800

    Fine tuning of checkValid() and checkThread()
---
 .../org/apache/datasketches/memory/BaseBuffer.java |  26 +---
 .../datasketches/memory/MemoryCloseException.java  |  46 -------
 .../memory/MemoryInvalidException.java             |  38 ------
 .../org/apache/datasketches/memory/Resource.java   |  69 +++-------
 .../apache/datasketches/memory/WritableMemory.java |  21 ++-
 .../memory/internal/AllocateDirect.java            |  22 +---
 .../memory/internal/AllocateDirectWritableMap.java |  50 +++----
 .../internal/BBNonNativeWritableBufferImpl.java    |  34 ++---
 .../internal/BBNonNativeWritableMemoryImpl.java    |  34 ++---
 .../memory/internal/BBWritableBufferImpl.java      |  32 ++---
 .../memory/internal/BBWritableMemoryImpl.java      |  31 ++---
 .../memory/internal/BaseBufferImpl.java            |  47 ++-----
 .../memory/internal/BaseWritableBufferImpl.java    |   6 +-
 .../memory/internal/CompareAndCopy.java            |   2 +-
 .../DirectNonNativeWritableBufferImpl.java         |  32 ++---
 .../DirectNonNativeWritableMemoryImpl.java         |  32 ++---
 .../memory/internal/DirectWritableBufferImpl.java  |  31 ++---
 .../memory/internal/DirectWritableMemoryImpl.java  |  31 ++---
 .../internal/HeapNonNativeWritableBufferImpl.java  |  17 +--
 .../internal/HeapNonNativeWritableMemoryImpl.java  |  17 +--
 .../memory/internal/HeapWritableBufferImpl.java    |  17 +--
 .../memory/internal/HeapWritableMemoryImpl.java    |  17 +--
 .../internal/MapNonNativeWritableBufferImpl.java   |  48 +++----
 .../internal/MapNonNativeWritableMemoryImpl.java   |  48 +++----
 .../memory/internal/MapWritableBufferImpl.java     |  48 +++----
 .../memory/internal/MapWritableMemoryImpl.java     |  46 ++++---
 .../memory/internal/MemoryCleaner.java             |   1 +
 .../datasketches/memory/internal/NioBits.java      | 144 ---------------------
 .../datasketches/memory/internal/ResourceImpl.java | 143 ++++++++++----------
 .../datasketches/memory/internal/UnsafeUtil.java   |   6 +-
 .../internal/AllocateDirectMapMemoryTest.java      |  24 ++--
 .../memory/internal/AllocateDirectMemoryTest.java  |   7 +-
 .../memory/internal/BaseBufferTest.java            |  13 +-
 .../datasketches/memory/internal/BufferTest.java   |   7 +-
 .../datasketches/memory/internal/LeafImplTest.java |   8 +-
 .../memory/internal/MemoryCloseExceptionTest.java  |  14 --
 .../datasketches/memory/internal/MemoryTest.java   |   5 +-
 .../internal/NativeWritableBufferImplTest.java     |   4 +-
 .../internal/NativeWritableMemoryImplTest.java     |   2 +-
 .../datasketches/memory/internal/NioBitsTest.java  |  78 -----------
 .../memory/internal/SpecificLeafTest.java          |  97 +++++++-------
 .../datasketches/memory/internal/ThreadTest.java   |  76 +++++++++++
 pom.xml                                            |   2 +-
 43 files changed, 520 insertions(+), 953 deletions(-)

diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/BaseBuffer.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/BaseBuffer.java
index 711de64..09f4a49 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/BaseBuffer.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/BaseBuffer.java
@@ -83,42 +83,20 @@ public interface BaseBuffer extends Resource {
 
   /**
    * Sets the current position.
-   * Asserts that the positional invariants are not violated,
-   * otherwise, if asserts are enabled throws an {@link AssertionError}.
    * @param position the given current position.
    * @return BaseBuffer
+   * @throws BufferPositionInvariantsException if positional invariants have been violated.
    */
   BaseBuffer setPosition(long position);
 
-  /**
-   * Sets the current position.
-   * Checks that the positional invariants are not violated,
-   * otherwise, throws an {@link IllegalArgumentException}.
-   * @param position the given current position.
-   * @return BaseBuffer
-   */
-  BaseBuffer setAndCheckPosition(long position);
-
   /**
    * Sets start position, current position, and end position.
-   * Asserts that the positional invariants are not violated,
-   * otherwise, if asserts are enabled throws an {@link AssertionError}.
    * @param start the start position in the buffer
    * @param position the current position between the start and end
    * @param end the end position in the buffer
    * @return BaseBuffer
+   * @throws BufferPositionInvariantsException if positional invariants have been violated.
    */
   BaseBuffer setStartPositionEnd(long start, long position, long end);
 
-  /**
-   * Sets start position, current position, and end position.
-   * Checks that the positional invariants are not violated,
-   * otherwise, throws an {@link IllegalArgumentException}.
-   * @param start the start position in the buffer
-   * @param position the current position between the start and end
-   * @param end the end position in the buffer
-   * @return BaseBuffer
-   */
-  BaseBuffer setAndCheckStartPositionEnd(long start, long position, long end);
-
 }
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/MemoryCloseException.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/MemoryCloseException.java
deleted file mode 100644
index 593df3c..0000000
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/MemoryCloseException.java
+++ /dev/null
@@ -1,46 +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;
-
-/**
- * Specific RuntimeException for the AutoCloseable.close() method.
- *
- * @author Lee Rhodes
- */
-public class MemoryCloseException extends MemoryException {
-  private static final long serialVersionUID = 1L;
-
-  /**
-   * The associated resource failed to close.
-   */
-  public MemoryCloseException() {
-    super("The associated resource failed to close.");
-  }
-
-  /**
-   * The associated resource failed to close, with comment
-   *
-   * @param resource the named resource that failed to close, plus other comments.
-   */
-  public MemoryCloseException(final String resource) {
-    super("The associated resource, " + resource + ", failed to close");
-  }
-
-}
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/MemoryInvalidException.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/MemoryInvalidException.java
deleted file mode 100644
index e85eb39..0000000
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/MemoryInvalidException.java
+++ /dev/null
@@ -1,38 +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;
-
-/**
- * Specific RuntimeException for invalid Memory.
- *
- * @author Lee Rhodes
- */
-public class MemoryInvalidException extends MemoryException {
-  private static final long serialVersionUID = 1L;
-
-  /**
-   * The associated resource failed to close.
-   */
-  public MemoryInvalidException() {
-    super("The associated Memory is invalid.");
-  }
-
-}
-
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/Resource.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/Resource.java
index 6d87514..bb40d16 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/Resource.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/Resource.java
@@ -19,7 +19,6 @@
 
 package org.apache.datasketches.memory;
 
-import java.io.UncheckedIOException;
 import java.nio.ByteOrder;
 
 /**
@@ -31,15 +30,6 @@ public interface Resource extends AutoCloseable {
 
   static MemoryRequestServer defaultMemReqSvr = null; //policy choice
 
-  /**
-   * Checks that the specified range of bytes is within bounds of this object, throws
-   * {@link IllegalArgumentException} if it's not: i. e. if offsetBytes &lt; 0, or length &lt; 0,
-   * or offsetBytes + length &gt; {@link #getCapacity()}.
-   * @param offsetBytes the given offset in bytes of this object
-   * @param lengthBytes the given length in bytes of this object
-   */
-  void checkValidAndBounds(long offsetBytes, long lengthBytes);
-
   /**
    * Closes this resource if this can be closed via <em>AutoCloseable</em>.
    * If this operation completes without exceptions, this resource will be marked as <em>not alive</em>,
@@ -50,23 +40,19 @@ public interface Resource extends AutoCloseable {
    * should be manifest in the client code; a failure in any of these transitions reveals a bug in the underlying
    * application logic.
    *
-   * @throws IllegalStateException if this is an AutoCloseable Resource (Memory mapped files and direct, off-heap
-   * memory allocations), and:
-   * <ul>
-   *  <li>this resource is already closed, or
-   *  <li>this method is called from a thread other than the thread owning this resource</li>.
-   * </ul>
-   *
+   * @throws IllegalStateException if this Resource is not <em>valid</em>.
+   * @throws IllegalStateException if this method is not accessed from the owning thread.
    * @throws UnsupportedOperationException if this resource is not {@link AutoCloseable}.
    */
   @Override
-  default void close() {/* Overridden by the actual AutoCloseable sub-classes. */ }
+  void close();
 
   /**
    * Returns true if the given object (<em>that</em>) is an instance of this class and has contents equal to
    * this object.
    * @param that the given Resource object
    * @return true if the given object has equal contents to this object.
+   * @see #equalTo(long, Resource, long, long)
    */
   default boolean equalTo(Resource that) {
     if (that == null || this.getCapacity() != that.getCapacity()) { return false; }
@@ -82,6 +68,8 @@ public interface Resource extends AutoCloseable {
    * @param thatOffsetBytes the starting offset in bytes for the given Resource object
    * @param lengthBytes the size of the range in bytes
    * @return true if the given Resource object has equal contents to this object in the given range of bytes.
+   * @throws IllegalStateException if either resource is not <em>valid</em>.
+   * @throws MemoryBoundsException if there is a bounds violation.
    */
   boolean equalTo(long thisOffsetBytes, Resource that, long thatOffsetBytes, long lengthBytes);
 
@@ -101,17 +89,12 @@ public interface Resource extends AutoCloseable {
    * In particular, this method has no effect for files mapped in read-only or private
    * mapping modes. This method may or may not have an effect for implementation-specific mapping modes.</p>
    *
-   * @throws IllegalStateException if:
-   * <ul>
-   *  <li>this memory-mapped Resource is not <em>alive</em></li>, or
-   *  <li>this method is called from a thread other than the thread owning this resource</li>.
-   * </ul>
-   *
-   * @throws UnsupportedOperationException if this Resource is not memory-mapped, e.g. if
-   * {@code isMapped() == false}.
-   *
-   * @throws UncheckedIOException if there is an I/O error writing the contents of this
-   * memory-mapped Resource to the associated storage device
+   * @throws IllegalStateException if this Resource is not <em>valid</em>.
+   * @throws IllegalStateException if this method is not accessed from the owning thread.
+   * @throws UnsupportedOperationException if this Resource is not memory-mapped, e.g. if {@code isMapped() == false}.
+   * @throws ReadOnlyException if this Resource is read-only.
+   * @throws RuntimeException if there is some other error writing the contents of this
+   * memory-mapped Resource to the associated storage device.
    */
   void force();
 
@@ -174,8 +157,8 @@ public interface Resource extends AutoCloseable {
   boolean isDuplicateBufferView();
 
   /**
-   * Returns true if this object is backed by an on-heap primitive array
-   * @return true if this object is backed by an on-heap primitive array
+   * Returns true if this object is backed by an on-heap primitive array or an on-heap ByteBuffer.
+   * @return true if this object is backed by an on-heap primitive array or an on-heap ByteBuffer.
    */
   boolean isHeapResource();
 
@@ -194,14 +177,9 @@ public interface Resource extends AutoCloseable {
    *
    * @return true if it is likely that all of the data in this memory-mapped Resource is resident in physical memory
    *
-   * @throws IllegalStateException if:
-   * <ul>
-   *  <li>this memory-mapped Resource  is not <em>alive</em></li>, or
-   *  <li>this method is called from a thread other than the thread owning this resource</li>.
-   * </ul>
-   *
-   * @throws UnsupportedOperationException if this Resource is not memory-mapped, e.g. if
-   * {@code isMapped() == false}.
+   * @throws IllegalStateException if this Resource is not <em>valid</em>.
+   * @throws IllegalStateException if this method is not accessed from the owning thread.
+   * @throws UnsupportedOperationException if this Resource is not memory-mapped, e.g. if {@code isMapped() == false}.
    */
   boolean isLoaded();
 
@@ -270,19 +248,14 @@ public interface Resource extends AutoCloseable {
    * resident in physical memory. Invoking this method may cause some number of page faults and
    * I/O operations to occur.</p>
    *
-   * @throws IllegalStateException if:
-   * <ul>
-   *  <li>this memory-mapped Resource  is not <em>alive</em></li>, or
-   *  <li>this method is called from a thread other than the thread owning this Resource</li>.
-   * </ul>
-   *
-   * @throws UnsupportedOperationException if this Resource is not memory-mapped, e.g. if
-   * {@code isMapped() == false}.
+   * @throws IllegalStateException if this Resource is not <em>valid</em>.
+   * @throws IllegalStateException if this method is not accessed from the owning thread.
+   * @throws UnsupportedOperationException if this Resource is not memory-mapped, e.g. if {@code isMapped() == false}.
    */
   void load();
 
   /**
-   * Sets the MemoryRequestServer.
+   * Sets the Default MemoryRequestServer
    * @param memReqSvr the given MemoryRequestServer.
    */
   void setMemoryRequestServer(MemoryRequestServer memReqSvr);
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 c5cfec6..844f4ff 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
@@ -325,7 +325,8 @@ public interface WritableMemory extends Memory {
   static WritableMemory writableWrap(boolean[] array) {
     Objects.requireNonNull(array, "array must be non-null");
     final long lengthBytes = array.length << Prim.BOOLEAN.shift();
-    return BaseWritableMemoryImpl.wrapHeapArray(array, 0, lengthBytes, false, ByteOrder.nativeOrder(), null);
+    return BaseWritableMemoryImpl.wrapHeapArray(array, 0, lengthBytes, false, ByteOrder.nativeOrder(),
+        defaultMemReqSvr);
   }
 
   /**
@@ -336,7 +337,8 @@ public interface WritableMemory extends Memory {
   static WritableMemory writableWrap(char[] array) {
     Objects.requireNonNull(array, "array must be non-null");
     final long lengthBytes = array.length << Prim.CHAR.shift();
-    return BaseWritableMemoryImpl.wrapHeapArray(array, 0L, lengthBytes, false, ByteOrder.nativeOrder(), null);
+    return BaseWritableMemoryImpl.wrapHeapArray(array, 0L, lengthBytes, false, ByteOrder.nativeOrder(),
+        defaultMemReqSvr);
   }
 
   /**
@@ -347,7 +349,8 @@ public interface WritableMemory extends Memory {
   static WritableMemory writableWrap(short[] array) {
     Objects.requireNonNull(array, "arr must be non-null");
     final long lengthBytes = array.length << Prim.SHORT.shift();
-    return BaseWritableMemoryImpl.wrapHeapArray(array, 0L, lengthBytes, false, ByteOrder.nativeOrder(), null);
+    return BaseWritableMemoryImpl.wrapHeapArray(array, 0L, lengthBytes, false, ByteOrder.nativeOrder(),
+        defaultMemReqSvr);
   }
 
   /**
@@ -358,7 +361,8 @@ public interface WritableMemory extends Memory {
   static WritableMemory writableWrap(int[] array) {
     Objects.requireNonNull(array, "arr must be non-null");
     final long lengthBytes = array.length << Prim.INT.shift();
-    return BaseWritableMemoryImpl.wrapHeapArray(array, 0L, lengthBytes, false, ByteOrder.nativeOrder(), null);
+    return BaseWritableMemoryImpl.wrapHeapArray(array, 0L, lengthBytes, false, ByteOrder.nativeOrder(),
+        defaultMemReqSvr);
   }
 
   /**
@@ -369,7 +373,8 @@ public interface WritableMemory extends Memory {
   static WritableMemory writableWrap(long[] array) {
     Objects.requireNonNull(array, "arr must be non-null");
     final long lengthBytes = array.length << Prim.LONG.shift();
-    return BaseWritableMemoryImpl.wrapHeapArray(array, 0L, lengthBytes, false, ByteOrder.nativeOrder(), null);
+    return BaseWritableMemoryImpl.wrapHeapArray(array, 0L, lengthBytes, false, ByteOrder.nativeOrder(),
+        defaultMemReqSvr);
   }
 
   /**
@@ -380,7 +385,8 @@ public interface WritableMemory extends Memory {
   static WritableMemory writableWrap(float[] array) {
     Objects.requireNonNull(array, "arr must be non-null");
     final long lengthBytes = array.length << Prim.FLOAT.shift();
-    return BaseWritableMemoryImpl.wrapHeapArray(array, 0L, lengthBytes, false, ByteOrder.nativeOrder(), null);
+    return BaseWritableMemoryImpl.wrapHeapArray(array, 0L, lengthBytes, false, ByteOrder.nativeOrder(),
+        defaultMemReqSvr);
   }
 
   /**
@@ -391,7 +397,8 @@ public interface WritableMemory extends Memory {
   static WritableMemory writableWrap(double[] array) {
     Objects.requireNonNull(array, "arr must be non-null");
     final long lengthBytes = array.length << Prim.DOUBLE.shift();
-    return BaseWritableMemoryImpl.wrapHeapArray(array, 0L, lengthBytes, false, ByteOrder.nativeOrder(), null);
+    return BaseWritableMemoryImpl.wrapHeapArray(array, 0L, lengthBytes, false, ByteOrder.nativeOrder(),
+        defaultMemReqSvr);
   }
   //END OF CONSTRUCTOR-TYPE METHODS
 
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 76a121d..6c6eb16 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
@@ -21,24 +21,16 @@ package org.apache.datasketches.memory.internal;
 
 import static org.apache.datasketches.memory.internal.UnsafeUtil.unsafe;
 
-import java.util.logging.Logger;
-
-import org.apache.datasketches.memory.MemoryCloseException;
-
 /**
  * Provides access to direct (native) memory.
  *
- * @author Roman Leventov
  * @author Lee Rhodes
  */
 @SuppressWarnings("restriction")
 final class AllocateDirect {
-  static final Logger LOG = Logger.getLogger(AllocateDirect.class.getCanonicalName());
-
   private final Deallocator deallocator;
   private final long nativeBaseOffset;
   private final MemoryCleaner cleaner;
-  private final Thread owner;
 
   /**
    * Base Constructor for allocate native memory.
@@ -52,12 +44,10 @@ final class AllocateDirect {
     final boolean pageAligned = VirtualMachineMemory.getIsPageAligned();
     final long pageSize = VirtualMachineMemory.getPageSize();
     final long allocationSize = capacityBytes + (pageAligned ? pageSize : 0);
-    this.owner = Thread.currentThread();
     final long nativeAddress;
     try {
       nativeAddress = unsafe.allocateMemory(allocationSize);
     } catch (final OutOfMemoryError err) {
-      NioBits.unreserveMemory(allocationSize, capacityBytes);
       throw new RuntimeException(err);
     }
     if (pageAligned && ((nativeAddress % pageSize) != 0)) {
@@ -71,7 +61,6 @@ final class AllocateDirect {
   }
 
   public void close() {
-    checkValidAndThread(); //we must be valid and called from the owner thread
     try {
       if (deallocator.deallocate(false)) {
         // This Cleaner.clean() call effectively just removes the Cleaner from the internal linked
@@ -84,11 +73,6 @@ final class AllocateDirect {
     }
   }
 
-  public final void checkValidAndThread() {
-    if (!getValid().get()) { throw new MemoryCloseException("Already closed"); }
-    ResourceImpl.checkThread(owner);
-  }
-
   long getNativeBaseOffset() {
     return nativeBaseOffset;
   }
@@ -111,15 +95,15 @@ final class AllocateDirect {
     }
 
     @Override
-    public void run() throws MemoryCloseException {
+    public void run() throws IllegalStateException {
       deallocate(true);
     }
 
-    boolean deallocate(final boolean calledFromCleaner) throws MemoryCloseException {
+    boolean deallocate(final boolean calledFromCleaner) throws IllegalStateException {
       if (valid.change()) {
         if (calledFromCleaner) {
           // Warn about non-deterministic resource cleanup.
-          LOG.warning("A WritableHandle was not closed manually");
+          //LOG.warning("A direct resource was not closed explicitly");
         }
         unsafe.freeMemory(nativeAddress);
         return true;
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirectWritableMap.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirectWritableMap.java
index f86267f..0dd39a9 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirectWritableMap.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirectWritableMap.java
@@ -29,10 +29,6 @@ import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.nio.MappedByteBuffer;
 import java.nio.channels.FileChannel;
-import java.util.logging.Logger;
-
-import org.apache.datasketches.memory.MemoryCloseException;
-import org.apache.datasketches.memory.ReadOnlyException;
 
 import sun.nio.ch.FileChannelImpl;
 
@@ -48,13 +44,11 @@ import sun.nio.ch.FileChannelImpl;
  * <a href="http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/f940e7a48b72/src/solaris/native/java/nio/MappedByteBuffer.c">
  * MappedByteBuffer.c</a></p>
  *
- * @author Roman Leventov
  * @author Lee Rhodes
  * @author Praveenkumar Venkatesan
  */
 @SuppressWarnings("restriction")
 class AllocateDirectWritableMap {
-  static final Logger LOG = Logger.getLogger(AllocateDirectWritableMap.class.getCanonicalName());
 
   private static final int MAP_RO = 0;
   private static final int MAP_RW = 1;
@@ -65,6 +59,7 @@ class AllocateDirectWritableMap {
   private static final Method MAPPED_BYTE_BUFFER_LOAD0_METHOD;
   private static final Method MAPPED_BYTE_BUFFER_ISLOADED0_METHOD;
   static final Method MAPPED_BYTE_BUFFER_FORCE0_METHOD;
+  private static int pageSize = unsafe.pageSize();
 
   static {
     try { //The FileChannelImpl methods map0 and unmap0 still exist in 16
@@ -96,7 +91,6 @@ class AllocateDirectWritableMap {
 
   private final Deallocator deallocator;
   private final MemoryCleaner cleaner;
-  private final Thread owner;
 
   private final File file;
   final long capacityBytes;
@@ -107,7 +101,6 @@ class AllocateDirectWritableMap {
   AllocateDirectWritableMap(final File file, final long fileOffsetBytes, final long capacityBytes,
       final boolean localReadOnly) {
     this.file = file;
-    this.owner = Thread.currentThread();
     this.capacityBytes = capacityBytes;
     resourceReadOnly = isFileReadOnly(file);
     final long fileLength = file.length();
@@ -123,13 +116,7 @@ class AllocateDirectWritableMap {
     cleaner = new MemoryCleaner(this, deallocator);
   }
 
-  public final void checkValidAndThread() {
-    if (!getValid().get()) { throw new MemoryCloseException("Already closed"); }
-    ResourceImpl.checkThread(owner);
-  }
-
   public void close() {
-    checkValidAndThread(); //we must be valid and called from the owner thread
     try {
       if (deallocator.deallocate(false)) {
         // This Cleaner.clean() call effectively just removes the Cleaner from the internal linked
@@ -138,18 +125,14 @@ class AllocateDirectWritableMap {
         cleaner.clean();
       }
 
-    } catch (final Exception e) {
-        throw new MemoryCloseException("Memory-Mapped File: " + file.getName() + " " + e);
+    } catch (final Exception e) { throw new IllegalStateException("Attempted close of Memory-Mapped File: "
+        + file.getName() + " " + e);
     } finally {
       ResourceImpl.reachabilityFence(this);
     }
   }
 
   public void force() {
-    checkValidAndThread();
-    if (resourceReadOnly) {
-      throw new ReadOnlyException("MemoryImpl Mapped File is Read Only.");
-    }
     try {
       MAPPED_BYTE_BUFFER_FORCE0_METHOD
           //force0 is effectively static, so ZERO_READ_ONLY_DIRECT_BYTE_BUFFER is not modified
@@ -158,7 +141,7 @@ class AllocateDirectWritableMap {
               nativeBaseOffset,
               capacityBytes);
     } catch (final IOException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
-      throw new RuntimeException(String.format("Encountered %s exception in force. " + e.getClass()));
+      throw new RuntimeException(String.format("Encountered %s exception in force. " + e.toString()));
     }
   }
 
@@ -171,15 +154,13 @@ class AllocateDirectWritableMap {
   }
 
   public boolean isLoaded() {
-    checkValidAndThread();
     try {
-      final int pageCount = NioBits.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,
               nativeBaseOffset,
               capacityBytes,
-              pageCount);
+              pageCount(capacityBytes));
     } catch (final  IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
       throw new RuntimeException(
               String.format("Encountered %s exception while loading", e.getClass()));
@@ -187,15 +168,13 @@ class AllocateDirectWritableMap {
   }
 
   public void load() {
-    checkValidAndThread();
     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 count = pageCount(capacityBytes);
     long offset = nativeBaseOffset;
     for (int i = 0; i < count; i++) {
       unsafe.getByte(offset);
-      offset += ps;
+      offset += pageSize;
     }
   }
 
@@ -218,6 +197,10 @@ class AllocateDirectWritableMap {
     }
   }
 
+  private static int pageCount(final long bytes) {
+    return (int)((bytes + pageSize) - 1L) / pageSize;
+  }
+
   //Does the actual mapping work, resourceReadOnly must already be set
   private static RandomAccessFile mapper(final File file, final long fileOffset,
       final long capacityBytes, final boolean resourceReadOnly)  {
@@ -291,15 +274,15 @@ class AllocateDirectWritableMap {
     }
 
     @Override
-    public void run() throws MemoryCloseException {
+    public void run() throws IllegalStateException {
       deallocate(true);
     }
 
-    boolean deallocate(final boolean calledFromCleaner) throws MemoryCloseException {
+    boolean deallocate(final boolean calledFromCleaner) throws IllegalStateException {
       if (valid.change()) {
         if (calledFromCleaner) {
           // Warn about non-deterministic resource cleanup.
-          LOG.warning("A WritableMapHandleImpl was not closed manually");
+          //LOG.warning("A WritableMapHandleImpl was not closed manually");
         }
         unmap();
         return true;
@@ -311,13 +294,12 @@ class AllocateDirectWritableMap {
      * Removes existing mapping.  <i>unmap0</i> is a native method in FileChannelImpl.c. See
      * reference at top of class.
      */
-    private void unmap() throws MemoryCloseException {
+    private void unmap() throws IllegalStateException {
       try {
         FILE_CHANNEL_IMPL_UNMAP0_METHOD.invoke(myFc, actualNativeBaseOffset, myCapacity);
         myRaf.close();
       } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException | IOException e) {
-        throw new MemoryCloseException(
-            String.format("Encountered %s exception while freeing memory", e.getClass()));
+        throw new IllegalStateException(String.format("Encountered %s exception while freeing memory", e.getClass()));
       }
     }
   } //End of class Deallocator
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBNonNativeWritableBufferImpl.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBNonNativeWritableBufferImpl.java
index f6888de..c209eb8 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBNonNativeWritableBufferImpl.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBNonNativeWritableBufferImpl.java
@@ -34,12 +34,11 @@ import org.apache.datasketches.memory.WritableBuffer;
 final class BBNonNativeWritableBufferImpl extends NonNativeWritableBufferImpl {
   private final ByteBuffer byteBuf; //holds a reference to a ByteBuffer until we are done with it.
   private final Object unsafeObj;
-  private final long nativeBaseOffset;
-  private final long offsetBytes;
+  private final long nativeBaseOffset; //raw off-heap address of allocation base if ByteBuffer direct, else 0
+  private final long offsetBytes;      //from the root resource including original ByteBuffer position or region offset
   private final long capacityBytes;
   private final int typeId;
-  private long cumOffsetBytes;
-  private final MemoryRequestServer memReqSvr;
+  private long cumOffsetBytes;         //includes array header if heap, and nativeBaseOffset if off-heap
 
   BBNonNativeWritableBufferImpl(
       final Object unsafeObj,
@@ -59,6 +58,10 @@ final class BBNonNativeWritableBufferImpl extends NonNativeWritableBufferImpl {
     this.cumOffsetBytes = cumOffsetBytes;
     this.memReqSvr = memReqSvr;
     this.byteBuf = byteBuf;
+    if ((this.owner != null) && (this.owner != Thread.currentThread())) {
+      throw new IllegalStateException(THREAD_EXCEPTION_TEXT);
+    }
+    this.owner = Thread.currentThread();
   }
 
   @Override
@@ -112,52 +115,39 @@ final class BBNonNativeWritableBufferImpl extends NonNativeWritableBufferImpl {
     }
   }
 
+  @Override
+  public ByteBuffer getByteBuffer() {
+    return byteBuf;
+  }
+
   @Override
   public long getCapacity() {
-    checkValid();
     return capacityBytes;
   }
 
   @Override
   public long getCumulativeOffset() {
-    checkValid();
     return cumOffsetBytes;
   }
 
-  @Override
-  public MemoryRequestServer getMemoryRequestServer() {
-    checkValid();
-    return memReqSvr;
-  }
-
   @Override
   public long getNativeBaseOffset() {
-    checkValid();
     return nativeBaseOffset;
   }
 
   @Override
   public long getTotalOffset() {
-    checkValid();
     return offsetBytes;
   }
 
   @Override
   int getTypeId() {
-    checkValid();
     return typeId;
   }
 
   @Override
   Object getUnsafeObject() {
-    checkValid();
     return unsafeObj;
   }
 
-  @Override
-  public ByteBuffer getByteBuffer() {
-    checkValid();
-    return byteBuf;
-  }
-
 }
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBNonNativeWritableMemoryImpl.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBNonNativeWritableMemoryImpl.java
index 16ea394..976fc5d 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBNonNativeWritableMemoryImpl.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBNonNativeWritableMemoryImpl.java
@@ -34,12 +34,11 @@ import org.apache.datasketches.memory.WritableMemory;
 final class BBNonNativeWritableMemoryImpl extends NonNativeWritableMemoryImpl {
   private final ByteBuffer byteBuf; //holds a reference to a ByteBuffer until we are done with it.
   private final Object unsafeObj;
-  private final long nativeBaseOffset;
-  private final long offsetBytes;
+  private final long nativeBaseOffset; //raw off-heap address of allocation base if ByteBuffer direct, else 0
+  private final long offsetBytes;      //from the root resource including original ByteBuffer position or region offset
   private final long capacityBytes;
   private final int typeId;
-  private long cumOffsetBytes;
-  private final MemoryRequestServer memReqSvr;
+  private long cumOffsetBytes;         //includes array header if heap, and nativeBaseOffset if off-heap
 
   BBNonNativeWritableMemoryImpl(
       final Object unsafeObj,
@@ -59,6 +58,10 @@ final class BBNonNativeWritableMemoryImpl extends NonNativeWritableMemoryImpl {
     this.cumOffsetBytes = cumOffsetBytes;
     this.memReqSvr = memReqSvr;
     this.byteBuf = byteBuf;
+    if ((this.owner != null) && (this.owner != Thread.currentThread())) {
+      throw new IllegalStateException(THREAD_EXCEPTION_TEXT);
+    }
+    this.owner = Thread.currentThread();
   }
 
   @Override
@@ -97,52 +100,39 @@ final class BBNonNativeWritableMemoryImpl extends NonNativeWritableMemoryImpl {
     }
   }
 
+  @Override
+  public ByteBuffer getByteBuffer() {
+    return byteBuf;
+  }
+
   @Override
   public long getCapacity() {
-    checkValid();
     return capacityBytes;
   }
 
   @Override
   public long getCumulativeOffset() {
-    checkValid();
     return cumOffsetBytes;
   }
 
-  @Override
-  public MemoryRequestServer getMemoryRequestServer() {
-    checkValid();
-    return memReqSvr;
-  }
-
   @Override
   public long getNativeBaseOffset() {
-    checkValid();
     return nativeBaseOffset;
   }
 
   @Override
   public long getTotalOffset() {
-    checkValid();
     return offsetBytes;
   }
 
   @Override
   int getTypeId() {
-    checkValid();
     return typeId;
   }
 
   @Override
   Object getUnsafeObject() {
-    checkValid();
     return unsafeObj;
   }
 
-  @Override
-  public ByteBuffer getByteBuffer() {
-    checkValid();
-    return byteBuf;
-  }
-
 }
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBWritableBufferImpl.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBWritableBufferImpl.java
index 2e3ee93..7aedb79 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBWritableBufferImpl.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBWritableBufferImpl.java
@@ -34,12 +34,11 @@ import org.apache.datasketches.memory.WritableBuffer;
 final class BBWritableBufferImpl extends NativeWritableBufferImpl {
   private final ByteBuffer byteBuf;    //holds a reference to a ByteBuffer until we are done with it.
   private final Object unsafeObj;
-  private final long nativeBaseOffset; //raw off-heap address of root allocation (whether direct or ByteBuffer)
+  private final long nativeBaseOffset; //raw off-heap address of allocation base if ByteBuffer direct, else 0
   private final long offsetBytes;      //from the root resource including original ByteBuffer position or split offset
   private final long capacityBytes;
   private final int typeId;
-  private long cumOffsetBytes;         //includes array header if heap and nativeBaseOffset if off-heap
-  private final MemoryRequestServer memReqSvr;
+  private long cumOffsetBytes;         //includes array header if heap, and nativeBaseOffset if off-heap
 
   BBWritableBufferImpl(
       final Object unsafeObj,
@@ -59,6 +58,10 @@ final class BBWritableBufferImpl extends NativeWritableBufferImpl {
     this.cumOffsetBytes = cumOffsetBytes;
     this.memReqSvr = memReqSvr;
     this.byteBuf = byteBuf;
+    if ((this.owner != null) && (this.owner != Thread.currentThread())) {
+      throw new IllegalStateException(THREAD_EXCEPTION_TEXT);
+    }
+    this.owner = Thread.currentThread();
   }
 
   @Override
@@ -112,52 +115,39 @@ final class BBWritableBufferImpl extends NativeWritableBufferImpl {
     }
   }
 
+  @Override
+  public ByteBuffer getByteBuffer() {
+    return byteBuf;
+  }
+
   @Override
   public long getCapacity() {
-    checkValid();
     return capacityBytes;
   }
 
   @Override
   public long getCumulativeOffset() {
-    checkValid();
     return cumOffsetBytes;
   }
 
-  @Override
-  public MemoryRequestServer getMemoryRequestServer() {
-    checkValid();
-    return memReqSvr;
-  }
-
   @Override
   public long getNativeBaseOffset() {
-    checkValid();
     return nativeBaseOffset;
   }
 
   @Override
   public long getTotalOffset() {
-    checkValid();
     return offsetBytes;
   }
 
   @Override
   int getTypeId() {
-    checkValid();
     return typeId;
   }
 
   @Override
   Object getUnsafeObject() {
-    checkValid();
     return unsafeObj;
   }
 
-  @Override
-  public ByteBuffer getByteBuffer() {
-    checkValid();
-    return byteBuf;
-  }
-
 }
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBWritableMemoryImpl.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBWritableMemoryImpl.java
index 0d09c08..bb77a1e 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBWritableMemoryImpl.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBWritableMemoryImpl.java
@@ -34,12 +34,11 @@ import org.apache.datasketches.memory.WritableMemory;
 final class BBWritableMemoryImpl extends NativeWritableMemoryImpl {
   private final ByteBuffer byteBuf; //holds a reference to a ByteBuffer until we are done with it.
   private final Object unsafeObj;
-  private final long nativeBaseOffset; //raw off-heap address of root allocation (whether direct or ByteBuffer)
+  private final long nativeBaseOffset; //raw off-heap address of allocation base if ByteBuffer direct, else 0
   private final long offsetBytes;      //from the root resource including original ByteBuffer position or region offset
   private final long capacityBytes;
   private final int typeId;
-  private long cumOffsetBytes;         //includes array header if heap and nativeBaseOffset if off-heap
-  private final MemoryRequestServer memReqSvr;
+  private long cumOffsetBytes;         //includes array header if heap, and nativeBaseOffset if off-heap
 
   BBWritableMemoryImpl(
       final Object unsafeObj,
@@ -59,6 +58,10 @@ final class BBWritableMemoryImpl extends NativeWritableMemoryImpl {
     this.cumOffsetBytes = cumOffsetBytes;
     this.memReqSvr = memReqSvr;
     this.byteBuf = byteBuf;
+    if ((this.owner != null) && (this.owner != Thread.currentThread())) {
+      throw new IllegalStateException(THREAD_EXCEPTION_TEXT);
+    }
+    this.owner = Thread.currentThread();
   }
 
   @Override
@@ -97,51 +100,39 @@ final class BBWritableMemoryImpl extends NativeWritableMemoryImpl {
     }
   }
 
+  @Override
+  public ByteBuffer getByteBuffer() {
+    return byteBuf;
+  }
+
   @Override
   public long getCapacity() {
-    checkValid();
     return capacityBytes;
   }
 
   @Override
   public long getCumulativeOffset() {
-    checkValid();
     return cumOffsetBytes;
   }
 
-  @Override
-  public MemoryRequestServer getMemoryRequestServer() {
-    checkValid();
-    return memReqSvr;
-  }
-
   @Override
   public long getNativeBaseOffset() {
-    checkValid();
     return nativeBaseOffset;
   }
 
   @Override
   public long getTotalOffset() {
-    checkValid();
     return offsetBytes;
   }
 
   @Override
   int getTypeId() {
-    checkValid();
     return typeId;
   }
 
   @Override
   Object getUnsafeObject() {
-    checkValid();
     return unsafeObj;
   }
 
-  @Override
-  public ByteBuffer getByteBuffer() {
-    checkValid();
-    return byteBuf;
-  }
 }
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BaseBufferImpl.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BaseBufferImpl.java
index eac45de..75f9dae 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BaseBufferImpl.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BaseBufferImpl.java
@@ -21,7 +21,6 @@ package org.apache.datasketches.memory.internal;
 
 import org.apache.datasketches.memory.BaseBuffer;
 import org.apache.datasketches.memory.BufferPositionInvariantsException;
-import org.apache.datasketches.memory.ReadOnlyException;
 
 /**
  * A new positional API. This is different from and simpler than Java BufferImpl positional approach.
@@ -97,31 +96,12 @@ public abstract class BaseBufferImpl extends ResourceImpl implements BaseBuffer
 
   @Override
   public final BaseBufferImpl setPosition(final long position) {
-    checkInvariants(start, position, end, capacity);
-    pos = position;
-    return this;
+    return setStartPositionEnd(start, position, end);
   }
 
   @Override
-  public final BaseBufferImpl setAndCheckPosition(final long position) {
-    checkInvariants(start, position, end, capacity);
-    pos = position;
-    return this;
-  }
-
-  @Override
-  public final BaseBufferImpl setStartPositionEnd(final long start, final long position,
-      final long end) {
-    checkInvariants(start, position, end, capacity);
-    this.start = start;
-    this.end = end;
-    pos = position;
-    return this;
-  }
-
-  @Override
-  public final BaseBufferImpl setAndCheckStartPositionEnd(final long start, final long position,
-      final long end) {
+  public final BaseBufferImpl setStartPositionEnd(final long start, final long position, final long end) {
+    checkValid();
     checkInvariants(start, position, end, capacity);
     this.start = start;
     this.end = end;
@@ -131,7 +111,7 @@ public abstract class BaseBufferImpl extends ResourceImpl implements BaseBuffer
 
   //RESTRICTED
 
-  //checks are used for arrays and apply at runtime
+  //used for buffer arrays and apply at runtime
   final void incrementAndCheckPositionForRead(final long position, final long increment) {
     checkValid();
     final long newPos = position + increment;
@@ -139,30 +119,21 @@ public abstract class BaseBufferImpl extends ResourceImpl implements BaseBuffer
     pos = newPos;
   }
 
+  //used for buffer arrays and apply at runtime
   final void incrementAndCheckPositionForWrite(final long position, final long increment) {
-    checkValidForWrite();
-    final long newPos = position + increment;
-    checkInvariants(start, newPos, end, capacity);
-    pos = newPos;
-  }
-
-  final void checkValidForWrite() {
-    checkValid();
-    if (isReadOnly()) {
-      throw new ReadOnlyException("BufferImpl is read-only.");
-    }
+    checkNotReadOnly();
+    incrementAndCheckPositionForRead(position, increment);
   }
 
   /**
    * The invariants equation is: {@code 0 <= start <= position <= end <= capacity}.
-   * If this equation is violated an <i>IllegalArgumentException</i> will be thrown.
+   * If this equation is violated a <i>BufferPositionInvariantsException</i> will be thrown.
    * @param start the lowest start position
    * @param pos the current position
    * @param end the highest position
    * @param cap the capacity of the backing buffer.
    */
-  static final void checkInvariants(final long start, final long pos, final long end,
-        final long cap) {
+  static final void checkInvariants(final long start, final long pos, final long end, final long cap) {
     if ((start | pos | end | cap | (pos - start) | (end - pos) | (cap - end) ) < 0L) {
       throw new BufferPositionInvariantsException(
           "Violation of Invariants: "
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BaseWritableBufferImpl.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BaseWritableBufferImpl.java
index 438a55f..61b3725 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BaseWritableBufferImpl.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BaseWritableBufferImpl.java
@@ -82,7 +82,7 @@ public abstract class BaseWritableBufferImpl extends BaseBufferImpl implements W
   @Override
   public Buffer region(final long offsetBytes, final long capacityBytes, final ByteOrder byteOrder) {
     final WritableBuffer buf = writableRegionImpl(offsetBytes, capacityBytes, true, byteOrder);
-    buf.setAndCheckStartPositionEnd(0, 0, capacityBytes);
+    buf.setStartPositionEnd(0, 0, capacityBytes);
     return buf;
   }
 
@@ -94,7 +94,7 @@ public abstract class BaseWritableBufferImpl extends BaseBufferImpl implements W
   @Override
   public WritableBuffer writableRegion(final long offsetBytes, final long capacityBytes, final ByteOrder byteOrder) {
     final WritableBuffer wbuf = writableRegionImpl(offsetBytes, capacityBytes, false, byteOrder);
-    wbuf.setAndCheckStartPositionEnd(0, 0, capacityBytes);
+    wbuf.setStartPositionEnd(0, 0, capacityBytes);
     return wbuf;
   }
 
@@ -405,7 +405,7 @@ public abstract class BaseWritableBufferImpl extends BaseBufferImpl implements W
 
   @Override
   public final void fill(final byte value) {
-    checkValidForWrite();
+    checkNotReadOnly();
     long pos = getPosition();
     long len = getEnd() - pos;
     checkInvariants(getStart(), pos + len, getEnd(), getCapacity());
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/CompareAndCopy.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/CompareAndCopy.java
index 2bb02fa..052b84e 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/CompareAndCopy.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/CompareAndCopy.java
@@ -65,7 +65,7 @@ final class CompareAndCopy {
     return (cap1 == cap2) && equals(state1, 0, state2, 0, cap1);
   }
 
-  //Developer notes: this is subtlely different from (campare == 0) in that this has an early
+  //Developer notes: this is subtlety different from (compare == 0) in that this has an early
   // stop if the arrays and offsets are the same as there is only one length.  Also this can take
   // advantage of chunking with longs, while compare cannot.
   static boolean equals(
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/DirectNonNativeWritableBufferImpl.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/DirectNonNativeWritableBufferImpl.java
index c98916c..f4da0d3 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/DirectNonNativeWritableBufferImpl.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/DirectNonNativeWritableBufferImpl.java
@@ -36,7 +36,6 @@ final class DirectNonNativeWritableBufferImpl extends NonNativeWritableBufferImp
   private final long capacityBytes;
   private final int typeId;
   private long cumOffsetBytes;
-  private final MemoryRequestServer memReqSvr;
 
   DirectNonNativeWritableBufferImpl(
       final AllocateDirect direct,
@@ -52,6 +51,10 @@ final class DirectNonNativeWritableBufferImpl extends NonNativeWritableBufferImp
     this.typeId = removeNnBuf(typeId) | DIRECT | BUFFER | NONNATIVE; //initially cannot be ReadOnly
     this.cumOffsetBytes = cumOffsetBytes;
     this.memReqSvr = memReqSvr;
+    if ((this.owner != null) && (this.owner != Thread.currentThread())) {
+      throw new IllegalStateException(THREAD_EXCEPTION_TEXT);
+    }
+    this.owner = Thread.currentThread();
   }
 
   @Override
@@ -63,6 +66,7 @@ final class DirectNonNativeWritableBufferImpl extends NonNativeWritableBufferImp
     final long newOffsetBytes = offsetBytes + regionOffsetBytes;
     final long newCumOffsetBytes = cumOffsetBytes + regionOffsetBytes;
     int typeIdOut = removeNnBuf(typeId) | BUFFER | REGION | (readOnly ? READONLY : 0);
+
     if (Util.isNativeByteOrder(byteOrder)) {
       typeIdOut |= NATIVE;
       return new DirectWritableBufferImpl(
@@ -105,8 +109,10 @@ final class DirectNonNativeWritableBufferImpl extends NonNativeWritableBufferImp
   }
 
   @Override
-  public boolean isValid() {
-    return direct.getValid().get();
+  public void close() {
+    checkValid();
+    checkThread(owner);
+    direct.close();
   }
 
   @Override
@@ -115,26 +121,13 @@ final class DirectNonNativeWritableBufferImpl extends NonNativeWritableBufferImp
     return capacityBytes;
   }
 
-  @Override
-  public void close() {
-    direct.close();
-  }
-
   @Override
   public long getCumulativeOffset() {
-    checkValid();
     return cumOffsetBytes;
   }
 
-  @Override
-  public MemoryRequestServer getMemoryRequestServer() {
-    checkValid();
-    return memReqSvr;
-  }
-
   @Override
   public long getNativeBaseOffset() {
-    checkValid();
     return direct.getNativeBaseOffset();
   }
 
@@ -146,14 +139,17 @@ final class DirectNonNativeWritableBufferImpl extends NonNativeWritableBufferImp
 
   @Override
   int getTypeId() {
-    checkValid();
     return typeId;
   }
 
   @Override
   Object getUnsafeObject() {
-    checkValid();
     return null;
   }
 
+  @Override
+  public boolean isValid() {
+    return direct.getValid().get();
+  }
+
 }
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/DirectNonNativeWritableMemoryImpl.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/DirectNonNativeWritableMemoryImpl.java
index 7293386..59b1059 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/DirectNonNativeWritableMemoryImpl.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/DirectNonNativeWritableMemoryImpl.java
@@ -36,7 +36,6 @@ final class DirectNonNativeWritableMemoryImpl extends NonNativeWritableMemoryImp
   private final long capacityBytes;
   private final int typeId;
   private long cumOffsetBytes;
-  private final MemoryRequestServer memReqSvr;
 
   DirectNonNativeWritableMemoryImpl(
       final AllocateDirect direct,
@@ -52,6 +51,10 @@ final class DirectNonNativeWritableMemoryImpl extends NonNativeWritableMemoryImp
     this.typeId = removeNnBuf(typeId) | DIRECT | MEMORY | NONNATIVE; //initially cannot be ReadOnly
     this.cumOffsetBytes = cumOffsetBytes;
     this.memReqSvr = memReqSvr;
+    if ((this.owner != null) && (this.owner != Thread.currentThread())) {
+      throw new IllegalStateException(THREAD_EXCEPTION_TEXT);
+    }
+    this.owner = Thread.currentThread();
   }
 
   @Override
@@ -91,8 +94,10 @@ final class DirectNonNativeWritableMemoryImpl extends NonNativeWritableMemoryImp
   }
 
   @Override
-  public boolean isValid() {
-    return direct.getValid().get();
+  public void close() {
+    checkValid();
+    checkThread(owner);
+    direct.close();
   }
 
   @Override
@@ -101,27 +106,13 @@ final class DirectNonNativeWritableMemoryImpl extends NonNativeWritableMemoryImp
     return capacityBytes;
   }
 
-  @Override
-  public void close() {
-    direct.close();
-  }
-
   @Override
   public long getCumulativeOffset() {
-    checkValid();
     return cumOffsetBytes;
   }
 
-  @Override
-  public MemoryRequestServer getMemoryRequestServer() {
-    checkValid();
-    return memReqSvr;
-  }
-
   @Override
   public long getNativeBaseOffset() {
-    checkValid();
-    checkValid();
     return direct.getNativeBaseOffset();
   }
 
@@ -133,14 +124,17 @@ final class DirectNonNativeWritableMemoryImpl extends NonNativeWritableMemoryImp
 
   @Override
   int getTypeId() {
-    checkValid();
     return typeId;
   }
 
   @Override
   Object getUnsafeObject() {
-    checkValid();
     return null;
   }
 
+  @Override
+  public boolean isValid() {
+    return direct.getValid().get();
+  }
+
 }
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/DirectWritableBufferImpl.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/DirectWritableBufferImpl.java
index c268024..125b235 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/DirectWritableBufferImpl.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/DirectWritableBufferImpl.java
@@ -36,7 +36,6 @@ final class DirectWritableBufferImpl extends NativeWritableBufferImpl {
   private final long capacityBytes;
   private final int typeId;
   private long cumOffsetBytes;
-  private final MemoryRequestServer memReqSvr;
 
   DirectWritableBufferImpl(
       final AllocateDirect direct,
@@ -52,6 +51,10 @@ final class DirectWritableBufferImpl extends NativeWritableBufferImpl {
     this.typeId = removeNnBuf(typeId) | DIRECT | BUFFER | NATIVE; //initially cannot be ReadOnly
     this.cumOffsetBytes = cumOffsetBytes;
     this.memReqSvr = memReqSvr;
+    if ((this.owner != null) && (this.owner != Thread.currentThread())) {
+      throw new IllegalStateException(THREAD_EXCEPTION_TEXT);
+    }
+    this.owner = Thread.currentThread();
   }
 
   @Override
@@ -106,8 +109,10 @@ final class DirectWritableBufferImpl extends NativeWritableBufferImpl {
   }
 
   @Override
-  public boolean isValid() {
-    return direct.getValid().get();
+  public void close() {
+    checkValid();
+    checkThread(owner);
+    direct.close();
   }
 
   @Override
@@ -116,26 +121,13 @@ final class DirectWritableBufferImpl extends NativeWritableBufferImpl {
     return capacityBytes;
   }
 
-  @Override
-  public void close() {
-    direct.close();
-  }
-
   @Override
   public long getCumulativeOffset() {
-    checkValid();
     return cumOffsetBytes;
   }
 
-  @Override
-  public MemoryRequestServer getMemoryRequestServer() {
-    checkValid();
-    return memReqSvr;
-  }
-
   @Override
   public long getNativeBaseOffset() {
-    checkValid();
     return direct.getNativeBaseOffset();
   }
 
@@ -147,14 +139,17 @@ final class DirectWritableBufferImpl extends NativeWritableBufferImpl {
 
   @Override
   int getTypeId() {
-    checkValid();
     return typeId;
   }
 
   @Override
   Object getUnsafeObject() {
-    checkValid();
     return null;
   }
 
+  @Override
+  public boolean isValid() {
+    return direct.getValid().get();
+  }
+
 }
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/DirectWritableMemoryImpl.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/DirectWritableMemoryImpl.java
index 1dbd041..c2a6b97 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/DirectWritableMemoryImpl.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/DirectWritableMemoryImpl.java
@@ -36,7 +36,6 @@ final class DirectWritableMemoryImpl extends NativeWritableMemoryImpl {
   private final long capacityBytes;
   private final int typeId;
   private long cumOffsetBytes;
-  private final MemoryRequestServer memReqSvr;
 
   DirectWritableMemoryImpl(
       final AllocateDirect direct,
@@ -52,6 +51,10 @@ final class DirectWritableMemoryImpl extends NativeWritableMemoryImpl {
     this.typeId = removeNnBuf(typeId) | DIRECT | MEMORY | NATIVE; //initially cannot be ReadOnly
     this.cumOffsetBytes = cumOffsetBytes;
     this.memReqSvr = memReqSvr;
+    if ((this.owner != null) && (this.owner != Thread.currentThread())) {
+      throw new IllegalStateException(THREAD_EXCEPTION_TEXT);
+    }
+    this.owner = Thread.currentThread();
   }
 
   @Override
@@ -91,8 +94,10 @@ final class DirectWritableMemoryImpl extends NativeWritableMemoryImpl {
   }
 
   @Override
-  public boolean isValid() {
-    return direct.getValid().get();
+  public void close() {
+    checkValid();
+    checkThread(owner);
+    direct.close();
   }
 
   @Override
@@ -101,26 +106,13 @@ final class DirectWritableMemoryImpl extends NativeWritableMemoryImpl {
     return capacityBytes;
   }
 
-  @Override
-  public void close() {
-    direct.close();
-  }
-
   @Override
   public long getCumulativeOffset() {
-    checkValid();
     return cumOffsetBytes;
   }
 
-  @Override
-  public MemoryRequestServer getMemoryRequestServer() {
-    checkValid();
-    return memReqSvr;
-  }
-
   @Override
   public long getNativeBaseOffset() {
-    checkValid();
     return direct.getNativeBaseOffset();
   }
 
@@ -132,14 +124,17 @@ final class DirectWritableMemoryImpl extends NativeWritableMemoryImpl {
 
   @Override
   int getTypeId() {
-    checkValid();
     return typeId;
   }
 
   @Override
   Object getUnsafeObject() {
-    checkValid();
     return null;
   }
 
+  @Override
+  public boolean isValid() {
+    return direct.getValid().get();
+  }
+
 }
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/HeapNonNativeWritableBufferImpl.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/HeapNonNativeWritableBufferImpl.java
index 8143b2e..9ad30b3 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/HeapNonNativeWritableBufferImpl.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/HeapNonNativeWritableBufferImpl.java
@@ -36,7 +36,6 @@ final class HeapNonNativeWritableBufferImpl extends NonNativeWritableBufferImpl
   private final long capacityBytes;
   private final int typeId;
   private long cumOffsetBytes;
-  private final MemoryRequestServer memReqSvr;
 
   HeapNonNativeWritableBufferImpl(
       final Object unsafeObj,
@@ -52,6 +51,10 @@ final class HeapNonNativeWritableBufferImpl extends NonNativeWritableBufferImpl
     this.typeId = removeNnBuf(typeId) | HEAP | BUFFER | NONNATIVE;
     this.cumOffsetBytes = cumOffsetBytes;
     this.memReqSvr = memReqSvr;
+    if ((this.owner != null) && (this.owner != Thread.currentThread())) {
+      throw new IllegalStateException(THREAD_EXCEPTION_TEXT);
+    }
+    this.owner = Thread.currentThread();
   }
 
   @Override
@@ -107,43 +110,31 @@ final class HeapNonNativeWritableBufferImpl extends NonNativeWritableBufferImpl
 
   @Override
   public long getCapacity() {
-    checkValid();
     return capacityBytes;
   }
 
   @Override
   public long getCumulativeOffset() {
-    checkValid();
     return cumOffsetBytes;
   }
 
-  @Override
-  public MemoryRequestServer getMemoryRequestServer() {
-    checkValid();
-    return memReqSvr;
-  }
-
   @Override
   public long getNativeBaseOffset() {
-    checkValid();
     return 0;
   }
 
   @Override
   public long getTotalOffset() {
-    checkValid();
     return offsetBytes;
   }
 
   @Override
   int getTypeId() {
-    checkValid();
     return typeId;
   }
 
   @Override
   Object getUnsafeObject() {
-    checkValid();
     return unsafeObj;
   }
 
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/HeapNonNativeWritableMemoryImpl.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/HeapNonNativeWritableMemoryImpl.java
index a72fc10..f900925 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/HeapNonNativeWritableMemoryImpl.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/HeapNonNativeWritableMemoryImpl.java
@@ -36,7 +36,6 @@ final class HeapNonNativeWritableMemoryImpl extends NonNativeWritableMemoryImpl
   private final long capacityBytes;
   private final int typeId;
   private long cumOffsetBytes;
-  private final MemoryRequestServer memReqSvr;
 
   HeapNonNativeWritableMemoryImpl(
       final Object unsafeObj,
@@ -52,6 +51,10 @@ final class HeapNonNativeWritableMemoryImpl extends NonNativeWritableMemoryImpl
     this.typeId = removeNnBuf(typeId) | HEAP | MEMORY | NONNATIVE;
     this.cumOffsetBytes = cumOffsetBytes;
     this.memReqSvr = memReqSvr;
+    if ((this.owner != null) && (this.owner != Thread.currentThread())) {
+      throw new IllegalStateException(THREAD_EXCEPTION_TEXT);
+    }
+    this.owner = Thread.currentThread();
   }
 
   @Override
@@ -92,43 +95,31 @@ final class HeapNonNativeWritableMemoryImpl extends NonNativeWritableMemoryImpl
 
   @Override
   public long getCapacity() {
-    checkValid();
     return capacityBytes;
   }
 
   @Override
   public long getCumulativeOffset() {
-    checkValid();
     return cumOffsetBytes;
   }
 
-  @Override
-  public MemoryRequestServer getMemoryRequestServer() {
-    checkValid();
-    return memReqSvr;
-  }
-
   @Override
   public long getNativeBaseOffset() {
-    checkValid();
     return 0;
   }
 
   @Override
   public long getTotalOffset() {
-    checkValid();
     return offsetBytes;
   }
 
   @Override
   int getTypeId() {
-    checkValid();
     return typeId;
   }
 
   @Override
   Object getUnsafeObject() {
-    checkValid();
     return unsafeObj;
   }
 
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/HeapWritableBufferImpl.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/HeapWritableBufferImpl.java
index 1e270ac..fcfea49 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/HeapWritableBufferImpl.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/HeapWritableBufferImpl.java
@@ -36,7 +36,6 @@ final class HeapWritableBufferImpl extends NativeWritableBufferImpl {
   private final long capacityBytes;
   private final int typeId;
   private long cumOffsetBytes;
-  private final MemoryRequestServer memReqSvr;
 
   HeapWritableBufferImpl(
       final Object unsafeObj,
@@ -52,6 +51,10 @@ final class HeapWritableBufferImpl extends NativeWritableBufferImpl {
     this.typeId = removeNnBuf(typeId) | HEAP | BUFFER | NATIVE;
     this.cumOffsetBytes = cumOffsetBytes;
     this.memReqSvr = memReqSvr;
+    if ((this.owner != null) && (this.owner != Thread.currentThread())) {
+      throw new IllegalStateException(THREAD_EXCEPTION_TEXT);
+    }
+    this.owner = Thread.currentThread();
   }
 
   @Override
@@ -107,43 +110,31 @@ final class HeapWritableBufferImpl extends NativeWritableBufferImpl {
 
   @Override
   public long getCapacity() {
-    checkValid();
     return capacityBytes;
   }
 
   @Override
   public long getCumulativeOffset() {
-    checkValid();
     return cumOffsetBytes;
   }
 
-  @Override
-  public MemoryRequestServer getMemoryRequestServer() {
-    checkValid();
-    return memReqSvr;
-  }
-
   @Override
   public long getNativeBaseOffset() {
-    checkValid();
     return 0;
   }
 
   @Override
   public long getTotalOffset() {
-    checkValid();
     return offsetBytes;
   }
 
   @Override
   int getTypeId() {
-    checkValid();
     return typeId;
   }
 
   @Override
   Object getUnsafeObject() {
-    checkValid();
     return unsafeObj;
   }
 
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/HeapWritableMemoryImpl.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/HeapWritableMemoryImpl.java
index 82f3a7a..7cca142 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/HeapWritableMemoryImpl.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/HeapWritableMemoryImpl.java
@@ -36,7 +36,6 @@ final class HeapWritableMemoryImpl extends NativeWritableMemoryImpl {
   private final long capacityBytes;
   private final int typeId;
   private long cumOffsetBytes;
-  private final MemoryRequestServer memReqSvr;
 
   HeapWritableMemoryImpl(
       final Object unsafeObj,
@@ -52,6 +51,10 @@ final class HeapWritableMemoryImpl extends NativeWritableMemoryImpl {
     this.typeId = removeNnBuf(typeId) | HEAP | MEMORY | NATIVE;
     this.cumOffsetBytes = cumOffsetBytes;
     this.memReqSvr = memReqSvr;
+    if ((this.owner != null) && (this.owner != Thread.currentThread())) {
+      throw new IllegalStateException(THREAD_EXCEPTION_TEXT);
+    }
+    this.owner = Thread.currentThread();
   }
 
   @Override
@@ -92,43 +95,31 @@ final class HeapWritableMemoryImpl extends NativeWritableMemoryImpl {
 
   @Override
   public long getCapacity() {
-    checkValid();
     return capacityBytes;
   }
 
   @Override
   public long getCumulativeOffset() {
-    checkValid();
     return cumOffsetBytes;
   }
 
-  @Override
-  public MemoryRequestServer getMemoryRequestServer() {
-    checkValid();
-    return memReqSvr;
-  }
-
   @Override
   public long getNativeBaseOffset() {
-    checkValid();
     return 0;
   }
 
   @Override
   public long getTotalOffset() {
-    checkValid();
     return offsetBytes;
   }
 
   @Override
   int getTypeId() {
-    checkValid();
     return typeId;
   }
 
   @Override
   Object getUnsafeObject() {
-    checkValid();
     return unsafeObj;
   }
 
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapNonNativeWritableBufferImpl.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapNonNativeWritableBufferImpl.java
index 01afc10..692c5ca 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapNonNativeWritableBufferImpl.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapNonNativeWritableBufferImpl.java
@@ -21,7 +21,6 @@ package org.apache.datasketches.memory.internal;
 
 import java.nio.ByteOrder;
 
-import org.apache.datasketches.memory.MemoryRequestServer;
 import org.apache.datasketches.memory.WritableBuffer;
 
 /**
@@ -49,6 +48,10 @@ final class MapNonNativeWritableBufferImpl extends NonNativeWritableBufferImpl {
     this.capacityBytes = capacityBytes;
     this.typeId = removeNnBuf(typeId) | MAP | BUFFER | NONNATIVE;
     this.cumOffsetBytes = cumOffsetBytes;
+    if ((this.owner != null) && (this.owner != Thread.currentThread())) {
+      throw new IllegalStateException(THREAD_EXCEPTION_TEXT);
+    }
+    this.owner = Thread.currentThread();
   }
 
   @Override
@@ -103,31 +106,33 @@ final class MapNonNativeWritableBufferImpl extends NonNativeWritableBufferImpl {
   }
 
   @Override
-  public boolean isValid() {
-    return dirWMap.getValid().get();
+  public void close() {
+    checkValid();
+    checkThread(owner);
+    dirWMap.close(); //checksValidAndThread
   }
 
   @Override
-  public long getCapacity() {
+  public void force() {
     checkValid();
-    return capacityBytes;
+    checkThread(owner);
+    checkNotReadOnly();
+    dirWMap.force(); //checksValidAndThread
   }
 
   @Override
-  public long getCumulativeOffset() {
+  public long getCapacity() {
     checkValid();
-    return cumOffsetBytes;
+    return capacityBytes;
   }
 
   @Override
-  public MemoryRequestServer getMemoryRequestServer() {
-    checkValid();
-    return null;
+  public long getCumulativeOffset() {
+    return cumOffsetBytes;
   }
 
   @Override
   public long getNativeBaseOffset() {
-    checkValid();
     return dirWMap.nativeBaseOffset;
   }
 
@@ -139,34 +144,31 @@ final class MapNonNativeWritableBufferImpl extends NonNativeWritableBufferImpl {
 
   @Override
   int getTypeId() {
-    checkValid();
     return typeId;
   }
 
   @Override
   Object getUnsafeObject() {
-    checkValid();
     return null;
   }
 
   @Override
-  public void close() {
-    dirWMap.close();
-  }
-
-  @Override
-  public void force() {
-    dirWMap.force();
+  public boolean isLoaded() {
+    checkValid();
+    checkThread(owner);
+    return dirWMap.isLoaded(); //checksValidAndThread
   }
 
   @Override
-  public boolean isLoaded() {
-    return dirWMap.isLoaded();
+  public boolean isValid() {
+    return dirWMap.getValid().get();
   }
 
   @Override
   public void load() {
-    dirWMap.load();
+    checkValid();
+    checkThread(owner);
+    dirWMap.load(); //checksValidAndThread
   }
 
 }
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapNonNativeWritableMemoryImpl.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapNonNativeWritableMemoryImpl.java
index ea5e3a6..f0fc5ef 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapNonNativeWritableMemoryImpl.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapNonNativeWritableMemoryImpl.java
@@ -21,7 +21,6 @@ package org.apache.datasketches.memory.internal;
 
 import java.nio.ByteOrder;
 
-import org.apache.datasketches.memory.MemoryRequestServer;
 import org.apache.datasketches.memory.WritableMemory;
 
 /**
@@ -49,6 +48,10 @@ final class MapNonNativeWritableMemoryImpl extends NonNativeWritableMemoryImpl {
     this.capacityBytes = capacityBytes;
     this.typeId = removeNnBuf(typeId) | MAP | MEMORY | NONNATIVE;
     this.cumOffsetBytes = cumOffsetBytes;
+    if ((this.owner != null) && (this.owner != Thread.currentThread())) {
+      throw new IllegalStateException(THREAD_EXCEPTION_TEXT);
+    }
+    this.owner = Thread.currentThread();
   }
 
   @Override
@@ -88,31 +91,33 @@ final class MapNonNativeWritableMemoryImpl extends NonNativeWritableMemoryImpl {
   }
 
   @Override
-  public boolean isValid() {
-    return dirWMap.getValid().get();
+  public void close() {
+    checkValid();
+    checkThread(owner);
+    dirWMap.close(); //checksValidAndThread
   }
 
   @Override
-  public long getCapacity() {
+  public void force() {
     checkValid();
-    return capacityBytes;
+    checkThread(owner);
+    checkNotReadOnly();
+    dirWMap.force(); //checksValidAndThread
   }
 
   @Override
-  public long getCumulativeOffset() {
+  public long getCapacity() {
     checkValid();
-    return cumOffsetBytes;
+    return capacityBytes;
   }
 
   @Override
-  public MemoryRequestServer getMemoryRequestServer() {
-    checkValid();
-    return null;
+  public long getCumulativeOffset() {
+    return cumOffsetBytes;
   }
 
   @Override
   public long getNativeBaseOffset() {
-    checkValid();
     return dirWMap.nativeBaseOffset;
   }
 
@@ -124,34 +129,31 @@ final class MapNonNativeWritableMemoryImpl extends NonNativeWritableMemoryImpl {
 
   @Override
   int getTypeId() {
-    checkValid();
     return typeId;
   }
 
   @Override
   Object getUnsafeObject() {
-    checkValid();
     return null;
   }
 
   @Override
-  public void close() {
-    dirWMap.close();
-  }
-
-  @Override
-  public void force() {
-    dirWMap.force();
+  public boolean isLoaded() {
+    checkValid();
+    checkThread(owner);
+    return dirWMap.isLoaded(); //checksValidAndThread
   }
 
   @Override
-  public boolean isLoaded() {
-    return dirWMap.isLoaded();
+  public boolean isValid() {
+    return dirWMap.getValid().get();
   }
 
   @Override
   public void load() {
-    dirWMap.load();
+    checkValid();
+    checkThread(owner);
+    dirWMap.load(); //checksValidAndThread
   }
 
 }
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapWritableBufferImpl.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapWritableBufferImpl.java
index 0470cab..04c6ade 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapWritableBufferImpl.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapWritableBufferImpl.java
@@ -21,7 +21,6 @@ package org.apache.datasketches.memory.internal;
 
 import java.nio.ByteOrder;
 
-import org.apache.datasketches.memory.MemoryRequestServer;
 import org.apache.datasketches.memory.WritableBuffer;
 
 /**
@@ -49,6 +48,10 @@ final class MapWritableBufferImpl extends NativeWritableBufferImpl {
     this.capacityBytes = capacityBytes;
     this.typeId = removeNnBuf(typeId) | MAP | BUFFER | NATIVE;
     this.cumOffsetBytes = cumOffsetBytes;
+    if ((this.owner != null) && (this.owner != Thread.currentThread())) {
+      throw new IllegalStateException(THREAD_EXCEPTION_TEXT);
+    }
+    this.owner = Thread.currentThread();
   }
 
   @Override
@@ -103,31 +106,33 @@ final class MapWritableBufferImpl extends NativeWritableBufferImpl {
   }
 
   @Override
-  public boolean isValid() {
-    return dirWMap.getValid().get();
+  public void close() {
+    checkValid();
+    checkThread(owner);
+    dirWMap.close(); //checksValidAndThread
   }
 
   @Override
-  public long getCapacity() {
+  public void force() {
     checkValid();
-    return capacityBytes;
+    checkThread(owner);
+    checkNotReadOnly();
+    dirWMap.force(); //checksValidAndThread
   }
 
   @Override
-  public long getCumulativeOffset() {
+  public long getCapacity() {
     checkValid();
-    return cumOffsetBytes;
+    return capacityBytes;
   }
 
   @Override
-  public MemoryRequestServer getMemoryRequestServer() {
-    checkValid();
-    return null;
+  public long getCumulativeOffset() {
+    return cumOffsetBytes;
   }
 
   @Override
   public long getNativeBaseOffset() {
-    checkValid();
     return dirWMap.nativeBaseOffset;
   }
 
@@ -139,34 +144,31 @@ final class MapWritableBufferImpl extends NativeWritableBufferImpl {
 
   @Override
   int getTypeId() {
-    checkValid();
     return typeId;
   }
 
   @Override
   Object getUnsafeObject() {
-    checkValid();
     return null;
   }
 
   @Override
-  public void close() {
-    dirWMap.close();
-  }
-
-  @Override
-  public void force() {
-    dirWMap.force();
+  public boolean isLoaded() {
+    checkValid();
+    checkThread(owner);
+    return dirWMap.isLoaded(); //checksValidAndThread
   }
 
   @Override
-  public boolean isLoaded() {
-    return dirWMap.isLoaded();
+  public boolean isValid() {
+    return dirWMap.getValid().get();
   }
 
   @Override
   public void load() {
-    dirWMap.load();
+    checkValid();
+    checkThread(owner);
+    dirWMap.load(); //checksValidAndThread
   }
 
 }
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapWritableMemoryImpl.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapWritableMemoryImpl.java
index b6b6c2b..c34ee2e 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapWritableMemoryImpl.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapWritableMemoryImpl.java
@@ -21,7 +21,6 @@ package org.apache.datasketches.memory.internal;
 
 import java.nio.ByteOrder;
 
-import org.apache.datasketches.memory.MemoryRequestServer;
 import org.apache.datasketches.memory.WritableMemory;
 
 /**
@@ -49,6 +48,10 @@ final class MapWritableMemoryImpl extends NativeWritableMemoryImpl {
     this.capacityBytes = capacityBytes;
     this.typeId = removeNnBuf(typeId) | MAP | MEMORY | NATIVE;
     this.cumOffsetBytes = cumOffsetBytes;
+    if ((this.owner != null) && (this.owner != Thread.currentThread())) {
+      throw new IllegalStateException(THREAD_EXCEPTION_TEXT);
+    }
+    this.owner = Thread.currentThread();
   }
 
   @Override
@@ -88,25 +91,29 @@ final class MapWritableMemoryImpl extends NativeWritableMemoryImpl {
   }
 
   @Override
-  public boolean isValid() {
-    return dirWMap.getValid().get();
+  public void close() {
+    checkValid();
+    checkThread(owner);
+    dirWMap.close();
   }
 
   @Override
-  public long getCapacity() {
+  public void force() {
     checkValid();
-    return capacityBytes;
+    checkThread(owner);
+    checkNotReadOnly();
+    dirWMap.force(); //checksValidAndThread
   }
 
   @Override
-  public long getCumulativeOffset() {
+  public long getCapacity() {
     checkValid();
-    return cumOffsetBytes;
+    return capacityBytes;
   }
 
   @Override
-  public MemoryRequestServer getMemoryRequestServer() {
-    return null;
+  public long getCumulativeOffset() {
+    return cumOffsetBytes;
   }
 
   @Override
@@ -122,34 +129,31 @@ final class MapWritableMemoryImpl extends NativeWritableMemoryImpl {
 
   @Override
   int getTypeId() {
-    checkValid();
     return typeId;
   }
 
   @Override
   Object getUnsafeObject() {
-    checkValid();
     return null;
   }
 
   @Override
-  public void close() {
-    dirWMap.close();
-  }
-
-  @Override
-  public void force() {
-    dirWMap.force();
+  public boolean isLoaded() {
+    checkValid();
+    checkThread(owner);
+    return dirWMap.isLoaded(); //checksValidAndThread
   }
 
   @Override
-  public boolean isLoaded() {
-    return dirWMap.isLoaded();
+  public boolean isValid() {
+    return dirWMap.getValid().get();
   }
 
   @Override
   public void load() {
-    dirWMap.load();
+    checkValid();
+    checkThread(owner);
+    dirWMap.load(); //checksValidAndThread
   }
 
 }
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MemoryCleaner.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MemoryCleaner.java
index 33053eb..a684018 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MemoryCleaner.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MemoryCleaner.java
@@ -44,6 +44,7 @@ public class MemoryCleaner {
 
     /**
      * Runs this cleaner, if it has not been run before.
+     * If there is any error, the system will exit.
      */
     public void clean() {
         cleaner.clean();
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/ResourceImpl.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/ResourceImpl.java
index 092a567..afdeafa 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/ResourceImpl.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/ResourceImpl.java
@@ -26,7 +26,6 @@ import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 
 import org.apache.datasketches.memory.MemoryBoundsException;
-import org.apache.datasketches.memory.MemoryInvalidException;
 import org.apache.datasketches.memory.MemoryRequestServer;
 import org.apache.datasketches.memory.ReadOnlyException;
 import org.apache.datasketches.memory.Resource;
@@ -85,6 +84,9 @@ public abstract class ResourceImpl implements Resource {
   public static final ByteOrder NON_NATIVE_BYTE_ORDER =
       (NATIVE_BYTE_ORDER == ByteOrder.LITTLE_ENDIAN) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
 
+  static final String NOT_MAPPED_FILE_RESOURCE = "This is not a memory-mapped file resource";
+  static final String THREAD_EXCEPTION_TEXT = "Attempted access outside owning thread";
+
   static {
     final String jdkVer = System.getProperty("java.version");
     final int[] p = parseJavaVersion(jdkVer);
@@ -92,7 +94,9 @@ public abstract class ResourceImpl implements Resource {
     JDK_MAJOR = (p[0] == 1) ? p[1] : p[0];
   }
 
-  MemoryRequestServer memReqSvr = null; //selected by the user
+  MemoryRequestServer memReqSvr = null; //set by the user.
+
+  Thread owner = null; //set by the leaf nodes.
 
   /**
    * The root of the Memory inheritance hierarchy
@@ -102,10 +106,12 @@ public abstract class ResourceImpl implements Resource {
   /**
    * Check the requested offset and length against the allocated size.
    * The invariants equation is: {@code 0 <= reqOff <= reqLen <= reqOff + reqLen <= allocSize}.
-   * If this equation is violated an {@link IllegalArgumentException} will be thrown.
+   * If this equation is violated an {@link MemoryBoundsException} will be thrown.
    * @param reqOff the requested offset
    * @param reqLen the requested length
    * @param allocSize the allocated size.
+   * @Throws MemoryBoundsException if the given arguments constitute a violation
+   * of the invariants equation expressed above.
    */
   public static void checkBounds(final long reqOff, final long reqLen, final long allocSize) {
     if ((reqOff | reqLen | (reqOff + reqLen) | (allocSize - (reqOff + reqLen))) < 0) {
@@ -116,38 +122,81 @@ public abstract class ResourceImpl implements Resource {
   }
 
   static void checkJavaVersion(final String jdkVer, final int p0, final int p1 ) {
-    final boolean ok = ((p0 == 1) && (p1 == 8)) || (p0 == 8) || (p0 == 11);
+    final boolean ok = ((p0 == 1) && (p1 == 8)) || (p0 == 8) || (p0 == 11) || (p0 == 17);
     if (!ok) { throw new IllegalArgumentException(
-        "Unsupported JDK Major Version. It must be one of 1.8, 8, 11: " + jdkVer);
+        "Unsupported JDK Major Version. It must be one of 1.8, 8, 11, 17: " + jdkVer);
+    }
+  }
+
+  void checkNotReadOnly() {
+    if (isReadOnly()) {
+      throw new ReadOnlyException("Cannot write to a read-only Resource.");
     }
   }
 
-  public static final void checkThread(final Thread owner) {
+  /**
+   * This checks that the current thread is the same as the given owner thread.
+   * @Throws IllegalStateException if it is not.
+   * @param owner the given owner thread.
+   */
+  static final void checkThread(final Thread owner) {
     if (owner != Thread.currentThread()) {
-      throw new IllegalStateException("Attempted access outside owning thread");
+      throw new IllegalStateException(THREAD_EXCEPTION_TEXT);
     }
   }
 
+  /**
+   * @throws IllegalStateException if this Resource is AutoCloseable, and already closed, i.e., not <em>valid</em>.
+   */
   void checkValid() {
     if (!isValid()) {
-      throw new MemoryInvalidException();
+      throw new IllegalStateException("this Resource is AutoCloseable, and already closed, i.e., not <em>valid</em>.");
     }
   }
 
-  @Override
+  /**
+   * Checks that this resource is still valid and throws a MemoryInvalidException if it is not.
+   * Checks that the specified range of bytes is within bounds of this resource, throws
+   * {@link MemoryBoundsException} if it's not: i. e. if offsetBytes &lt; 0, or length &lt; 0,
+   * or offsetBytes + length &gt; {@link #getCapacity()}.
+   * @param offsetBytes the given offset in bytes of this object
+   * @param lengthBytes the given length in bytes of this object
+   * @Throws MemoryInvalidException if this resource is AutoCloseable and is no longer valid, i.e.,
+   * it has already been closed.
+   * @Throws MemoryBoundsException if this resource violates the memory bounds of this resource.
+   */
   public final void checkValidAndBounds(final long offsetBytes, final long lengthBytes) {
     checkValid();
-    ResourceImpl.checkBounds(offsetBytes, lengthBytes, getCapacity());
+    checkBounds(offsetBytes, lengthBytes, getCapacity());
   }
 
+  /**
+   * Checks that this resource is still valid and throws a MemoryInvalidException if it is not.
+   * Checks that the specified range of bytes is within bounds of this resource, throws
+   * {@link MemoryBoundsException} if it's not: i. e. if offsetBytes &lt; 0, or length &lt; 0,
+   * or offsetBytes + length &gt; {@link #getCapacity()}.
+   * Checks that this operation is a read-only operation and throws a ReadOnlyException if not.
+   * @param offsetBytes the given offset in bytes of this object
+   * @param lengthBytes the given length in bytes of this object
+   * @Throws MemoryInvalidException if this resource is AutoCloseable and is no longer valid, i.e.,
+   * it has already been closed.
+   * @Throws MemoryBoundsException if this resource violates the memory bounds of this resource.
+   * @Throws ReadOnlyException if the associated operation is not a Read-only operation.
+   */
   final void checkValidAndBoundsForWrite(final long offsetBytes, final long lengthBytes) {
     checkValid();
-    ResourceImpl.checkBounds(offsetBytes, lengthBytes, getCapacity());
+    checkBounds(offsetBytes, lengthBytes, getCapacity());
     if (isReadOnly()) {
       throw new ReadOnlyException("Memory is read-only.");
     }
   }
 
+  @Override
+  public void close() {
+    /* Overridden by the actual AutoCloseable leaf sub-classes. */
+    throw new UnsupportedOperationException("This resource is not AutoCloseable.");
+  }
+
   @Override
   public final boolean equalTo(final long thisOffsetBytes, final Resource that,
       final long thatOffsetBytes, final long lengthBytes) {
@@ -157,17 +206,17 @@ public abstract class ResourceImpl implements Resource {
 
   @Override
   public void force() { //overridden by Map Leaves
-    throw new IllegalStateException("This resource is not a memory-mapped file type.");
+    throw new UnsupportedOperationException(NOT_MAPPED_FILE_RESOURCE);
   }
 
-  //Overridden by ByteBuffer Leafs
+  //Overridden by ByteBuffer Leaves. Used internally and for tests.
   ByteBuffer getByteBuffer() {
     return null;
   }
 
   @Override
   public final ByteOrder getByteOrder() {
-    return isNonNativeType(getTypeId()) ? Util.NON_NATIVE_BYTE_ORDER : ByteOrder.nativeOrder();
+    return isNativeOrder(getTypeId()) ? NATIVE_BYTE_ORDER : NON_NATIVE_BYTE_ORDER;
   }
 
   /**
@@ -195,15 +244,15 @@ public abstract class ResourceImpl implements Resource {
   //Documented in WritableMemory and WritableBuffer interfaces.
   //Implemented in the Leaf nodes; Required here by toHex(...).
   @Override
-  public abstract MemoryRequestServer getMemoryRequestServer();
+  public MemoryRequestServer getMemoryRequestServer() { return memReqSvr; }
 
   //Overridden by ByteBuffer, Direct and Map Leaves
   abstract long getNativeBaseOffset();
 
-  //Overridden by all leafs
+  //Overridden by all leaves
   abstract int getTypeId();
 
-  //Overridden by Heap and ByteBuffer Leafs. Made public as getArray() in WritableMemoryImpl and
+  //Overridden by Heap and ByteBuffer leaves. Made public as getArray() in WritableMemoryImpl and
   // WritableBufferImpl
   Object getUnsafeObject() {
     return null;
@@ -214,17 +263,13 @@ public abstract class ResourceImpl implements Resource {
     return (getTypeId() & BYTEBUF) > 0;
   }
 
-  final boolean isByteBufferType(final int typeId) {
-    return (typeId & BYTEBUF) > 0;
-  }
-
   @Override
   public final boolean isByteOrderCompatible(final ByteOrder byteOrder) {
     final ByteOrder typeBO = getByteOrder();
     return typeBO == ByteOrder.nativeOrder() && typeBO == byteOrder;
   }
 
-  final boolean isBufferType(final int typeId) {
+  final boolean isBufferApi(final int typeId) {
     return (typeId & BUFFER) > 0;
   }
 
@@ -238,23 +283,15 @@ public abstract class ResourceImpl implements Resource {
     return (getTypeId() & DUPLICATE) > 0;
   }
 
-  final boolean isDuplicateType(final int typeId) {
-    return (typeId & DUPLICATE) > 0;
-  }
-
   @Override
   public final boolean isHeapResource() {
     checkValid();
     return getUnsafeObject() != null;
   }
 
-  final boolean isHeapType(final int typeId) {
-    return (typeId & (MAP | DIRECT)) == 0;
-  }
-
   @Override
   public boolean isLoaded() { //overridden by Map Leaves
-    throw new IllegalStateException("This resource is not a memory-mapped file type.");
+    throw new IllegalStateException(NOT_MAPPED_FILE_RESOURCE);
   }
 
   @Override
@@ -262,20 +299,12 @@ public abstract class ResourceImpl implements Resource {
     return (getTypeId() & MAP) > 0;
   }
 
-  final boolean isMapType(final int typeId) { //not used
-    return (typeId & MAP) > 0;
-  }
-
   @Override
   public boolean isMemoryApi() {
     return (getTypeId() & BUFFER) == 0;
   }
 
-  final boolean isMemoryType(final int typeId) { //not used
-    return (typeId & BUFFER) == 0;
-  }
-
-  final boolean isNativeType(final int typeId) { //not used
+  final boolean isNativeOrder(final int typeId) { //not used
     return (typeId & NONNATIVE) == 0;
   }
 
@@ -284,18 +313,10 @@ public abstract class ResourceImpl implements Resource {
     return (getTypeId() & NONNATIVE) > 0;
   }
 
-  final boolean isNonNativeType(final int typeId) {
-    return (typeId & NONNATIVE) > 0;
-  }
-
   @Override
   public final boolean isReadOnly() {
     checkValid();
-    return isReadOnlyType(getTypeId());
-  }
-
-  final boolean isReadOnlyType(final int typeId) {
-    return (typeId & READONLY) > 0;
+    return (getTypeId() & READONLY) > 0;
   }
 
   @Override
@@ -303,10 +324,6 @@ public abstract class ResourceImpl implements Resource {
     return (getTypeId() & REGION) > 0;
   }
 
-  final boolean isRegionType(final int typeId) {
-    return (typeId & REGION) > 0;
-  }
-
   @Override
   public boolean isSameResource(final Resource that) {
     checkValid();
@@ -320,19 +337,15 @@ public abstract class ResourceImpl implements Resource {
             && getByteBuffer() == that1.getByteBuffer();
   }
 
-  //Overridden by Direct and Map leafs
+  //Overridden by Direct and Map leaves
   @Override
   public boolean isValid() {
     return true;
   }
 
-  final boolean isWritableType(final int typeId) { //not used
-    return (typeId & READONLY) == 0;
-  }
-
   @Override
-  public void load() { //overridden by Map leafs
-    throw new IllegalStateException("This resource is not a memory-mapped file type.");
+  public void load() { //overridden by Map leaves
+    throw new IllegalStateException(NOT_MAPPED_FILE_RESOURCE);
   }
 
   private static String pad(final String s, final int fieldLen) {
@@ -364,15 +377,13 @@ public abstract class ResourceImpl implements Resource {
 
   final static int removeNnBuf(final int typeId) { return typeId & ~NONNATIVE & ~BUFFER; }
 
-  @Override
-  public void setMemoryRequestServer(final MemoryRequestServer memReqSvr) {
-    this.memReqSvr = memReqSvr;
-  }
-
-  final static int setReadOnlyType(final int typeId, final boolean readOnly) {
+  final static int setReadOnlyBit(final int typeId, final boolean readOnly) {
     return readOnly ? typeId | READONLY : typeId & ~READONLY;
   }
 
+  @Override
+  public void setMemoryRequestServer(final MemoryRequestServer memReqSvr) { this.memReqSvr = memReqSvr; }
+
   /**
    * Returns a formatted hex string of an area of this object.
    * Used primarily for testing.
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 f213615..aabbb90 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
@@ -139,14 +139,14 @@ public final class UnsafeUtil {
     } catch (final NumberFormatException | ArrayIndexOutOfBoundsException  e) {
       throw new IllegalArgumentException("Improper Java -version string: " + jdkVer + "\n" + e);
     }
-    //checkJavaVersion(jdkVer, p0, p1); //TODO Optional to omit this.
+    checkJavaVersion(jdkVer, p0, p1);
     return new int[] {p0, p1};
   }
 
   public static void checkJavaVersion(final String jdkVer, final int p0, final int p1) {
     if ( (p0 < 1) || ((p0 == 1) && (p1 < 8)) || (p0 > 13)  ) {
       throw new IllegalArgumentException(
-          "Unsupported JDK Major Version, must be one of 1.8, 8, 9, 10, 11, 12, 13: " + jdkVer);
+          "Unsupported JDK Major Version, must be one of 1.8, 8, 11, 17: " + jdkVer);
     }
   }
 
@@ -154,7 +154,7 @@ public final class UnsafeUtil {
     try {
       return unsafe.objectFieldOffset(c.getDeclaredField(fieldName));
     } catch (final NoSuchFieldException e) {
-      throw new IllegalStateException(e);
+      throw new IllegalStateException(e + ": " + fieldName);
     }
   }
 
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/AllocateDirectMapMemoryTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/AllocateDirectMapMemoryTest.java
index e08682e..a506bbf 100644
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/AllocateDirectMapMemoryTest.java
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/AllocateDirectMapMemoryTest.java
@@ -32,8 +32,6 @@ import java.io.File;
 import java.nio.ByteOrder;
 
 import org.apache.datasketches.memory.Memory;
-import org.apache.datasketches.memory.MemoryCloseException;
-import org.apache.datasketches.memory.MemoryInvalidException;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
@@ -45,19 +43,17 @@ public class AllocateDirectMapMemoryTest {
     UtilTest.setGettysburgAddressFileToReadOnly();
   }
 
-  @Test(expectedExceptions = MemoryCloseException.class)
+  @Test(expectedExceptions = IllegalStateException.class)
   public void simpleMap() {
     File file = getResourceFile("GettysburgAddress.txt");
     assertTrue(AllocateDirectWritableMap.isFileReadOnly(file));
     try (Memory mem = Memory.map(file)) {
-      mem.close(); //redundant close
-    }
-    //The Try-With-Resources will throw at the close of the block,
-    // because of the redundant close before the close of the block.
+      mem.close(); //explicit close
+    } //The Try-With-Resources will throw if already closed
   }
 
   @Test
-  public void simpleMap2()  {
+  public void printGettysbergAddress()  {
     File file = getResourceFile("GettysburgAddress.txt");
     try (Memory mem = Memory.map(file))
     {
@@ -99,8 +95,8 @@ public class AllocateDirectMapMemoryTest {
     }
   }
 
-  @Test(expectedExceptions = MemoryInvalidException.class)
-  public void testMapAndMultipleCloseTypes() {
+  @Test(expectedExceptions = IllegalStateException.class)
+  public void testAccessAfterClose() {
     File file = getResourceFile("GettysburgAddress.txt");
     long memCapacity = file.length();
     try (Memory mem = Memory.map(file, 0, memCapacity, ByteOrder.nativeOrder())) {
@@ -108,16 +104,16 @@ public class AllocateDirectMapMemoryTest {
     } //normal close via TWR
     Memory mem = Memory.map(file, 0, memCapacity, ByteOrder.nativeOrder());
     mem.close(); //normal manual close
-    mem.getCapacity(); //already closed, invalid
+    mem.getCapacity(); //isLoaded(); //already closed, invalid
   }
 
-  @Test(expectedExceptions = MemoryInvalidException.class)
+  @Test(expectedExceptions = IllegalStateException.class)
   public void testReadFailAfterClose()  {
     File file = getResourceFile("GettysburgAddress.txt");
     long memCapacity = file.length();
     Memory mem = Memory.map(file, 0, memCapacity, ByteOrder.nativeOrder());
     mem.close();
-    mem.getByte(0);
+    mem.isLoaded();
   }
 
   @Test
@@ -127,7 +123,7 @@ public class AllocateDirectMapMemoryTest {
     try (Memory mem = Memory.map(file, 0, memCapacity, ByteOrder.nativeOrder())) {
       mem.load();
       assertTrue(mem.isLoaded());
-    }
+    } //normal TWR close
   }
 
   @Test
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/AllocateDirectMemoryTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/AllocateDirectMemoryTest.java
index 160a7b1..c259fda 100644
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/AllocateDirectMemoryTest.java
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/AllocateDirectMemoryTest.java
@@ -24,7 +24,6 @@ import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertTrue;
 
 import org.apache.datasketches.memory.DefaultMemoryRequestServer;
-import org.apache.datasketches.memory.MemoryCloseException;
 import org.apache.datasketches.memory.MemoryRequestServer;
 import org.apache.datasketches.memory.Resource;
 import org.apache.datasketches.memory.WritableMemory;
@@ -32,7 +31,7 @@ import org.testng.annotations.Test;
 
 public class AllocateDirectMemoryTest {
 
-  @Test(expectedExceptions = MemoryCloseException.class)
+  @Test(expectedExceptions = IllegalStateException.class)
   public void simpleAllocateDirect()  {
     int longs = 32;
     try (WritableMemory wMem = WritableMemory.allocateDirect(longs << 3)) {
@@ -42,8 +41,8 @@ public class AllocateDirectMemoryTest {
       }
       //inside the TWR block the memory should be valid
       ((ResourceImpl)wMem).checkValid();
-      wMem.close(); //Redundant close
-    } //normal TWR close will throw
+      wMem.close(); //explicit close
+    } //normal TWR close will not throw if already closed
   }
 
   @Test
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BaseBufferTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BaseBufferTest.java
index 5b9c3b6..759fdd5 100644
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BaseBufferTest.java
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BaseBufferTest.java
@@ -24,7 +24,6 @@ import static org.testng.Assert.fail;
 import org.apache.datasketches.memory.Buffer;
 import org.apache.datasketches.memory.BufferPositionInvariantsException;
 import org.apache.datasketches.memory.Memory;
-import org.apache.datasketches.memory.MemoryInvalidException;
 import org.apache.datasketches.memory.WritableMemory;
 import org.testng.annotations.Test;
 
@@ -49,17 +48,17 @@ public class BaseBufferTest {
   @Test
   public void checkLimitsAndCheck() {
     Buffer buf = Memory.wrap(new byte[100]).asBuffer();
-    buf.setAndCheckStartPositionEnd(40, 45, 50);
-    buf.setAndCheckStartPositionEnd(0, 0, 100);
+    buf.setStartPositionEnd(40, 45, 50);
+    buf.setStartPositionEnd(0, 0, 100);
     try {
-      buf.setAndCheckStartPositionEnd(0, 0, 101);
+      buf.setStartPositionEnd(0, 0, 101);
       fail();
     } catch (BufferPositionInvariantsException e) {
       //ok
     }
-    buf.setAndCheckPosition(100);
+    buf.setPosition(100);
     try {
-      buf.setAndCheckPosition(101);
+      buf.setPosition(101);
       fail();
     } catch (BufferPositionInvariantsException e) {
       //ok
@@ -74,7 +73,7 @@ public class BaseBufferTest {
     }
   }
 
-  @Test(expectedExceptions = MemoryInvalidException.class)
+  @Test(expectedExceptions = IllegalStateException.class)
   public void checkCheckValid() {
 
     Buffer buf;
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BufferTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BufferTest.java
index ae05e43..529eb5e 100644
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BufferTest.java
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BufferTest.java
@@ -28,7 +28,6 @@ import java.util.List;
 import org.apache.datasketches.memory.Buffer;
 import org.apache.datasketches.memory.BufferPositionInvariantsException;
 import org.apache.datasketches.memory.Memory;
-import org.apache.datasketches.memory.MemoryInvalidException;
 import org.apache.datasketches.memory.WritableBuffer;
 import org.apache.datasketches.memory.WritableMemory;
 import org.testng.annotations.Test;
@@ -280,18 +279,16 @@ public class BufferTest {
     }
   }
 
-  @Test(expectedExceptions = MemoryInvalidException.class)
+  @Test(expectedExceptions = IllegalStateException.class)
   public void checkParentUseAfterFree() throws Exception {
     int bytes = 64 * 8;
     WritableMemory wmem = WritableMemory.allocateDirect(bytes);
     WritableBuffer wbuf = wmem.asWritableBuffer();
     wmem.close();
-    //with -ea assert: Memory not valid.
-    //with -da sometimes segfaults, sometimes passes!
     wbuf.getLong();
   }
 
-  @Test(expectedExceptions = MemoryInvalidException.class)
+  @Test(expectedExceptions = IllegalStateException.class)
   public void checkRegionUseAfterFree() throws Exception {
     int bytes = 64;
     WritableMemory wmem = WritableMemory.allocateDirect(bytes);
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/LeafImplTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/LeafImplTest.java
index cc76b31..1bd16df 100644
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/LeafImplTest.java
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/LeafImplTest.java
@@ -55,7 +55,7 @@ public class LeafImplTest {
   }
 
   @Test
-  public void checkDirectLeafs() throws Exception {
+  public void checkDirectLeaves() throws Exception {
     long off = 0;
     long cap = 128;
     // Off Heap, Native order, No ByteBuffer, has MemReqSvr
@@ -75,7 +75,7 @@ public class LeafImplTest {
   }
 
   @Test
-  public void checkByteBufferLeafs() {
+  public void checkByteBufferLeaves() {
     long off = 0;
     long cap = 128;
     //BB on heap, native order, has ByteBuffer, has MemReqSvr
@@ -116,7 +116,7 @@ public class LeafImplTest {
   }
 
   @Test
-  public void checkMapLeafs() throws Exception {
+  public void checkMapLeaves() throws Exception {
     long off = 0;
     long cap = 128;
     File file = new File("TestFile2.bin");
@@ -148,7 +148,7 @@ public class LeafImplTest {
   }
 
   @Test
-  public void checkHeapLeafs() {
+  public void checkHeapLeaves() {
     long off = 0;
     long cap = 128;
     // On Heap, Native order, No ByteBuffer, No MemReqSvr
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryCloseExceptionTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryCloseExceptionTest.java
index 2a2ee39..b4d5980 100644
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryCloseExceptionTest.java
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryCloseExceptionTest.java
@@ -19,21 +19,7 @@
 
 package org.apache.datasketches.memory.internal;
 
-import org.apache.datasketches.memory.MemoryCloseException;
-import org.testng.annotations.Test;
-
 public class MemoryCloseExceptionTest {
 
-  @Test
-  public void checkNoArgs() {
-    try {
-      throw new MemoryCloseException();
-    } catch (final MemoryCloseException e) { }
-
-    try {
-      throw new MemoryCloseException("Test Exception");
-    } catch (final MemoryCloseException e) { }
-  }
 }
 
-
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryTest.java
index f3da8ce..5b328d2 100644
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryTest.java
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryTest.java
@@ -35,7 +35,6 @@ import java.util.List;
 
 import org.apache.datasketches.memory.DefaultMemoryRequestServer;
 import org.apache.datasketches.memory.Memory;
-import org.apache.datasketches.memory.MemoryInvalidException;
 import org.apache.datasketches.memory.MemoryRequestServer;
 import org.apache.datasketches.memory.Resource;
 import org.apache.datasketches.memory.WritableBuffer;
@@ -317,7 +316,7 @@ public class MemoryTest {
     }
   }
 
-  @Test(expectedExceptions = MemoryInvalidException.class)
+  @Test(expectedExceptions = IllegalStateException.class)
   public void checkParentUseAfterFree() throws Exception {
     int bytes = 64 * 8;
     WritableMemory wmem = WritableMemory.allocateDirect(bytes);
@@ -325,7 +324,7 @@ public class MemoryTest {
     wmem.getLong(0);
   }
 
-  @Test(expectedExceptions = MemoryInvalidException.class)
+  @Test(expectedExceptions = IllegalStateException.class)
   public void checkRegionUseAfterFree() throws Exception {
     int bytes = 64;
     Memory mem = WritableMemory.allocateDirect(bytes);
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/NativeWritableBufferImplTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/NativeWritableBufferImplTest.java
index 7a626b0..7a60d11 100644
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/NativeWritableBufferImplTest.java
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/NativeWritableBufferImplTest.java
@@ -442,7 +442,7 @@ public class NativeWritableBufferImplTest {
     for (int i = 0; i < 64; i++) { wmem.putByte(i, (byte)i); }
 
     WritableBuffer wbuf = wmem.asWritableBuffer().writableDuplicate();
-    wbuf.checkValidAndBounds(0, 64);
+    ((ResourceImpl)wbuf).checkValidAndBounds(0, 64);
     for (int i = 0; i < 64; i++) {
       assertEquals(wbuf.getByte(), i);
     }
@@ -456,7 +456,7 @@ public class NativeWritableBufferImplTest {
       assertEquals(wmem2.getByte(i), i);
     }
     WritableMemory wmem3 = wbuf.asWritableMemory();
-    wmem3.checkValidAndBounds(0, 64);
+    ((ResourceImpl)wmem3).checkValidAndBounds(0, 64);
   }
 
   @Test
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/NativeWritableMemoryImplTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/NativeWritableMemoryImplTest.java
index 7f768e0..f8a07e6 100644
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/NativeWritableMemoryImplTest.java
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/NativeWritableMemoryImplTest.java
@@ -568,7 +568,7 @@ public class NativeWritableMemoryImplTest {
     assertEquals(comp, 0);
     comp = mem3.compareTo(0, 4, mem4, 1, 4);
     assertEquals(comp, -1);
-    mem3.checkValidAndBounds(0, 5);
+    ((ResourceImpl)mem3).checkValidAndBounds(0, 5);
   }
 
   @Test
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/NioBitsTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/NioBitsTest.java
deleted file mode 100644
index 8ed5916..0000000
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/NioBitsTest.java
+++ /dev/null
@@ -1,78 +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.testng.Assert.assertEquals;
-
-import org.testng.annotations.Test;
-
-/**
- * @author Lee Rhodes
- */
-public class NioBitsTest {
-
-  @Test
-  public void checkVMParams() {
-    println("Max MemoryImpl: " + NioBits.getMaxDirectByteBufferMemory());
-    println("Page Aligned: " + NioBits.isPageAligned());
-    println("Page Size: " + NioBits.pageSize());
-  }
-
-  @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();
-    NioBits.reserveMemory(cap, cap);
-    printStats();
-    NioBits. unreserveMemory(cap, cap);
-    printStats();
-  }
-
-  @Test
-  public void checkPageCount() {
-    assertEquals(NioBits.pageCount(0), 0);
-    assertEquals(NioBits.pageCount(1), 1);
-  }
-
-  private static void printStats() {
-    long count = NioBits.getDirectAllocationsCount();
-    long resMem = NioBits.getReservedMemory();
-    long totCap = NioBits.getTotalCapacity();
-    long maxDBBmem = NioBits.getMaxDirectByteBufferMemory();
-    String s = String.format("%,10d\t%,15d\t%,15d\t%,15d", count, resMem, totCap, maxDBBmem);
-    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/src/test/java/org/apache/datasketches/memory/internal/SpecificLeafTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/SpecificLeafTest.java
index db060ab..250d0a5 100644
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/SpecificLeafTest.java
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/SpecificLeafTest.java
@@ -38,7 +38,7 @@ import org.testng.annotations.Test;
 public class SpecificLeafTest {
 
   @Test
-  public void checkByteBufferLeafs() {
+  public void checkByteBufferLeaves() {
     int bytes = 128;
     ByteBuffer bb = ByteBuffer.allocate(bytes);
     bb.order(ByteOrder.nativeOrder());
@@ -46,8 +46,8 @@ public class SpecificLeafTest {
     Memory mem = Memory.wrap(bb).region(0, bytes, ByteOrder.nativeOrder());
     ResourceImpl bsi = (ResourceImpl)mem;
     int typeId = bsi.getTypeId();
-    assertTrue(bsi.isByteBufferType(typeId));
-    assertTrue(bsi.isNativeType(typeId));
+    assertTrue(bsi.isByteBufferResource());
+    assertTrue(bsi.isNativeOrder(typeId));
     assertTrue(mem.isReadOnly());
     checkCrossLeafTypeIds(mem);
     Buffer buf = mem.asBuffer().region(0, bytes, ByteOrder.nativeOrder());
@@ -57,15 +57,15 @@ public class SpecificLeafTest {
     Buffer buf2 = mem2.asBuffer().region(0, bytes, Util.NON_NATIVE_BYTE_ORDER);
     Buffer buf3 = buf2.duplicate();
 
-    assertTrue(((ResourceImpl)mem).isRegionType(((ResourceImpl)mem).getTypeId()));
-    assertTrue(((ResourceImpl)mem2).isRegionType(((ResourceImpl)mem2).getTypeId()));
-    assertTrue(((ResourceImpl)buf).isRegionType(((ResourceImpl)buf).getTypeId()));
-    assertTrue(((ResourceImpl)buf2).isRegionType(((ResourceImpl)buf2).getTypeId()));
-    assertTrue(((ResourceImpl)buf3).isDuplicateType(((ResourceImpl)buf3).getTypeId()));
+    assertTrue(((ResourceImpl)mem).isRegionView());
+    assertTrue(((ResourceImpl)mem2).isRegionView());
+    assertTrue(((ResourceImpl)buf).isRegionView());
+    assertTrue(((ResourceImpl)buf2).isRegionView());
+    assertTrue(((ResourceImpl)buf3).isDuplicateBufferView());
   }
 
   @Test
-  public void checkDirectLeafs()  {
+  public void checkDirectLeaves()  {
     int bytes = 128;
     try (WritableMemory wmem = WritableMemory.allocateDirect(bytes)) {
       assertTrue(((ResourceImpl)wmem).isDirectResource());
@@ -81,22 +81,21 @@ public class SpecificLeafTest {
       Buffer buf2 = mem2.asBuffer().region(0, bytes, Util.NON_NATIVE_BYTE_ORDER);
       Buffer buf3 = buf2.duplicate();
 
-      assertTrue(((ResourceImpl)mem).isRegionType(((ResourceImpl)mem).getTypeId()));
-      assertTrue(((ResourceImpl)mem2).isRegionType(((ResourceImpl)mem2).getTypeId()));
-      assertTrue(((ResourceImpl)buf).isRegionType(((ResourceImpl)buf).getTypeId()));
-      assertTrue(((ResourceImpl)buf2).isRegionType(((ResourceImpl)buf2).getTypeId()));
-      assertTrue(((ResourceImpl)buf3).isDuplicateType(((ResourceImpl)buf3).getTypeId()));
+      assertTrue(((ResourceImpl)mem).isRegionView());
+      assertTrue(((ResourceImpl)mem2).isRegionView());
+      assertTrue(((ResourceImpl)buf).isRegionView());
+      assertTrue(((ResourceImpl)buf2).isRegionView());
+      assertTrue(((ResourceImpl)buf3).isDuplicateBufferView());
     }
   }
 
   @Test
-  public void checkHeapLeafs() {
+  public void checkHeapLeaves() {
     int bytes = 128;
     Memory mem = Memory.wrap(new byte[bytes]);
     ResourceImpl bsi = (ResourceImpl)mem;
-    int typeId = bsi.getTypeId();
-    assertTrue(bsi.isHeapType(typeId));
-    assertTrue(bsi.isReadOnlyType(typeId));
+    assertTrue(bsi.isHeapResource());
+    assertTrue(bsi.isReadOnly());
     checkCrossLeafTypeIds(mem);
     Memory nnreg = mem.region(0, bytes, Util.NON_NATIVE_BYTE_ORDER);
 
@@ -108,16 +107,16 @@ public class SpecificLeafTest {
     Buffer buf2 = reg2.asBuffer().region(0, bytes, Util.NON_NATIVE_BYTE_ORDER);
     Buffer buf3 = buf2.duplicate();
 
-    assertFalse(((ResourceImpl)mem).isRegionType(((ResourceImpl)mem).getTypeId()));
-    assertTrue(((ResourceImpl)reg2).isRegionType(((ResourceImpl)reg2).getTypeId()));
-    assertTrue(((ResourceImpl)buf).isRegionType(((ResourceImpl)buf).getTypeId()));
-    assertTrue(((ResourceImpl)buf2).isRegionType(((ResourceImpl)buf2).getTypeId()));
-    assertTrue(((ResourceImpl)buf3).isDuplicateType(((ResourceImpl)buf3).getTypeId()));
-    assertTrue(((ResourceImpl)buf4).isDuplicateType(((ResourceImpl)buf4).getTypeId()));
+    assertFalse(((ResourceImpl)mem).isRegionView());
+    assertTrue(((ResourceImpl)reg2).isRegionView());
+    assertTrue(((ResourceImpl)buf).isRegionView());
+    assertTrue(((ResourceImpl)buf2).isRegionView());
+    assertTrue(((ResourceImpl)buf3).isDuplicateBufferView());
+    assertTrue(((ResourceImpl)buf4).isDuplicateBufferView());
   }
 
   @Test
-  public void checkMapLeafs() throws IOException {
+  public void checkMapLeaves() throws IOException {
     File file = new File("TestFile2.bin");
     if (file.exists()) {
       try {
@@ -134,7 +133,7 @@ public class SpecificLeafTest {
     final long bytes = 128;
 
     try (WritableMemory mem = WritableMemory.writableMap(file, 0L, bytes, ByteOrder.nativeOrder())) {
-      assertTrue(((ResourceImpl)mem).isMapType(((ResourceImpl)mem).getTypeId()));
+      assertTrue(((ResourceImpl)mem).isMemoryMappedResource());
       assertFalse(mem.isReadOnly());
       checkCrossLeafTypeIds(mem);
       Memory nnreg = mem.region(0, bytes, Util.NON_NATIVE_BYTE_ORDER);
@@ -147,47 +146,47 @@ public class SpecificLeafTest {
       Buffer buf2 = reg2.asBuffer().region(0, bytes, Util.NON_NATIVE_BYTE_ORDER);
       Buffer buf3 = buf2.duplicate();
 
-      assertTrue(((ResourceImpl)reg).isRegionType(((ResourceImpl)reg).getTypeId()));
-      assertTrue(((ResourceImpl)reg2).isRegionType(((ResourceImpl)reg2).getTypeId()));
-      assertTrue(((ResourceImpl)buf).isRegionType(((ResourceImpl)buf).getTypeId()));
-      assertTrue(((ResourceImpl)buf2).isRegionType(((ResourceImpl)buf2).getTypeId()));
-      assertTrue(((ResourceImpl)buf3).isDuplicateType(((ResourceImpl)buf3).getTypeId()));
-      assertTrue(((ResourceImpl)buf4).isDuplicateType(((ResourceImpl)buf4).getTypeId()));
+      assertTrue(((ResourceImpl)reg).isRegionView());
+      assertTrue(((ResourceImpl)reg2).isRegionView());
+      assertTrue(((ResourceImpl)buf).isRegionView());
+      assertTrue(((ResourceImpl)buf2).isRegionView());
+      assertTrue(((ResourceImpl)buf3).isDuplicateBufferView());
+      assertTrue(((ResourceImpl)buf4).isDuplicateBufferView());
     }
   }
 
   private static void checkCrossLeafTypeIds(Memory mem) {
     Memory reg1 = mem.region(0, mem.getCapacity());
-    assertTrue(((ResourceImpl)reg1).isRegionType(((ResourceImpl)reg1).getTypeId()));
+    assertTrue(((ResourceImpl)reg1).isRegionView());
     Buffer buf1 = reg1.asBuffer();
-    assertTrue(((ResourceImpl)buf1).isRegionType(((ResourceImpl)buf1).getTypeId()));
-    assertTrue(((ResourceImpl)buf1).isBufferType(((ResourceImpl)buf1).getTypeId()));
+    assertTrue(((ResourceImpl)buf1).isRegionView());
+    assertTrue(((ResourceImpl)buf1).isBufferApi(((ResourceImpl)buf1).getTypeId()));
     assertTrue(buf1.isReadOnly());
 
     Buffer buf2 = buf1.duplicate();
-    assertTrue(((ResourceImpl)buf2).isRegionType(((ResourceImpl)buf2).getTypeId()));
-    assertTrue(((ResourceImpl)buf2).isBufferType(((ResourceImpl)buf2).getTypeId()));
-    assertTrue(((ResourceImpl)buf2).isDuplicateType(((ResourceImpl)buf2).getTypeId()));
+    assertTrue(((ResourceImpl)buf2).isRegionView());
+    assertTrue(((ResourceImpl)buf2).isBufferApi(((ResourceImpl)buf2).getTypeId()));
+    assertTrue(((ResourceImpl)buf2).isDuplicateBufferView());
     assertTrue(buf2.isReadOnly());
 
     Memory mem2 = buf1.asMemory(); //
-    assertTrue(((ResourceImpl)mem2).isRegionType(((ResourceImpl)mem2).getTypeId()));
-    assertFalse(((ResourceImpl)mem2).isBufferType(((ResourceImpl)mem2).getTypeId()));
-    assertFalse(((ResourceImpl)mem2).isDuplicateType(((ResourceImpl)mem2).getTypeId()));
+    assertTrue(((ResourceImpl)mem2).isRegionView());
+    assertFalse(((ResourceImpl)mem2).isBufferApi(((ResourceImpl)mem2).getTypeId()));
+    assertFalse(((ResourceImpl)mem2).isDuplicateBufferView());
     assertTrue(mem2.isReadOnly());
 
     Buffer buf3 = buf1.duplicate(Util.NON_NATIVE_BYTE_ORDER);
-    assertTrue(((ResourceImpl)buf3).isRegionType(((ResourceImpl)buf3).getTypeId()));
-    assertTrue(((ResourceImpl)buf3).isBufferType(((ResourceImpl)buf3).getTypeId()));
-    assertTrue(((ResourceImpl)buf3).isDuplicateType(((ResourceImpl)buf3).getTypeId()));
-    assertTrue(((ResourceImpl)buf3).isNonNativeType(((ResourceImpl)buf3).getTypeId()));
+    assertTrue(((ResourceImpl)buf3).isRegionView());
+    assertTrue(((ResourceImpl)buf3).isBufferApi(((ResourceImpl)buf3).getTypeId()));
+    assertTrue(((ResourceImpl)buf3).isDuplicateBufferView());
+    assertTrue(((ResourceImpl)buf3).isNonNativeOrder());
     assertTrue(buf3.isReadOnly());
 
     Memory mem3 = buf3.asMemory();
-    assertTrue(((ResourceImpl)mem3).isRegionType(((ResourceImpl)mem3).getTypeId()));
-    assertFalse(((ResourceImpl)mem3).isBufferType(((ResourceImpl)mem3).getTypeId()));
-    assertTrue(((ResourceImpl)mem3).isDuplicateType(((ResourceImpl)mem3).getTypeId()));
-    assertTrue(((ResourceImpl)mem3).isNonNativeType(((ResourceImpl)mem3).getTypeId()));
+    assertTrue(((ResourceImpl)mem3).isRegionView());
+    assertFalse(((ResourceImpl)mem3).isBufferApi(((ResourceImpl)mem3).getTypeId()));
+    assertTrue(((ResourceImpl)mem3).isDuplicateBufferView());
+    assertTrue(((ResourceImpl)mem3).isNonNativeOrder());
     assertTrue(mem3.isReadOnly());
   }
 
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/ThreadTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/ThreadTest.java
new file mode 100644
index 0000000..89852bd
--- /dev/null
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/ThreadTest.java
@@ -0,0 +1,76 @@
+/*
+ * 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.Util.getResourceFile;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.io.File;
+
+import org.apache.datasketches.memory.Memory;
+import org.apache.datasketches.memory.WritableMemory;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class ThreadTest {
+
+  File file;
+  Memory mem;
+  WritableMemory wmem;
+  Thread altThread;
+
+  @BeforeClass
+  public void prepareFileAndMemory() {
+    UtilTest.setGettysburgAddressFileToReadOnly();
+    file = getResourceFile("GettysburgAddress.txt");
+    assertTrue(AllocateDirectWritableMap.isFileReadOnly(file));
+  }
+
+  void initMap() {
+    mem = Memory.map(file); assertTrue(mem.isValid());
+  }
+
+  void initDirectMem() {
+    wmem = WritableMemory.allocateDirect(1024); assertTrue(wmem.isValid());
+  }
+
+  Runnable tryMapClose = () -> {
+    try { mem.close(); fail(); }
+    catch (IllegalStateException expected) { }
+  };
+
+  Runnable tryDirectClose = () -> {
+    try { wmem.close(); fail(); }
+    catch (IllegalStateException expected) { }
+  };
+
+  @Test
+  public void runTests() {
+    initMap();
+    altThread = new Thread(tryMapClose, "altThread"); altThread.start();
+    mem.close();
+    initDirectMem();
+    altThread = new Thread(tryDirectClose, "altThread"); altThread.start();
+    wmem.close();
+  }
+
+}
+
diff --git a/pom.xml b/pom.xml
index 7085c35..40be1a9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -99,7 +99,7 @@ under the License.
     <!-- END:UNIQUE FOR THIS JAVA COMPONENT -->
 
     <!-- Test -->
-    <testng.version>7.5</testng.version>
+    <testng.version>7.4.0</testng.version>
 
     <!-- System-wide properties -->
     <maven.version>3.5.0</maven.version>


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datasketches.apache.org
For additional commands, e-mail: commits-help@datasketches.apache.org