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/01/29 22:41:26 UTC

[datasketches-memory] 02/02: Changed nearly all asserts to checks.

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

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

commit d1cd1cf9357d114f1904d3ab168e1a2d7f5a08af
Author: Lee Rhodes <le...@users.noreply.github.com>
AuthorDate: Sun Jan 29 14:41:10 2023 -0800

    Changed nearly all asserts to checks.
    
    Added more descriptive exceptions
    Eliminated Handles.
    Moved AutoCloseable close() to Resource, the root of the hierarchy.
    Moved load(), isLoaded() and force() also to Resource.
---
 ...java => BufferPositionInvariantsException.java} |  22 +-
 .../org/apache/datasketches/memory/Handle.java     |  59 ----
 .../java/org/apache/datasketches/memory/Map.java   |  46 ----
 .../org/apache/datasketches/memory/MapHandle.java  |  30 --
 .../org/apache/datasketches/memory/Memory.java     |  20 +-
 ...WritableMap.java => MemoryBoundsException.java} |  17 +-
 .../datasketches/memory/MemoryCloseException.java  |   3 +-
 ...ableHandle.java => MemoryInvalidException.java} |  16 +-
 .../org/apache/datasketches/memory/Resource.java   | 254 +++++++++++------
 .../apache/datasketches/memory/WritableMemory.java |  25 +-
 .../memory/internal/AllocateDirect.java            |  44 ++-
 .../memory/internal/AllocateDirectWritableMap.java | 122 ++++-----
 .../internal/BBNonNativeWritableBufferImpl.java    |  14 +-
 .../internal/BBNonNativeWritableMemoryImpl.java    |  14 +-
 .../memory/internal/BBWritableBufferImpl.java      |  14 +-
 .../memory/internal/BBWritableMemoryImpl.java      |  14 +-
 .../memory/internal/BaseBufferImpl.java            |  47 +---
 .../memory/internal/BaseWritableBufferImpl.java    |  78 +++---
 .../memory/internal/BaseWritableMemoryImpl.java    |  91 +++---
 .../memory/internal/CompareAndCopy.java            |  37 ++-
 .../DirectNonNativeWritableBufferImpl.java         |  44 +--
 .../DirectNonNativeWritableMemoryImpl.java         |  41 +--
 .../memory/internal/DirectWritableBufferImpl.java  |  44 +--
 .../memory/internal/DirectWritableMemoryImpl.java  |  40 +--
 .../internal/HeapNonNativeWritableBufferImpl.java  |  12 +-
 .../internal/HeapNonNativeWritableMemoryImpl.java  |  12 +-
 .../memory/internal/HeapWritableBufferImpl.java    |  12 +-
 .../memory/internal/HeapWritableMemoryImpl.java    |  12 +-
 .../memory/internal/MapHandleImpl.java             |  57 ----
 .../internal/MapNonNativeWritableBufferImpl.java   |  59 ++--
 .../internal/MapNonNativeWritableMemoryImpl.java   |  55 ++--
 .../memory/internal/MapWritableBufferImpl.java     |  59 ++--
 .../memory/internal/MapWritableMemoryImpl.java     |  54 ++--
 .../memory/internal/NativeWritableBufferImpl.java  |  60 ++--
 .../memory/internal/NativeWritableMemoryImpl.java  |  57 ++--
 .../internal/NonNativeWritableBufferImpl.java      |  35 +--
 .../internal/NonNativeWritableMemoryImpl.java      |  32 +--
 .../datasketches/memory/internal/ResourceImpl.java | 305 ++++++++++++---------
 .../datasketches/memory/internal/UnsafeUtil.java   |  30 --
 .../apache/datasketches/memory/internal/Util.java  |   2 +-
 .../memory/internal/VirtualMachineMemory.java      |   8 +
 .../memory/internal/WritableDirectHandleImpl.java  |  67 -----
 .../memory/internal/WritableMapHandleImpl.java     |  52 ----
 .../internal/AllocateDirectMapMemoryTest.java      | 112 +++-----
 .../memory/internal/AllocateDirectMemoryTest.java  |  47 +---
 .../AllocateDirectWritableMapMemoryTest.java       |  71 ++---
 .../memory/internal/BaseBufferTest.java            |  22 +-
 .../datasketches/memory/internal/Buffer2Test.java  |   8 +-
 .../memory/internal/BufferBoundaryCheckTest.java   | 191 +++----------
 .../memory/internal/BufferInvariantsTest.java      |  10 +-
 .../memory/internal/BufferReadWriteSafetyTest.java |  38 +--
 .../datasketches/memory/internal/BufferTest.java   |  24 +-
 .../memory/internal/CommonBufferTest.java          |  17 +-
 .../memory/internal/CommonMemoryTest.java          |  25 +-
 .../memory/internal/CopyMemoryOverlapTest.java     |   7 +-
 .../memory/internal/CopyMemoryTest.java            |  17 +-
 .../memory/internal/DruidIssue11544Test.java       |   6 +-
 .../internal/ExampleMemoryRequestServerTest.java   | 177 ------------
 .../memory/internal/IgnoredArrayOverflowTest.java  |  11 +-
 .../datasketches/memory/internal/LeafImplTest.java |  70 +++--
 .../memory/internal/MemoryBoundaryCheckTest.java   | 161 +++--------
 .../memory/internal/MemoryReadWriteSafetyTest.java | 116 ++++----
 .../datasketches/memory/internal/MemoryTest.java   | 121 +++-----
 .../memory/internal/MemoryWriteToTest.java         |   4 +-
 .../memory/internal/MurmurHash3v2Test.java         |   4 +-
 .../internal/NativeWritableBufferImplTest.java     |  77 +++---
 .../internal/NativeWritableMemoryImplTest.java     | 128 ++++-----
 .../internal/NonNativeWritableMemoryImplTest.java  |  14 +-
 .../datasketches/memory/internal/ResourceTest.java |   8 +-
 .../memory/internal/SpecificLeafTest.java          |  14 +-
 .../datasketches/memory/internal/Utf8Test.java     |  81 +++---
 .../datasketches/memory/internal/UtilTest.java     |   5 +-
 .../memory/internal/WritableDirectCopyTest.java    |  69 ++---
 .../memory/internal/ZeroCapacityTest.java          |  14 +-
 74 files changed, 1466 insertions(+), 2319 deletions(-)

diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/WritableMapHandle.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/BufferPositionInvariantsException.java
similarity index 68%
rename from datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/WritableMapHandle.java
rename to datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/BufferPositionInvariantsException.java
index 7cf9f18..c759645 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/WritableMapHandle.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/BufferPositionInvariantsException.java
@@ -19,12 +19,16 @@
 
 package org.apache.datasketches.memory;
 
-/**
- * A Handle for a memory-mapped, writable file resource.
- * Joins a WritableHandle with an AutoCloseable WritableMap resource
- * Please read Javadocs for {@link Handle}.
- *
- * @author Roman Leventov
- * @author Lee Rhodes
- */
-public interface WritableMapHandle extends WritableMap, WritableHandle { }
+public class BufferPositionInvariantsException extends MemoryException {
+  private static final long serialVersionUID = 1L;
+
+  /**
+   * The associated position operation used violated the positional invariants equation with required details
+   *
+   * @param details of the violation.
+   */
+  public BufferPositionInvariantsException(final String details) {
+    super(details);
+  }
+}
+
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/Handle.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/Handle.java
deleted file mode 100644
index 04efe46..0000000
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/Handle.java
+++ /dev/null
@@ -1,59 +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;
-
-/**
- * A handle for read-only Memory resource.
- *
- * <p>The purpose of a Handle is to
- * <ul><li>Provide a <i>strong reference</i> to an external <i>resource</i>.</li>
- * <li>Extend <i>AutoCloseable</i>, which provides a means to close the resource.</li>
- * <li>Provide other capabilities unique to a particular resource.</li>
- * </ul>
- *
- * <p>Maintaining strong references to external resources is critical to avoid accidental
- * <i>use-after-free</i> scenarios, where the Garbage Collector will automatically close an external
- * resource if there are no remaining strong references to it. One very common mistake, is to allow
- * a newly created Handle to fall out-of-scope from the block where it was created, such as from a
- * try-with-resources statement. The Garbage Collector will eventually close the Handle referent
- * resource.</p>
- *
- * <p>Another <i>use-after-free</i> scenario is where a thread or agent, with access to the
- * Handle, prematurely closes a resource, when another part of the program is still using that
- * same resource. Avoiding this scenario requires careful planning and design.</p>
- *
- * <p>The design philosophy here is that whatever process created the external resource has the
- * responsibility to <i>close()</i> that resource when it is no longer needed.  This responsibility
- * can be delegated, by passing the appropriate Handle to the delegatee. In principle, however, at
- * any one time there should be only one agent holding the Handle and responsible for closing the
- * resource.</p>
- *
- * @author Lee Rhodes
- * @author Roman Leventov
- */
-public interface Handle extends AutoCloseable {
-
-  /**
-   * Gets a Memory
-   * @return a Memory
-   */
-  Memory get();
-
-}
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/Map.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/Map.java
deleted file mode 100644
index 6b99059..0000000
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/Map.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;
-
-/**
- * Read only interface for a memory mapped file
- *
- * @author Roman Leventov
- * @author Lee Rhodes
- * @author Praveenkumar Venkatesan
- */
-public interface Map extends AutoCloseable {
-
-  /**
-   * @see <a href="https://docs.oracle.com/javase/8/docs/api/java/nio/MappedByteBuffer.html#load--">
-   * java/nio/MappedByteBuffer.load</a>
-   */
-  void load();
-
-  /**
-   * @return true if loaded
-   *
-   * @see <a href=
-   * "https://docs.oracle.com/javase/8/docs/api/java/nio/MappedByteBuffer.html#isLoaded--"> java
-   * /nio/MappedByteBuffer.isLoaded</a>
-   */
-  boolean isLoaded();
-
-}
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/MapHandle.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/MapHandle.java
deleted file mode 100644
index d0c498e..0000000
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/MapHandle.java
+++ /dev/null
@@ -1,30 +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;
-
-/**
- * A Handle for a memory-mapped, read-only file resource. This
- * joins a Read-only Handle with an AutoCloseable Map resource.
- * Please read Javadocs for {@link Handle}.
- *
- * @author Lee Rhodes
- * @author Roman Leventov
- */
-public interface MapHandle extends Map, Handle { }
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/Memory.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/Memory.java
index 3500d93..afe381e 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/Memory.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/Memory.java
@@ -30,7 +30,7 @@ import java.util.Objects;
 
 import org.apache.datasketches.memory.internal.BaseWritableMemoryImpl;
 import org.apache.datasketches.memory.internal.Prim;
-import org.apache.datasketches.memory.internal.UnsafeUtil;
+import org.apache.datasketches.memory.internal.ResourceImpl;
 
 /**
  * Defines the read-only API for offset access to a resource.
@@ -71,10 +71,9 @@ public interface Memory extends Resource {
    * Calling this method is equivalent to calling
    * {@link #map(File, long, long, ByteOrder) map(file, 0, file.length(), ByteOrder.nativeOrder())}.
    * @param file the given file to map. It must be non-null, length &ge; 0, and readable.
-   * @return <i>MapHandle</i> for managing the mapped memory.
-   * Please read Javadocs for {@link Handle}.
+   * @return <i>Memory</i> for managing the mapped memory.
    */
-  static MapHandle map(File file) {
+  static Memory map(File file) {
     return map(file, 0, file.length(), ByteOrder.nativeOrder());
   }
 
@@ -84,16 +83,15 @@ public interface Memory extends Resource {
    * @param fileOffsetBytes the position in the given file in bytes. It must not be negative.
    * @param capacityBytes the size of the mapped memory. It must not be negative.
    * @param byteOrder the byte order to be used for the mapped memory. It must be non-null.
-   * @return <i>MapHandle</i> for managing the mapped memory.
-   * Please read Javadocs for {@link Handle}.
+   * @return <i>Memory</i> for managing the mapped memory.
    */
-  static MapHandle map(File file, long fileOffsetBytes, long capacityBytes, ByteOrder byteOrder) {
+  static Memory map(File file, long fileOffsetBytes, long capacityBytes, ByteOrder byteOrder) {
     Objects.requireNonNull(file, "file must be non-null.");
     Objects.requireNonNull(byteOrder, "byteOrder must be non-null.");
-    if (!file.canRead()) { throw new IllegalArgumentException("file must be readable."); }
+    if (!file.canRead()) { throw new ReadOnlyException("file must be readable."); }
     negativeCheck(fileOffsetBytes, "fileOffsetBytes");
     negativeCheck(capacityBytes, "capacityBytes");
-    return (MapHandle) BaseWritableMemoryImpl.wrapMap(file, fileOffsetBytes, capacityBytes, true, byteOrder);
+    return BaseWritableMemoryImpl.wrapMap(file, fileOffsetBytes, capacityBytes, true, byteOrder);
   }
 
   //REGIONS
@@ -194,7 +192,7 @@ public interface Memory extends Resource {
     Objects.requireNonNull(byteOrder, "byteOrder must be non-null");
     negativeCheck(offsetBytes, "offsetBytes");
     negativeCheck(lengthBytes, "lengthBytes");
-    UnsafeUtil.checkBounds(offsetBytes, lengthBytes, array.length);
+    ResourceImpl.checkBounds(offsetBytes, lengthBytes, array.length);
     return BaseWritableMemoryImpl.wrapHeapArray(array, 0, lengthBytes, true, ByteOrder.nativeOrder(), null);
   }
 
@@ -484,5 +482,3 @@ public interface Memory extends Resource {
       throws IOException;
 
 }
-
-
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/WritableMap.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/MemoryBoundsException.java
similarity index 71%
rename from datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/WritableMap.java
rename to datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/MemoryBoundsException.java
index 21502a7..501012d 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/WritableMap.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/MemoryBoundsException.java
@@ -20,18 +20,21 @@
 package org.apache.datasketches.memory;
 
 /**
- * Writable interface for a memory mapped file
+ * Specific RuntimeException for bounds violations.
  *
- * @author Roman Leventov
  * @author Lee Rhodes
- * @author Praveenkumar Venkatesan
  */
-public interface WritableMap extends Map {
+public class MemoryBoundsException extends MemoryException {
+  private static final long serialVersionUID = 1L;
 
   /**
-   * @see <a href="https://docs.oracle.com/javase/8/docs/api/java/nio/MappedByteBuffer.html#force--">
-   * java/nio/MappedByteBuffer.force</a>
+   * The associated operation violated access bounds with required details.
+   *
+   * @param details of the violation.
    */
-  void force();
+  public MemoryBoundsException(final String details) {
+    super(details);
+  }
 
 }
+
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
index 3238927..593df3c 100644
--- 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
@@ -23,10 +23,9 @@ 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 = 2L;
+  private static final long serialVersionUID = 1L;
 
   /**
    * The associated resource failed to close.
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/WritableHandle.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/MemoryInvalidException.java
similarity index 75%
rename from datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/WritableHandle.java
rename to datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/MemoryInvalidException.java
index 5546d5e..e85eb39 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/WritableHandle.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/MemoryInvalidException.java
@@ -20,17 +20,19 @@
 package org.apache.datasketches.memory;
 
 /**
- * A Handle for writable direct memory or a memory-mapped, writable file resource.
- * Please read Javadocs for {@link Handle}.
+ * Specific RuntimeException for invalid Memory.
  *
  * @author Lee Rhodes
- * @author Roman Leventov
  */
-public interface WritableHandle extends Handle {
+public class MemoryInvalidException extends MemoryException {
+  private static final long serialVersionUID = 1L;
 
   /**
-   * Gets a WritableMemory
-   * @return a WritableMemory
+   * The associated resource failed to close.
    */
-  WritableMemory getWritable();
+  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 ec9af82..591379b 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,17 +19,18 @@
 
 package org.apache.datasketches.memory;
 
+import java.io.UncheckedIOException;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 
-import org.apache.datasketches.memory.internal.ResourceImpl;
-
 /**
  *  Methods common to all memory access resources, including attributes like byte order and capacity.
  *
  * @author Lee Rhodes
  */
-public interface Resource {
+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
@@ -41,39 +42,85 @@ public interface Resource {
   void checkValidAndBounds(long offsetBytes, long lengthBytes);
 
   /**
-   * The placeholder for the default MemoryRequestServer, if set at all.
+   * 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>,
+   * and subsequent operations on this resource will fail with {@link IllegalStateException}.
+   *
+   * @apiNote This operation is not idempotent; that is, closing an already closed resource <em>always</em>
+   * results in an exception being thrown. This reflects a deliberate design choice: resource state transitions
+   * 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 UnsupportedOperationException if this resource is not {@link AutoCloseable}.
    */
-  static final MemoryRequestServer defaultMemReqSvr = null; //new DefaultMemoryRequestServer();
-
-
+  @Override
+  default void close() {/* Overridden by the actual AutoCloseable sub-classes. */ }
 
   /**
-   * Returns true if the given object is an instance of this class and has equal data contents.
-   * @param that the given object
-   * @return true if the given Object is an instance of this class and has equal data contents.
+   * 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.
    */
-  @Override
-  boolean equals(Object that);
+  default boolean equalTo(Resource that) {
+    if (that == null || this.getCapacity() != that.getCapacity()) { return false; }
+    else { return equalTo(0, that, 0, that.getCapacity()); }
+  }
 
   /**
-   * Returns true if the given object is an instance of this class and has equal contents to
+   * Returns true if the given Resource has equal contents to
    * this object in the given range of bytes. This will also check two distinct ranges within the
    * same object for equals.
    * @param thisOffsetBytes the starting offset in bytes for this object.
-   * @param that the given object
-   * @param thatOffsetBytes the starting offset in bytes for the given object
+   * @param that the given Resource
+   * @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 object has equal contents to this object in the given range of
-   * bytes.
+   * @return true if the given Resource object has equal contents to this object in the given range of bytes.
    */
-  boolean equalTo(long thisOffsetBytes, Object that,
-      long thatOffsetBytes, long lengthBytes);
+  boolean equalTo(long thisOffsetBytes, Resource that, long thatOffsetBytes, long lengthBytes);
+
+  /**
+   * Forces any changes made to the contents of this memory-mapped Resource to be written to the storage
+   * device described by the configured file descriptor.
+   *
+   * <p>If the file descriptor associated with this memory-mapped Resource resides on a local storage device then when
+   * this method returns, it is guaranteed that all changes made to this mapped Resource since it was created, or since
+   * this method was last invoked, will have been written to that device.</p>
+   *
+   * <p>If the file descriptor associated with this memory-mapped Resource does not reside on a local device then no
+   * such guarantee is made.</p>
+   *
+   * <p>If this memory-mapped Resource was not mapped in read/write mode
+   * ({@link java.nio.channels.FileChannel.MapMode#READ_WRITE}) then invoking this method may have no effect.
+   * 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
+   */
+  void force();
 
   /**
    * Gets the backing ByteBuffer if it exists, otherwise returns null.
    * @return the backing ByteBuffer if it exists, otherwise returns null.
    */
-  ByteBuffer getByteBuffer();
+  ByteBuffer getByteBuffer(); //TODO Deprecate
 
   /**
    * Gets the current ByteOrder.
@@ -88,39 +135,11 @@ public interface Resource {
    */
   long getCapacity();
 
-  //Monitoring
   /**
-   * Gets the current size of active direct memory allocated.
-   * @return the current size of active direct memory allocated.
+   * Returns the MemoryRequestSever or null, if it has not been configured.
+   * @return the MemoryRequestSever or null, if it has not been configured.
    */
-  static long getCurrentDirectMemoryAllocated() {
-    return ResourceImpl.getCurrentDirectMemoryAllocated();
-  }
-
-  /**
-   * Gets the current number of active direct memory allocations.
-   * @return the current number of active direct memory allocations.
-   */
-  static long getCurrentDirectMemoryAllocations() {
-    return ResourceImpl.getCurrentDirectMemoryAllocations();
-  }
-
-  /**
-   * Gets the current size of active direct memory map allocated.
-   * @return the current size of active direct memory map allocated.
-   */
-  static long getCurrentDirectMemoryMapAllocated() {
-    return ResourceImpl.getCurrentDirectMemoryMapAllocated();
-  }
-
-  /**
-   * Gets the current number of active direct memory map allocations.
-   * @return the current number of active direct memory map allocations.
-   */
-  static long getCurrentDirectMemoryMapAllocations() {
-    return ResourceImpl.getCurrentDirectMemoryMapAllocations();
-  }
-  //End Monitoring
+  MemoryRequestServer getMemoryRequestServer();
 
   /**
    * Returns the offset of address zero of this object relative to the base address of the
@@ -135,28 +154,20 @@ public interface Resource {
    * 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
    */
-  boolean hasArray();
+  boolean hasArray(); //TODO Change to isHeapResource
 
   /**
-   * Returns true if this Memory is backed by a ByteBuffer.
-   * @return true if this Memory is backed by a ByteBuffer.
+   * Returns true if this object is valid and has not been closed.
+   * This is relevant only for direct (off-heap) memory and Mapped Files.
+   * @return true if this object is valid and has not been closed.
    */
-  boolean hasByteBuffer();
+  boolean isValid(); //TODO isAlive()
 
   /**
-   * Returns the hashCode of this object.
-   *
-   * <p>The hash code of this object depends upon all of its contents.
-   * Because of this, it is inadvisable to use these objects as keys in hash maps
-   * or similar data structures unless it is known that their contents will not change.</p>
-   *
-   * <p>If it is desirable to use these objects in a hash map depending only on object identity,
-   * than the {@link java.util.IdentityHashMap} can be used.</p>
-   *
-   * @return the hashCode of this object.
+   * Returns true if this Memory is backed by a ByteBuffer.
+   * @return true if this Memory is backed by a ByteBuffer.
    */
-  @Override
-  int hashCode();
+  boolean isByteBufferResource();
 
   /**
    * Returns true if the Native ByteOrder is the same as the ByteOrder of the
@@ -168,11 +179,74 @@ public interface Resource {
   boolean isByteOrderCompatible(ByteOrder byteOrder);
 
   /**
-   * Returns true if the backing resource is direct (off-heap) memory.
-   * This is the case for allocated direct memory, memory mapped files,
+   * If true, the backing resource is direct (off-heap) memory.
+   * This is the case for allocated direct memory, memory-mapped files,
+   * or from a wrapped ByteBuffer that was allocated direct.
+   * If false, the backing resource is the Java heap.
    * @return true if the backing resource is direct (off-heap) memory.
    */
-  boolean isDirect();
+  boolean isDirectResource();
+
+  /**
+   * Returns true if this instance is a duplicate of a Buffer instance.
+   * @return true if this instance is a duplicate of a Buffer instance.
+   */
+  boolean isDuplicateBufferView();
+
+  /**
+   * Tells whether or not the contents of this memory-mapped Resource is resident in physical memory.
+   *
+   * <p>A return value of {@code true} implies that it is highly likely that all of the data in this memory-mapped
+   * Resource is resident in physical memory and may therefore be accessed without incurring any virtual-memory page
+   * faults or I/O operations.</p>
+   *
+   * <p>A return value of {@code false} does not necessarily imply that all of the data in this memory-mapped Resource
+   * is not resident in physical memory.</p>
+   *
+   * <p>The returned value is a hint, rather than a guarantee, because the underlying operating system may have paged
+   * out some of this Resource's data by the time that an invocation of this method returns.</p>
+   *
+   * @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}.
+   */
+  boolean isLoaded();
+
+  /**
+   * If true, this is a <i>Memory</i> or <i>WritableMemory</i> instance, which provides the Memory API.
+   * The Memory API is the principal API for this Memory Component.
+   * It provides a rich variety of direct manipulations of four types of resources:
+   * On-heap memory, direct (off-heap) memory, memory-mapped files, and ByteBuffers.
+   * If false, this is a <i>Buffer</i> or <i>WritableBuffer</i> instance, which provides the Buffer API.
+   *
+   * <p>The Buffer API is largely parallel to the Memory API except that it adds a positional API
+   * similar to that in <i>ByteBuffer</i>.  The positional API is a convenience when iterating over structured
+   * arrays, or buffering input or output streams (thus the name).</p>
+   *
+   * @return true if this is a <i>Memory</i> or <i>WritableMemory</i> instance, which provides the Memory API,
+   * otherwise this is a <i>Buffer</i> or <i>WritableBuffer</i> instance, which provides the Buffer API.
+   */
+  boolean isMemoryApi();
+
+  /**
+   * Returns true if the backing resource is a memory-mapped file.
+   * @return true if the backing resource is a memory-mapped file.
+   */
+  boolean isMapped();
+
+  /**
+   * If true, all put and get operations will assume the non-native ByteOrder.
+   * Otherwise, all put and get operations will assume the native ByteOrder.
+   * @return true, if all put and get operations will assume the non-native ByteOrder.
+   */
+  boolean isNonNativeOrder();
 
   /**
    * Returns true if this object or the backing resource is read-only.
@@ -180,29 +254,53 @@ public interface Resource {
    */
   boolean isReadOnly();
 
+  /**
+   * Returns true if this instance is a region view of another Memory or Buffer
+   * @return true if this instance is a region view of another Memory or Buffer
+   */
+  boolean isRegionView();
+
   /**
    * Returns true if the backing resource of <i>this</i> is identical with the backing resource
    * of <i>that</i>. The capacities must be the same.  If <i>this</i> is a region,
    * the region offset must also be the same.
-   * @param that A different non-null object
+   * @param that A different non-null Resource
    * @return true if the backing resource of <i>this</i> is the same as the backing resource
    * of <i>that</i>.
    */
-  boolean isSameResource(Object that);
+  boolean isSameResource(Resource that);
 
   /**
-   * Returns true if this object is valid and has not been closed.
-   * This is relevant only for direct (off-heap) memory and Mapped Files.
-   * @return true if this object is valid and has not been closed.
+   * Loads the contents of this memory-mapped Resource into physical memory.
+   *
+   * <p>This method makes a best effort to ensure that, when it returns, this contents of the memory-mapped Resource is
+   * 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}.
+   */
+  void load();
+
+  /**
+   * Sets the MemoryRequestServer.
+   * @param memReqSvr the given MemoryRequestServer.
    */
-  boolean isValid();
+  void setMemoryRequestServer(MemoryRequestServer memReqSvr);
 
   /**
-   * Returns a formatted hex string of a range of this object.
-   * Used primarily for testing.
+   * Returns a description of this object with an optional formatted hex string of the data
+   * for the specified a range. Used primarily for testing.
    * @param header a descriptive header
    * @param offsetBytes offset bytes relative to this object start
    * @param lengthBytes number of bytes to convert to a hex string
+// @param withData include output listing of byte data in the given range
    * @return a formatted hex string in a human readable array
    */
   String toHexString(String header, long offsetBytes, int lengthBytes);
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 d8fbd12..fc7d22f 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
@@ -28,7 +28,7 @@ import java.util.Objects;
 
 import org.apache.datasketches.memory.internal.BaseWritableMemoryImpl;
 import org.apache.datasketches.memory.internal.Prim;
-import org.apache.datasketches.memory.internal.UnsafeUtil;
+import org.apache.datasketches.memory.internal.ResourceImpl;
 
 /**
  * Defines the writable API for offset access to a resource.
@@ -84,10 +84,9 @@ public interface WritableMemory extends Memory {
    * Calling this method is equivalent to calling
    * {@link #writableMap(File, long, long, ByteOrder) writableMap(file, 0, file.length(), ByteOrder.nativeOrder())}.
    * @param file the given file to map. It must be non-null, with length &ge; 0, and writable.
-   * @return WritableMapHandle for managing the mapped Memory.
-   * Please read Javadocs for {@link Handle}.
+   * @return WritableMemory for managing the mapped Memory.
    */
-  static WritableMapHandle writableMap(File file) {
+  static WritableMemory writableMap(File file) {
     return writableMap(file, 0, file.length(), ByteOrder.nativeOrder());
   }
 
@@ -100,10 +99,9 @@ public interface WritableMemory extends Memory {
    * @param fileOffsetBytes the position in the given file in bytes. It must not be negative.
    * @param capacityBytes the size of the mapped Memory. It must not be negative.
    * @param byteOrder the byte order to be used for the given file. It must be non-null.
-   * @return WritableMapHandle for managing the mapped Memory.
-   * Please read Javadocs for {@link Handle}.
+   * @return WritableMemory for managing the mapped Memory.
    */
-  static WritableMapHandle writableMap(File file, long fileOffsetBytes, long capacityBytes, ByteOrder byteOrder) {
+  static WritableMemory writableMap(File file, long fileOffsetBytes, long capacityBytes, ByteOrder byteOrder) {
     Objects.requireNonNull(file, "file must be non-null.");
     Objects.requireNonNull(byteOrder, "byteOrder must be non-null.");
     if (!file.canWrite()) { throw new ReadOnlyException("file must be writable."); }
@@ -124,10 +122,9 @@ public interface WritableMemory extends Memory {
    * and to call <i>close()</i> when done.</p>
    *
    * @param capacityBytes the size of the desired memory in bytes. It must be &ge; 0.
-   * @return WritableHandle for this off-heap resource.
-   * Please read Javadocs for {@link Handle}.
+   * @return WritableMemory for this off-heap resource.
    */
-  static WritableHandle allocateDirect(long capacityBytes) {
+  static WritableMemory allocateDirect(long capacityBytes) {
     return allocateDirect(capacityBytes, ByteOrder.nativeOrder(), defaultMemReqSvr);
   }
 
@@ -143,10 +140,9 @@ public interface WritableMemory extends Memory {
    * @param byteOrder the given byte order. It must be non-null.
    * @param memReqSvr A user-specified MemoryRequestServer, which may be null.
    * This is a callback mechanism for a user client of direct memory to request more memory.
-   * @return WritableHandle for this off-heap resource.
-   * Please read Javadocs for {@link Handle}.
+   * @return WritableMemory for this off-heap resource.
    */
-  static WritableHandle allocateDirect(long capacityBytes, ByteOrder byteOrder, MemoryRequestServer memReqSvr) {
+  static WritableMemory allocateDirect(long capacityBytes, ByteOrder byteOrder, MemoryRequestServer memReqSvr) {
     Objects.requireNonNull(byteOrder, "byteOrder must be non-null");
     negativeCheck(capacityBytes, "capacityBytes");
     return BaseWritableMemoryImpl.wrapDirect(capacityBytes, byteOrder, memReqSvr);
@@ -317,7 +313,7 @@ public interface WritableMemory extends Memory {
     Objects.requireNonNull(byteOrder, "byteOrder must be non-null");
     negativeCheck(offsetBytes, "offsetBytes");
     negativeCheck(lengthBytes, "lengthBytes");
-    UnsafeUtil.checkBounds(offsetBytes, lengthBytes, array.length);
+    ResourceImpl.checkBounds(offsetBytes, lengthBytes, array.length);
     return BaseWritableMemoryImpl.wrapHeapArray(array, offsetBytes, lengthBytes, false, byteOrder, memReqSvr);
   }
 
@@ -634,6 +630,7 @@ public interface WritableMemory extends Memory {
    * in the test tree.
    * @return the MemoryRequestServer object or null.
    */
+  @Override
   MemoryRequestServer getMemoryRequestServer();
 
 }
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 f6bafd0..107cf1b 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
@@ -23,6 +23,8 @@ 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.
  *
@@ -30,12 +32,13 @@ import java.util.logging.Logger;
  * @author Lee Rhodes
  */
 @SuppressWarnings("restriction")
-final class AllocateDirect {
+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.
@@ -46,11 +49,10 @@ final class AllocateDirect {
    * @param capacityBytes the the requested capacity of off-heap memory. Cannot be zero.
    */
   AllocateDirect(final long capacityBytes) {
-    final boolean pageAligned = NioBits.isPageAligned();
-    final long pageSize = NioBits.pageSize();
+    final boolean pageAligned = VirtualMachineMemory.getIsPageAligned();
+    final long pageSize = VirtualMachineMemory.getPageSize();
     final long allocationSize = capacityBytes + (pageAligned ? pageSize : 0);
-    NioBits.reserveMemory(allocationSize, capacityBytes);
-
+    this.owner = Thread.currentThread();
     final long nativeAddress;
     try {
       nativeAddress = unsafe.allocateMemory(allocationSize);
@@ -64,47 +66,44 @@ final class AllocateDirect {
     } else {
       nativeBaseOffset = nativeAddress;
     }
-    deallocator = new Deallocator(nativeAddress, allocationSize, capacityBytes);
+    deallocator = new Deallocator(nativeAddress);
     cleaner = new MemoryCleaner(this, deallocator);
   }
 
-  boolean doClose() {
+  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
         // list of all cleaners. It will delegate to Deallocator.deallocate() which will be a no-op
         // because the valid state is already changed.
         cleaner.clean();
-        return true;
       }
-      return false;
     } finally {
       ResourceImpl.reachabilityFence(this);
     }
   }
 
+  public final void checkValidAndThread() {
+    if (!getValid().get()) { throw new MemoryCloseException("Already closed"); }
+    ResourceImpl.checkThread(owner);
+  }
+
   long getNativeBaseOffset() {
     return nativeBaseOffset;
   }
 
-  StepBoolean getValid() {
+  public StepBoolean getValid() {
     return deallocator.getValid();
   }
 
-  static final class Deallocator implements Runnable {
+  private static final class Deallocator implements Runnable {
     //This is the only place the actual native address is kept for use by unsafe.freeMemory();
     private final long nativeAddress;
-    private final long allocationSize;
-    private final long capacity;
     private final StepBoolean valid = new StepBoolean(true); //only place for this
 
-    Deallocator(final long nativeAddress, final long allocationSize, final long capacity) {
-      ResourceImpl.currentDirectMemoryAllocations_.incrementAndGet();
-      ResourceImpl.currentDirectMemoryAllocated_.addAndGet(capacity);
+    Deallocator(final long nativeAddress) {
       this.nativeAddress = nativeAddress;
-      this.allocationSize = allocationSize;
-      this.capacity = capacity;
-      assert (nativeAddress != 0);
     }
 
     StepBoolean getValid() {
@@ -112,20 +111,17 @@ final class AllocateDirect {
     }
 
     @Override
-    public void run() {
+    public void run() throws MemoryCloseException {
       deallocate(true);
     }
 
-    boolean deallocate(final boolean calledFromCleaner) {
+    boolean deallocate(final boolean calledFromCleaner) throws MemoryCloseException {
       if (valid.change()) {
         if (calledFromCleaner) {
           // Warn about non-deterministic resource cleanup.
           LOG.warning("A WritableHandle was not closed manually");
         }
         unsafe.freeMemory(nativeAddress);
-        NioBits.unreserveMemory(allocationSize, capacity);
-        ResourceImpl.currentDirectMemoryAllocations_.decrementAndGet();
-        ResourceImpl.currentDirectMemoryAllocated_.addAndGet(-capacity);
         return true;
       }
       return false;
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 c217356..f86267f 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
@@ -33,7 +33,6 @@ import java.util.logging.Logger;
 
 import org.apache.datasketches.memory.MemoryCloseException;
 import org.apache.datasketches.memory.ReadOnlyException;
-import org.apache.datasketches.memory.WritableMap;
 
 import sun.nio.ch.FileChannelImpl;
 
@@ -54,7 +53,7 @@ import sun.nio.ch.FileChannelImpl;
  * @author Praveenkumar Venkatesan
  */
 @SuppressWarnings("restriction")
-class AllocateDirectWritableMap implements WritableMap {
+class AllocateDirectWritableMap {
   static final Logger LOG = Logger.getLogger(AllocateDirectWritableMap.class.getCanonicalName());
 
   private static final int MAP_RO = 0;
@@ -97,15 +96,18 @@ class AllocateDirectWritableMap implements WritableMap {
 
   private final Deallocator deallocator;
   private final MemoryCleaner cleaner;
+  private final Thread owner;
 
+  private final File file;
   final long capacityBytes;
   final RandomAccessFile raf;
   final long nativeBaseOffset;
   final boolean resourceReadOnly;
 
-  //called from AllocateDirectWritableMap constructor
   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();
@@ -121,40 +123,30 @@ class AllocateDirectWritableMap implements WritableMap {
     cleaner = new MemoryCleaner(this, deallocator);
   }
 
-  //Map Interface
-
-  @Override
-  public void load() {
-    madvise();
-    // Performance optimization. Read a byte from each page to bring it into memory.
-    final int ps = NioBits.pageSize();
-    final int count = NioBits.pageCount(capacityBytes);
-    long offset = nativeBaseOffset;
-    for (int i = 0; i < count; i++) {
-      unsafe.getByte(offset);
-      offset += ps;
-    }
+  public final void checkValidAndThread() {
+    if (!getValid().get()) { throw new MemoryCloseException("Already closed"); }
+    ResourceImpl.checkThread(owner);
   }
 
-  @Override
-  public boolean isLoaded() {
+  public void close() {
+    checkValidAndThread(); //we must be valid and called from the owner thread
     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);
-    } catch (final  IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
-      throw new RuntimeException(
-              String.format("Encountered %s exception while loading", e.getClass()));
+      if (deallocator.deallocate(false)) {
+        // This Cleaner.clean() call effectively just removes the Cleaner from the internal linked
+        // list of all cleaners. It will delegate to Deallocator.deallocate() which will be a no-op
+        // because the valid state is already changed.
+        cleaner.clean();
+      }
+
+    } catch (final Exception e) {
+        throw new MemoryCloseException("Memory-Mapped File: " + file.getName() + " " + e);
+    } finally {
+      ResourceImpl.reachabilityFence(this);
     }
   }
 
-  //WritableMap Interface
-  @Override
   public void force() {
+    checkValidAndThread();
     if (resourceReadOnly) {
       throw new ReadOnlyException("MemoryImpl Mapped File is Read Only.");
     }
@@ -170,31 +162,41 @@ class AllocateDirectWritableMap implements WritableMap {
     }
   }
 
-  // AutoCloseable Interface
-  @Override
-  public void close() {
-    doClose("AllocateDirectMap");
+  public StepBoolean getValid() {
+    return deallocator.getValid();
+  }
+
+  public static boolean isFileReadOnly(final File file) {
+    return (!file.canWrite());
   }
 
-  boolean doClose(final String resource) {
+  public boolean isLoaded() {
+    checkValidAndThread();
     try {
-      if (deallocator.deallocate(false)) {
-        // This Cleaner.clean() call effectively just removes the Cleaner from the internal linked
-        // list of all cleaners. It will delegate to Deallocator.deallocate() which will be a no-op
-        // because the valid state is already changed.
-        cleaner.clean();
-        return true;
-      }
-      return false;
-    } catch (final Exception e) {
-        throw new MemoryCloseException(resource);
-    } finally {
-      ResourceImpl.reachabilityFence(this);
+      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);
+    } catch (final  IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+      throw new RuntimeException(
+              String.format("Encountered %s exception while loading", e.getClass()));
     }
   }
 
-  StepBoolean getValid() {
-    return deallocator.getValid();
+  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);
+    long offset = nativeBaseOffset;
+    for (int i = 0; i < count; i++) {
+      unsafe.getByte(offset);
+      offset += ps;
+    }
   }
 
   // Private methods
@@ -265,10 +267,6 @@ class AllocateDirectWritableMap implements WritableMap {
     }
   }
 
-  public static boolean isFileReadOnly(final File file) {
-    return (!file.canWrite());
-  }
-
   private static final class Deallocator implements Runnable {
     private final RandomAccessFile myRaf;
     private final FileChannel myFc;
@@ -279,8 +277,6 @@ class AllocateDirectWritableMap implements WritableMap {
 
     Deallocator(final long nativeBaseOffset, final long capacityBytes,
         final RandomAccessFile raf) {
-      ResourceImpl.currentDirectMemoryMapAllocations_.incrementAndGet();
-      ResourceImpl.currentDirectMemoryMapAllocated_.addAndGet(capacityBytes);
       myRaf = raf;
       assert myRaf != null;
       myFc = myRaf.getChannel();
@@ -295,23 +291,17 @@ class AllocateDirectWritableMap implements WritableMap {
     }
 
     @Override
-    public void run() {
+    public void run() throws MemoryCloseException {
       deallocate(true);
     }
 
-    boolean deallocate(final boolean calledFromCleaner) {
+    boolean deallocate(final boolean calledFromCleaner) throws MemoryCloseException {
       if (valid.change()) {
         if (calledFromCleaner) {
           // Warn about non-deterministic resource cleanup.
           LOG.warning("A WritableMapHandleImpl was not closed manually");
         }
-        try {
-          unmap();
-        }
-        finally {
-          ResourceImpl.currentDirectMemoryMapAllocations_.decrementAndGet();
-          ResourceImpl.currentDirectMemoryMapAllocated_.addAndGet(-myCapacity);
-        }
+        unmap();
         return true;
       }
       return false;
@@ -321,12 +311,12 @@ class AllocateDirectWritableMap implements WritableMap {
      * Removes existing mapping.  <i>unmap0</i> is a native method in FileChannelImpl.c. See
      * reference at top of class.
      */
-    private void unmap() throws RuntimeException {
+    private void unmap() throws MemoryCloseException {
       try {
         FILE_CHANNEL_IMPL_UNMAP0_METHOD.invoke(myFc, actualNativeBaseOffset, myCapacity);
         myRaf.close();
       } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException | IOException e) {
-        throw new RuntimeException(
+        throw new MemoryCloseException(
             String.format("Encountered %s exception while freeing memory", e.getClass()));
       }
     }
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 a024f11..f6888de 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
@@ -114,47 +114,49 @@ final class BBNonNativeWritableBufferImpl extends NonNativeWritableBufferImpl {
 
   @Override
   public long getCapacity() {
-    assertValid();
+    checkValid();
     return capacityBytes;
   }
 
   @Override
   public long getCumulativeOffset() {
-    assertValid();
+    checkValid();
     return cumOffsetBytes;
   }
 
   @Override
   public MemoryRequestServer getMemoryRequestServer() {
+    checkValid();
     return memReqSvr;
   }
 
   @Override
   public long getNativeBaseOffset() {
+    checkValid();
     return nativeBaseOffset;
   }
 
   @Override
   public long getTotalOffset() {
-    assertValid();
+    checkValid();
     return offsetBytes;
   }
 
   @Override
   int getTypeId() {
-    assertValid();
+    checkValid();
     return typeId;
   }
 
   @Override
   Object getUnsafeObject() {
-    assertValid();
+    checkValid();
     return unsafeObj;
   }
 
   @Override
   public ByteBuffer getByteBuffer() {
-    assertValid();
+    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 80604b4..16ea394 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
@@ -99,47 +99,49 @@ final class BBNonNativeWritableMemoryImpl extends NonNativeWritableMemoryImpl {
 
   @Override
   public long getCapacity() {
-    assertValid();
+    checkValid();
     return capacityBytes;
   }
 
   @Override
   public long getCumulativeOffset() {
-    assertValid();
+    checkValid();
     return cumOffsetBytes;
   }
 
   @Override
   public MemoryRequestServer getMemoryRequestServer() {
+    checkValid();
     return memReqSvr;
   }
 
   @Override
   public long getNativeBaseOffset() {
+    checkValid();
     return nativeBaseOffset;
   }
 
   @Override
   public long getTotalOffset() {
-    assertValid();
+    checkValid();
     return offsetBytes;
   }
 
   @Override
   int getTypeId() {
-    assertValid();
+    checkValid();
     return typeId;
   }
 
   @Override
   Object getUnsafeObject() {
-    assertValid();
+    checkValid();
     return unsafeObj;
   }
 
   @Override
   public ByteBuffer getByteBuffer() {
-    assertValid();
+    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 fcd47f3..2e3ee93 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
@@ -114,47 +114,49 @@ final class BBWritableBufferImpl extends NativeWritableBufferImpl {
 
   @Override
   public long getCapacity() {
-    assertValid();
+    checkValid();
     return capacityBytes;
   }
 
   @Override
   public long getCumulativeOffset() {
-    assertValid();
+    checkValid();
     return cumOffsetBytes;
   }
 
   @Override
   public MemoryRequestServer getMemoryRequestServer() {
+    checkValid();
     return memReqSvr;
   }
 
   @Override
   public long getNativeBaseOffset() {
+    checkValid();
     return nativeBaseOffset;
   }
 
   @Override
   public long getTotalOffset() {
-    assertValid();
+    checkValid();
     return offsetBytes;
   }
 
   @Override
   int getTypeId() {
-    assertValid();
+    checkValid();
     return typeId;
   }
 
   @Override
   Object getUnsafeObject() {
-    assertValid();
+    checkValid();
     return unsafeObj;
   }
 
   @Override
   public ByteBuffer getByteBuffer() {
-    assertValid();
+    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 c80bcef..0d09c08 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
@@ -99,47 +99,49 @@ final class BBWritableMemoryImpl extends NativeWritableMemoryImpl {
 
   @Override
   public long getCapacity() {
-    assertValid();
+    checkValid();
     return capacityBytes;
   }
 
   @Override
   public long getCumulativeOffset() {
-    assertValid();
+    checkValid();
     return cumOffsetBytes;
   }
 
   @Override
   public MemoryRequestServer getMemoryRequestServer() {
+    checkValid();
     return memReqSvr;
   }
 
   @Override
   public long getNativeBaseOffset() {
+    checkValid();
     return nativeBaseOffset;
   }
 
   @Override
   public long getTotalOffset() {
-    assertValid();
+    checkValid();
     return offsetBytes;
   }
 
   @Override
   int getTypeId() {
-    assertValid();
+    checkValid();
     return typeId;
   }
 
   @Override
   Object getUnsafeObject() {
-    assertValid();
+    checkValid();
     return unsafeObj;
   }
 
   @Override
   public ByteBuffer getByteBuffer() {
-    assertValid();
+    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 22c42eb..eac45de 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
@@ -20,6 +20,7 @@
 package org.apache.datasketches.memory.internal;
 
 import org.apache.datasketches.memory.BaseBuffer;
+import org.apache.datasketches.memory.BufferPositionInvariantsException;
 import org.apache.datasketches.memory.ReadOnlyException;
 
 /**
@@ -53,7 +54,7 @@ public abstract class BaseBufferImpl extends ResourceImpl implements BaseBuffer
 
   @Override
   public final BaseBufferImpl incrementPosition(final long increment) {
-    incrementAndAssertPositionForRead(pos, increment);
+    incrementAndCheckPositionForRead(pos, increment);
     return this;
   }
 
@@ -96,7 +97,7 @@ public abstract class BaseBufferImpl extends ResourceImpl implements BaseBuffer
 
   @Override
   public final BaseBufferImpl setPosition(final long position) {
-    assertInvariants(start, position, end, capacity);
+    checkInvariants(start, position, end, capacity);
     pos = position;
     return this;
   }
@@ -111,7 +112,7 @@ public abstract class BaseBufferImpl extends ResourceImpl implements BaseBuffer
   @Override
   public final BaseBufferImpl setStartPositionEnd(final long start, final long position,
       final long end) {
-    assertInvariants(start, position, end, capacity);
+    checkInvariants(start, position, end, capacity);
     this.start = start;
     this.end = end;
     pos = position;
@@ -129,22 +130,6 @@ public abstract class BaseBufferImpl extends ResourceImpl implements BaseBuffer
   }
 
   //RESTRICTED
-  //Position checks are only used for Buffers
-  //asserts are used for primitives, not used at runtime
-  final void incrementAndAssertPositionForRead(final long position, final long increment) {
-    assertValid();
-    final long newPos = position + increment;
-    assertInvariants(start, newPos, end, capacity);
-    pos = newPos;
-  }
-
-  final void incrementAndAssertPositionForWrite(final long position, final long increment) {
-    assertValid();
-    assert !isReadOnly() : "BufferImpl is read-only.";
-    final long newPos = position + increment;
-    assertInvariants(start, newPos, end, capacity);
-    pos = newPos;
-  }
 
   //checks are used for arrays and apply at runtime
   final void incrementAndCheckPositionForRead(final long position, final long increment) {
@@ -168,28 +153,6 @@ public abstract class BaseBufferImpl extends ResourceImpl implements BaseBuffer
     }
   }
 
-  /**
-   * The invariants equation is: {@code 0 <= start <= position <= end <= capacity}.
-   * If this equation is violated and assertions are enabled,
-   * an <i>AssertionError</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 assertInvariants(final long start, final long pos, final long end,
-      final long cap) {
-    assert (start | pos | end | cap | (pos - start) | (end - pos) | (cap - end) ) >= 0L
-        : "Violation of Invariants: "
-        + "start: " + start
-        + " <= pos: " + pos
-        + " <= end: " + end
-        + " <= cap: " + cap
-        + "; (pos - start): " + (pos - start)
-        + ", (end - pos): " + (end - pos)
-        + ", (cap - end): " + (cap - end);
-  }
-
   /**
    * The invariants equation is: {@code 0 <= start <= position <= end <= capacity}.
    * If this equation is violated an <i>IllegalArgumentException</i> will be thrown.
@@ -201,7 +164,7 @@ public abstract class BaseBufferImpl extends ResourceImpl implements BaseBuffer
   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 IllegalArgumentException(
+      throw new BufferPositionInvariantsException(
           "Violation of Invariants: "
               + "start: " + start
               + " <= pos: " + pos
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 36106e8..955d668 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
@@ -27,7 +27,6 @@ import static org.apache.datasketches.memory.internal.UnsafeUtil.ARRAY_CHAR_INDE
 import static org.apache.datasketches.memory.internal.UnsafeUtil.ARRAY_INT_INDEX_SCALE;
 import static org.apache.datasketches.memory.internal.UnsafeUtil.ARRAY_LONG_INDEX_SCALE;
 import static org.apache.datasketches.memory.internal.UnsafeUtil.ARRAY_SHORT_INDEX_SCALE;
-import static org.apache.datasketches.memory.internal.UnsafeUtil.checkBounds;
 import static org.apache.datasketches.memory.internal.UnsafeUtil.unsafe;
 
 import java.nio.ByteBuffer;
@@ -41,19 +40,6 @@ import org.apache.datasketches.memory.ReadOnlyException;
 import org.apache.datasketches.memory.WritableBuffer;
 import org.apache.datasketches.memory.WritableMemory;
 
-/*
- * Developer notes: The heavier methods, such as put/get arrays, duplicate, region, clear, fill,
- * compareTo, etc., use hard checks (check*() and incrementAndCheck*() methods), which execute at
- * runtime and throw exceptions if violated. The cost of the runtime checks are minor compared to
- * the rest of the work these methods are doing.
- *
- * <p>The light weight methods, such as put/get primitives, use asserts (assert*() and
- * incrementAndAssert*() methods), which only execute when asserts are enabled and JIT will remove
- * them entirely from production runtime code. The offset versions of the light weight methods will
- * simplify to a single unsafe call, which is further simplified by JIT to an intrinsic that is
- * often a single CPU instruction.
- */
-
 /**
  * Common base of native-ordered and non-native-ordered {@link WritableBuffer} implementations.
  * Contains methods which are agnostic to the byte order.
@@ -72,7 +58,7 @@ public abstract class BaseWritableBufferImpl extends BaseBufferImpl implements W
    * @param memReqSvr the requested MemoryRequestServer, which may be null.
    * @return this class constructed via the leaf node.
    */
-  public static BaseWritableBufferImpl wrapByteBuffer(
+  public static WritableBuffer wrapByteBuffer(
       final ByteBuffer byteBuf, final boolean localReadOnly, final ByteOrder byteOrder,
       final MemoryRequestServer memReqSvr) {
     final AccessByteBuffer abb = new AccessByteBuffer(byteBuf);
@@ -124,7 +110,7 @@ public abstract class BaseWritableBufferImpl extends BaseBufferImpl implements W
     return wbuf;
   }
 
-  abstract BaseWritableBufferImpl toWritableRegion(
+  abstract WritableBuffer toWritableRegion(
       long offsetBytes, long capcityBytes, boolean readOnly, ByteOrder byteOrder);
 
   //DUPLICATES
@@ -182,19 +168,19 @@ public abstract class BaseWritableBufferImpl extends BaseBufferImpl implements W
     return wmem;
   }
 
-  abstract BaseWritableMemoryImpl toWritableMemory(boolean readOnly, ByteOrder byteOrder);
+  abstract WritableMemory toWritableMemory(boolean readOnly, ByteOrder byteOrder);
 
   //PRIMITIVE getX() and getXArray()
   @Override
   public final boolean getBoolean() {
     final long pos = getPosition();
-    incrementAndAssertPositionForRead(pos, ARRAY_BOOLEAN_INDEX_SCALE);
+    incrementAndCheckPositionForRead(pos, ARRAY_BOOLEAN_INDEX_SCALE);
     return unsafe.getBoolean(getUnsafeObject(), getCumulativeOffset(pos));
   }
 
   @Override
   public final boolean getBoolean(final long offsetBytes) {
-    assertValidAndBoundsForRead(offsetBytes, ARRAY_BOOLEAN_INDEX_SCALE);
+    checkValidAndBounds(offsetBytes, ARRAY_BOOLEAN_INDEX_SCALE);
     return unsafe.getBoolean(getUnsafeObject(), getCumulativeOffset(offsetBytes));
   }
 
@@ -204,7 +190,7 @@ public abstract class BaseWritableBufferImpl extends BaseBufferImpl implements W
     final long pos = getPosition();
     final long copyBytes = lengthBooleans;
     incrementAndCheckPositionForRead(pos, copyBytes);
-    checkBounds(dstOffsetBooleans, lengthBooleans, dstArray.length);
+    ResourceImpl.checkBounds(dstOffsetBooleans, lengthBooleans, dstArray.length);
     CompareAndCopy.copyMemoryCheckingDifferentObject(
             getUnsafeObject(),
             getCumulativeOffset(pos),
@@ -216,13 +202,13 @@ public abstract class BaseWritableBufferImpl extends BaseBufferImpl implements W
   @Override
   public final byte getByte() {
     final long pos = getPosition();
-    incrementAndAssertPositionForRead(pos, ARRAY_BYTE_INDEX_SCALE);
+    incrementAndCheckPositionForRead(pos, ARRAY_BYTE_INDEX_SCALE);
     return unsafe.getByte(getUnsafeObject(), getCumulativeOffset(pos));
   }
 
   @Override
   public final byte getByte(final long offsetBytes) {
-    assertValidAndBoundsForRead(offsetBytes, ARRAY_BYTE_INDEX_SCALE);
+    checkValidAndBounds(offsetBytes, ARRAY_BYTE_INDEX_SCALE);
     return unsafe.getByte(getUnsafeObject(), getCumulativeOffset(offsetBytes));
   }
 
@@ -232,7 +218,7 @@ public abstract class BaseWritableBufferImpl extends BaseBufferImpl implements W
     final long pos = getPosition();
     final long copyBytes = lengthBytes;
     incrementAndCheckPositionForRead(pos, copyBytes);
-    checkBounds(dstOffsetBytes, lengthBytes, dstArray.length);
+    ResourceImpl.checkBounds(dstOffsetBytes, lengthBytes, dstArray.length);
     CompareAndCopy.copyMemoryCheckingDifferentObject(
             getUnsafeObject(),
             getCumulativeOffset(pos),
@@ -244,45 +230,45 @@ public abstract class BaseWritableBufferImpl extends BaseBufferImpl implements W
   //PRIMITIVE getX() Native Endian (used by both endians)
   final char getNativeOrderedChar() {
     final long pos = getPosition();
-    incrementAndAssertPositionForRead(pos, ARRAY_CHAR_INDEX_SCALE);
+    incrementAndCheckPositionForRead(pos, ARRAY_CHAR_INDEX_SCALE);
     return unsafe.getChar(getUnsafeObject(), getCumulativeOffset(pos));
   }
 
   final char getNativeOrderedChar(final long offsetBytes) {
-    assertValidAndBoundsForRead(offsetBytes, ARRAY_CHAR_INDEX_SCALE);
+    checkValidAndBounds(offsetBytes, ARRAY_CHAR_INDEX_SCALE);
     return unsafe.getChar(getUnsafeObject(), getCumulativeOffset(offsetBytes));
   }
 
   final int getNativeOrderedInt() {
     final long pos = getPosition();
-    incrementAndAssertPositionForRead(pos, ARRAY_INT_INDEX_SCALE);
+    incrementAndCheckPositionForRead(pos, ARRAY_INT_INDEX_SCALE);
     return unsafe.getInt(getUnsafeObject(), getCumulativeOffset(pos));
   }
 
   final int getNativeOrderedInt(final long offsetBytes) {
-    assertValidAndBoundsForRead(offsetBytes, ARRAY_INT_INDEX_SCALE);
+    checkValidAndBounds(offsetBytes, ARRAY_INT_INDEX_SCALE);
     return unsafe.getInt(getUnsafeObject(), getCumulativeOffset(offsetBytes));
   }
 
   final long getNativeOrderedLong() {
     final long pos = getPosition();
-    incrementAndAssertPositionForRead(pos, ARRAY_LONG_INDEX_SCALE);
+    incrementAndCheckPositionForRead(pos, ARRAY_LONG_INDEX_SCALE);
     return unsafe.getLong(getUnsafeObject(), getCumulativeOffset(pos));
   }
 
   final long getNativeOrderedLong(final long offsetBytes) {
-    assertValidAndBoundsForRead(offsetBytes, ARRAY_LONG_INDEX_SCALE);
+    checkValidAndBounds(offsetBytes, ARRAY_LONG_INDEX_SCALE);
     return unsafe.getLong(getUnsafeObject(), getCumulativeOffset(offsetBytes));
   }
 
   final short getNativeOrderedShort() {
     final long pos = getPosition();
-    incrementAndAssertPositionForRead(pos, ARRAY_SHORT_INDEX_SCALE);
+    incrementAndCheckPositionForRead(pos, ARRAY_SHORT_INDEX_SCALE);
     return unsafe.getShort(getUnsafeObject(), getCumulativeOffset(pos));
   }
 
   final short getNativeOrderedShort(final long offsetBytes) {
-    assertValidAndBoundsForRead(offsetBytes, ARRAY_SHORT_INDEX_SCALE);
+    checkValidAndBounds(offsetBytes, ARRAY_SHORT_INDEX_SCALE);
     return unsafe.getShort(getUnsafeObject(), getCumulativeOffset(offsetBytes));
   }
 
@@ -303,13 +289,13 @@ public abstract class BaseWritableBufferImpl extends BaseBufferImpl implements W
   @Override
   public final void putBoolean(final boolean value) {
     final long pos = getPosition();
-    incrementAndAssertPositionForWrite(pos, ARRAY_BOOLEAN_INDEX_SCALE);
+    incrementAndCheckPositionForWrite(pos, ARRAY_BOOLEAN_INDEX_SCALE);
     unsafe.putBoolean(getUnsafeObject(), getCumulativeOffset(pos), value);
   }
 
   @Override
   public final void putBoolean(final long offsetBytes, final boolean value) {
-    assertValidAndBoundsForWrite(offsetBytes, ARRAY_BOOLEAN_INDEX_SCALE);
+    checkValidAndBoundsForWrite(offsetBytes, ARRAY_BOOLEAN_INDEX_SCALE);
     unsafe.putBoolean(getUnsafeObject(), getCumulativeOffset(offsetBytes), value);
   }
 
@@ -319,7 +305,7 @@ public abstract class BaseWritableBufferImpl extends BaseBufferImpl implements W
     final long pos = getPosition();
     final long copyBytes = lengthBooleans;
     incrementAndCheckPositionForWrite(pos, copyBytes);
-    checkBounds(srcOffsetBooleans, lengthBooleans, srcArray.length);
+    ResourceImpl.checkBounds(srcOffsetBooleans, lengthBooleans, srcArray.length);
     CompareAndCopy.copyMemoryCheckingDifferentObject(
             srcArray,
             ARRAY_BOOLEAN_BASE_OFFSET + srcOffsetBooleans,
@@ -331,13 +317,13 @@ public abstract class BaseWritableBufferImpl extends BaseBufferImpl implements W
   @Override
   public final void putByte(final byte value) {
     final long pos = getPosition();
-    incrementAndAssertPositionForWrite(pos, ARRAY_BYTE_INDEX_SCALE);
+    incrementAndCheckPositionForWrite(pos, ARRAY_BYTE_INDEX_SCALE);
     unsafe.putByte(getUnsafeObject(), getCumulativeOffset(pos), value);
   }
 
   @Override
   public final void putByte(final long offsetBytes, final byte value) {
-    assertValidAndBoundsForWrite(offsetBytes, ARRAY_BYTE_INDEX_SCALE);
+    checkValidAndBoundsForWrite(offsetBytes, ARRAY_BYTE_INDEX_SCALE);
     unsafe.putByte(getUnsafeObject(), getCumulativeOffset(offsetBytes), value);
   }
 
@@ -347,7 +333,7 @@ public abstract class BaseWritableBufferImpl extends BaseBufferImpl implements W
     final long pos = getPosition();
     final long copyBytes = lengthBytes;
     incrementAndCheckPositionForWrite(pos, copyBytes);
-    checkBounds(srcOffsetBytes, lengthBytes, srcArray.length);
+    ResourceImpl.checkBounds(srcOffsetBytes, lengthBytes, srcArray.length);
     CompareAndCopy.copyMemoryCheckingDifferentObject(
             srcArray,
             ARRAY_BYTE_BASE_OFFSET + srcOffsetBytes,
@@ -359,52 +345,52 @@ public abstract class BaseWritableBufferImpl extends BaseBufferImpl implements W
   //PRIMITIVE putX() Native Endian (used by both endians)
   final void putNativeOrderedChar(final char value) {
     final long pos = getPosition();
-    incrementAndAssertPositionForWrite(pos, ARRAY_CHAR_INDEX_SCALE);
+    incrementAndCheckPositionForWrite(pos, ARRAY_CHAR_INDEX_SCALE);
     unsafe.putChar(getUnsafeObject(), getCumulativeOffset(pos), value);
   }
 
   final void putNativeOrderedChar(final long offsetBytes, final char value) {
-    assertValidAndBoundsForWrite(offsetBytes, ARRAY_CHAR_INDEX_SCALE);
+    checkValidAndBoundsForWrite(offsetBytes, ARRAY_CHAR_INDEX_SCALE);
     unsafe.putChar(getUnsafeObject(), getCumulativeOffset(offsetBytes), value);
   }
 
   final void putNativeOrderedInt(final int value) {
     final long pos = getPosition();
-    incrementAndAssertPositionForWrite(pos, ARRAY_INT_INDEX_SCALE);
+    incrementAndCheckPositionForWrite(pos, ARRAY_INT_INDEX_SCALE);
     unsafe.putInt(getUnsafeObject(), getCumulativeOffset(pos), value);
   }
 
   final void putNativeOrderedInt(final long offsetBytes, final int value) {
-    assertValidAndBoundsForWrite(offsetBytes, ARRAY_INT_INDEX_SCALE);
+    checkValidAndBoundsForWrite(offsetBytes, ARRAY_INT_INDEX_SCALE);
     unsafe.putInt(getUnsafeObject(), getCumulativeOffset(offsetBytes), value);
   }
 
   final void putNativeOrderedLong(final long value) {
     final long pos = getPosition();
-    incrementAndAssertPositionForWrite(pos, ARRAY_LONG_INDEX_SCALE);
+    incrementAndCheckPositionForWrite(pos, ARRAY_LONG_INDEX_SCALE);
     unsafe.putLong(getUnsafeObject(), getCumulativeOffset(pos), value);
   }
 
   final void putNativeOrderedLong(final long offsetBytes, final long value) {
-    assertValidAndBoundsForWrite(offsetBytes, ARRAY_LONG_INDEX_SCALE);
+    checkValidAndBoundsForWrite(offsetBytes, ARRAY_LONG_INDEX_SCALE);
     unsafe.putLong(getUnsafeObject(), getCumulativeOffset(offsetBytes), value);
   }
 
   final void putNativeOrderedShort(final short value) {
     final long pos = getPosition();
-    incrementAndAssertPositionForWrite(pos, ARRAY_SHORT_INDEX_SCALE);
+    incrementAndCheckPositionForWrite(pos, ARRAY_SHORT_INDEX_SCALE);
     unsafe.putShort(getUnsafeObject(), getCumulativeOffset(pos), value);
   }
 
   final void putNativeOrderedShort(final long offsetBytes, final short value) {
-    assertValidAndBoundsForWrite(offsetBytes, ARRAY_SHORT_INDEX_SCALE);
+    checkValidAndBoundsForWrite(offsetBytes, ARRAY_SHORT_INDEX_SCALE);
     unsafe.putShort(getUnsafeObject(), getCumulativeOffset(offsetBytes), value);
   }
 
   //OTHER
   @Override
   public final Object getArray() {
-    assertValid();
+    checkValid();
     return getUnsafeObject();
   }
 
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BaseWritableMemoryImpl.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BaseWritableMemoryImpl.java
index eea9ede..e2aee82 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BaseWritableMemoryImpl.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BaseWritableMemoryImpl.java
@@ -27,7 +27,6 @@ import static org.apache.datasketches.memory.internal.UnsafeUtil.ARRAY_CHAR_INDE
 import static org.apache.datasketches.memory.internal.UnsafeUtil.ARRAY_INT_INDEX_SCALE;
 import static org.apache.datasketches.memory.internal.UnsafeUtil.ARRAY_LONG_INDEX_SCALE;
 import static org.apache.datasketches.memory.internal.UnsafeUtil.ARRAY_SHORT_INDEX_SCALE;
-import static org.apache.datasketches.memory.internal.UnsafeUtil.checkBounds;
 import static org.apache.datasketches.memory.internal.UnsafeUtil.unsafe;
 import static org.apache.datasketches.memory.internal.Util.negativeCheck;
 
@@ -44,22 +43,8 @@ import org.apache.datasketches.memory.MemoryRequestServer;
 import org.apache.datasketches.memory.ReadOnlyException;
 import org.apache.datasketches.memory.Utf8CodingException;
 import org.apache.datasketches.memory.WritableBuffer;
-import org.apache.datasketches.memory.WritableHandle;
-import org.apache.datasketches.memory.WritableMapHandle;
 import org.apache.datasketches.memory.WritableMemory;
 
-/*
- * Developer notes: The heavier methods, such as put/get arrays, duplicate, region, clear, fill,
- * compareTo, etc., use hard checks (checkValid*() and checkBounds()), which execute at runtime and
- * throw exceptions if violated. The cost of the runtime checks are minor compared to the rest of
- * the work these methods are doing.
- *
- * <p>The light weight methods, such as put/get primitives, use asserts (assertValid*()), which only
- * execute when asserts are enabled and JIT will remove them entirely from production runtime code.
- * The light weight methods will simplify to a single unsafe call, which is further simplified by
- * JIT to an intrinsic that is often a single CPU instruction.
- */
-
 /**
  * Common base of native-ordered and non-native-ordered {@link WritableMemory} implementations.
  * Contains methods which are agnostic to the byte order.
@@ -87,7 +72,7 @@ public abstract class BaseWritableMemoryImpl extends ResourceImpl implements Wri
    * @param memReqSvr the requested MemoryRequestServer, which may be null.
    * @return this class constructed via the leaf node.
    */
-  public static BaseWritableMemoryImpl wrapHeapArray(final Object arr, final long offsetBytes, final long lengthBytes,
+  public static WritableMemory wrapHeapArray(final Object arr, final long offsetBytes, final long lengthBytes,
       final boolean localReadOnly, final ByteOrder byteOrder, final MemoryRequestServer memReqSvr) {
     final long cumOffsetBytes = UnsafeUtil.getArrayBaseOffset(arr.getClass()) + offsetBytes;
     final int typeId = (localReadOnly ? READONLY : 0);
@@ -104,7 +89,7 @@ public abstract class BaseWritableMemoryImpl extends ResourceImpl implements Wri
    * @param memReqSvr the requested MemoryRequestServer, which may be null.
    * @return this class constructed via the leaf node.
    */
-  public static BaseWritableMemoryImpl wrapByteBuffer(
+  public static WritableMemory wrapByteBuffer(
       final ByteBuffer byteBuf, final boolean localReadOnly, final ByteOrder byteOrder,
       final MemoryRequestServer memReqSvr) {
     final AccessByteBuffer abb = new AccessByteBuffer(byteBuf);
@@ -128,7 +113,7 @@ public abstract class BaseWritableMemoryImpl extends ResourceImpl implements Wri
    * @param byteOrder the requested byte-order
    * @return this class constructed via the leaf node.
    */
-  public static WritableMapHandle wrapMap(final File file, final long fileOffsetBytes,
+  public static WritableMemory wrapMap(final File file, final long fileOffsetBytes,
       final long capacityBytes, final boolean localReadOnly, final ByteOrder byteOrder) {
     final AllocateDirectWritableMap dirWMap =
         new AllocateDirectWritableMap(file, fileOffsetBytes, capacityBytes, localReadOnly);
@@ -136,20 +121,18 @@ public abstract class BaseWritableMemoryImpl extends ResourceImpl implements Wri
     final long cumOffsetBytes = dirWMap.nativeBaseOffset;
     final BaseWritableMemoryImpl wmem = Util.isNativeByteOrder(byteOrder)
         ? new MapWritableMemoryImpl(
-            dirWMap.nativeBaseOffset,
+            dirWMap,
             0L,
             capacityBytes,
             typeId,
-            cumOffsetBytes,
-            dirWMap.getValid())
+            cumOffsetBytes)
         : new MapNonNativeWritableMemoryImpl(
-            dirWMap.nativeBaseOffset,
+            dirWMap,
             0L,
             capacityBytes,
             typeId,
-            cumOffsetBytes,
-            dirWMap.getValid());
-    return new WritableMapHandleImpl(dirWMap, wmem);
+            cumOffsetBytes);
+    return wmem;
   }
 
   /**
@@ -159,7 +142,7 @@ public abstract class BaseWritableMemoryImpl extends ResourceImpl implements Wri
    * @param memReqSvr the requested MemoryRequestServer, which may be null
    * @return this class constructed via the leaf node.
    */
-  public static WritableHandle wrapDirect(final long capacityBytes,
+  public static WritableMemory wrapDirect(final long capacityBytes,
       final ByteOrder byteOrder, final MemoryRequestServer memReqSvr) {
     final AllocateDirect direct = new AllocateDirect(capacityBytes);
     final int typeId = 0; //direct is never read-only on construction
@@ -167,24 +150,20 @@ public abstract class BaseWritableMemoryImpl extends ResourceImpl implements Wri
     final long cumOffsetBytes = nativeBaseOffset;
     final BaseWritableMemoryImpl wmem = Util.isNativeByteOrder(byteOrder)
         ? new DirectWritableMemoryImpl(
-            nativeBaseOffset,
+            direct,
             0L,
             capacityBytes,
             typeId,
             cumOffsetBytes,
-            memReqSvr,
-            direct.getValid())
+            memReqSvr)
         : new DirectNonNativeWritableMemoryImpl(
-            nativeBaseOffset,
+            direct,
             0L,
             capacityBytes,
             typeId,
             cumOffsetBytes,
-            memReqSvr,
-            direct.getValid());
-
-    final WritableHandle handle = new WritableDirectHandleImpl(direct, wmem);
-    return handle;
+            memReqSvr);
+    return wmem;
   }
 
   //REGIONS
@@ -212,7 +191,7 @@ public abstract class BaseWritableMemoryImpl extends ResourceImpl implements Wri
     return toWritableRegion(regionOffsetBytes, capacityBytes, finalReadOnly, byteOrder);
   }
 
-  abstract BaseWritableMemoryImpl toWritableRegion(
+  abstract WritableMemory toWritableRegion(
       long regionOffsetBytes, long capacityBytes, boolean finalReadOnly, ByteOrder byteOrder);
 
   //AS BUFFER
@@ -238,12 +217,12 @@ public abstract class BaseWritableMemoryImpl extends ResourceImpl implements Wri
     return wbuf;
   }
 
-  abstract BaseWritableBufferImpl toWritableBuffer(boolean finalReadOnly, ByteOrder byteOrder);
+  abstract WritableBuffer toWritableBuffer(boolean finalReadOnly, ByteOrder byteOrder);
 
   //PRIMITIVE getX() and getXArray()
   @Override
   public final boolean getBoolean(final long offsetBytes) {
-    assertValidAndBoundsForRead(offsetBytes, ARRAY_BOOLEAN_INDEX_SCALE);
+    checkValidAndBounds(offsetBytes, ARRAY_BOOLEAN_INDEX_SCALE);
     return unsafe.getBoolean(getUnsafeObject(), getCumulativeOffset(offsetBytes));
   }
 
@@ -252,7 +231,7 @@ public abstract class BaseWritableMemoryImpl extends ResourceImpl implements Wri
       final int dstOffsetBooleans, final int lengthBooleans) {
     final long copyBytes = lengthBooleans;
     checkValidAndBounds(offsetBytes, copyBytes);
-    checkBounds(dstOffsetBooleans, lengthBooleans, dstArray.length);
+    ResourceImpl.checkBounds(dstOffsetBooleans, lengthBooleans, dstArray.length);
     CompareAndCopy.copyMemoryCheckingDifferentObject(
         getUnsafeObject(),
         getCumulativeOffset(offsetBytes),
@@ -263,7 +242,7 @@ public abstract class BaseWritableMemoryImpl extends ResourceImpl implements Wri
 
   @Override
   public final byte getByte(final long offsetBytes) {
-    assertValidAndBoundsForRead(offsetBytes, ARRAY_BYTE_INDEX_SCALE);
+    checkValidAndBounds(offsetBytes, ARRAY_BYTE_INDEX_SCALE);
     return unsafe.getByte(getUnsafeObject(), getCumulativeOffset(offsetBytes));
   }
 
@@ -272,7 +251,7 @@ public abstract class BaseWritableMemoryImpl extends ResourceImpl implements Wri
       final int dstOffsetBytes, final int lengthBytes) {
     final long copyBytes = lengthBytes;
     checkValidAndBounds(offsetBytes, copyBytes);
-    checkBounds(dstOffsetBytes, lengthBytes, dstArray.length);
+    ResourceImpl.checkBounds(dstOffsetBytes, lengthBytes, dstArray.length);
     CompareAndCopy.copyMemoryCheckingDifferentObject(
         getUnsafeObject(),
         getCumulativeOffset(offsetBytes),
@@ -303,22 +282,22 @@ public abstract class BaseWritableMemoryImpl extends ResourceImpl implements Wri
 
   //PRIMITIVE getX() Native Endian (used by both endians)
   final char getNativeOrderedChar(final long offsetBytes) {
-    assertValidAndBoundsForRead(offsetBytes, ARRAY_CHAR_INDEX_SCALE);
+    checkValidAndBounds(offsetBytes, ARRAY_CHAR_INDEX_SCALE);
     return unsafe.getChar(getUnsafeObject(), getCumulativeOffset(offsetBytes));
   }
 
   final int getNativeOrderedInt(final long offsetBytes) {
-    assertValidAndBoundsForRead(offsetBytes, ARRAY_INT_INDEX_SCALE);
+    checkValidAndBounds(offsetBytes, ARRAY_INT_INDEX_SCALE);
     return unsafe.getInt(getUnsafeObject(), getCumulativeOffset(offsetBytes));
   }
 
   final long getNativeOrderedLong(final long offsetBytes) {
-    assertValidAndBoundsForRead(offsetBytes, ARRAY_LONG_INDEX_SCALE);
+    checkValidAndBounds(offsetBytes, ARRAY_LONG_INDEX_SCALE);
     return unsafe.getLong(getUnsafeObject(), getCumulativeOffset(offsetBytes));
   }
 
   final short getNativeOrderedShort(final long offsetBytes) {
-    assertValidAndBoundsForRead(offsetBytes, ARRAY_SHORT_INDEX_SCALE);
+    checkValidAndBounds(offsetBytes, ARRAY_SHORT_INDEX_SCALE);
     return unsafe.getShort(getUnsafeObject(), getCumulativeOffset(offsetBytes));
   }
 
@@ -355,7 +334,7 @@ public abstract class BaseWritableMemoryImpl extends ResourceImpl implements Wri
   //PRIMITIVE putX() and putXArray() implementations
   @Override
   public final void putBoolean(final long offsetBytes, final boolean value) {
-    assertValidAndBoundsForWrite(offsetBytes, ARRAY_BOOLEAN_INDEX_SCALE);
+    checkValidAndBoundsForWrite(offsetBytes, ARRAY_BOOLEAN_INDEX_SCALE);
     unsafe.putBoolean(getUnsafeObject(), getCumulativeOffset(offsetBytes), value);
   }
 
@@ -364,7 +343,7 @@ public abstract class BaseWritableMemoryImpl extends ResourceImpl implements Wri
       final int srcOffsetBooleans, final int lengthBooleans) {
     final long copyBytes = lengthBooleans;
     checkValidAndBoundsForWrite(offsetBytes, copyBytes);
-    checkBounds(srcOffsetBooleans, lengthBooleans, srcArray.length);
+    ResourceImpl.checkBounds(srcOffsetBooleans, lengthBooleans, srcArray.length);
     CompareAndCopy.copyMemoryCheckingDifferentObject(
         srcArray,
         ARRAY_BOOLEAN_BASE_OFFSET + srcOffsetBooleans,
@@ -376,7 +355,7 @@ public abstract class BaseWritableMemoryImpl extends ResourceImpl implements Wri
 
   @Override
   public final void putByte(final long offsetBytes, final byte value) {
-    assertValidAndBoundsForWrite(offsetBytes, ARRAY_BYTE_INDEX_SCALE);
+    checkValidAndBoundsForWrite(offsetBytes, ARRAY_BYTE_INDEX_SCALE);
     unsafe.putByte(getUnsafeObject(), getCumulativeOffset(offsetBytes), value);
   }
 
@@ -385,7 +364,7 @@ public abstract class BaseWritableMemoryImpl extends ResourceImpl implements Wri
       final int srcOffsetBytes, final int lengthBytes) {
     final long copyBytes = lengthBytes;
     checkValidAndBoundsForWrite(offsetBytes, copyBytes);
-    checkBounds(srcOffsetBytes, lengthBytes, srcArray.length);
+    ResourceImpl.checkBounds(srcOffsetBytes, lengthBytes, srcArray.length);
     CompareAndCopy.copyMemoryCheckingDifferentObject(
         srcArray,
         ARRAY_BYTE_BASE_OFFSET + srcOffsetBytes,
@@ -404,29 +383,29 @@ public abstract class BaseWritableMemoryImpl extends ResourceImpl implements Wri
 
   //PRIMITIVE putX() Native Endian (used by both endians)
   final void putNativeOrderedChar(final long offsetBytes, final char value) {
-    assertValidAndBoundsForWrite(offsetBytes, ARRAY_CHAR_INDEX_SCALE);
+    checkValidAndBoundsForWrite(offsetBytes, ARRAY_CHAR_INDEX_SCALE);
     unsafe.putChar(getUnsafeObject(), getCumulativeOffset(offsetBytes), value);
   }
 
   final void putNativeOrderedInt(final long offsetBytes, final int value) {
-    assertValidAndBoundsForWrite(offsetBytes, ARRAY_INT_INDEX_SCALE);
+    checkValidAndBoundsForWrite(offsetBytes, ARRAY_INT_INDEX_SCALE);
     unsafe.putInt(getUnsafeObject(), getCumulativeOffset(offsetBytes), value);
   }
 
   final void putNativeOrderedLong(final long offsetBytes, final long value) {
-    assertValidAndBoundsForWrite(offsetBytes, ARRAY_LONG_INDEX_SCALE);
+    checkValidAndBoundsForWrite(offsetBytes, ARRAY_LONG_INDEX_SCALE);
     unsafe.putLong(getUnsafeObject(), getCumulativeOffset(offsetBytes), value);
   }
 
   final void putNativeOrderedShort(final long offsetBytes, final short value) {
-    assertValidAndBoundsForWrite(offsetBytes, ARRAY_SHORT_INDEX_SCALE);
+    checkValidAndBoundsForWrite(offsetBytes, ARRAY_SHORT_INDEX_SCALE);
     unsafe.putShort(getUnsafeObject(), getCumulativeOffset(offsetBytes), value);
   }
 
   //OTHER WRITE METHODS
   @Override
   public final Object getArray() {
-    assertValid();
+    checkValid();
     return getUnsafeObject();
   }
 
@@ -448,7 +427,7 @@ public abstract class BaseWritableMemoryImpl extends ResourceImpl implements Wri
 
   @Override
   public final void clearBits(final long offsetBytes, final byte bitMask) {
-    assertValidAndBoundsForWrite(offsetBytes, ARRAY_BYTE_INDEX_SCALE);
+    checkValidAndBoundsForWrite(offsetBytes, ARRAY_BYTE_INDEX_SCALE);
     final long cumBaseOff = getCumulativeOffset(offsetBytes);
     int value = unsafe.getByte(getUnsafeObject(), cumBaseOff) & 0XFF;
     value &= ~bitMask;
@@ -473,7 +452,7 @@ public abstract class BaseWritableMemoryImpl extends ResourceImpl implements Wri
 
   @Override
   public final void setBits(final long offsetBytes, final byte bitMask) {
-    assertValidAndBoundsForWrite(offsetBytes, ARRAY_BYTE_INDEX_SCALE);
+    checkValidAndBoundsForWrite(offsetBytes, ARRAY_BYTE_INDEX_SCALE);
     final long myOffset = getCumulativeOffset(offsetBytes);
     final byte value = unsafe.getByte(getUnsafeObject(), myOffset);
     unsafe.putByte(getUnsafeObject(), myOffset, (byte)(value | bitMask));
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 aa8b2e2..2bb02fa 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
@@ -25,7 +25,6 @@ import static org.apache.datasketches.memory.internal.UnsafeUtil.FLOAT_SHIFT;
 import static org.apache.datasketches.memory.internal.UnsafeUtil.INT_SHIFT;
 import static org.apache.datasketches.memory.internal.UnsafeUtil.LONG_SHIFT;
 import static org.apache.datasketches.memory.internal.UnsafeUtil.SHORT_SHIFT;
-import static org.apache.datasketches.memory.internal.UnsafeUtil.checkBounds;
 import static org.apache.datasketches.memory.internal.UnsafeUtil.unsafe;
 import static org.apache.datasketches.memory.internal.Util.UNSAFE_COPY_THRESHOLD_BYTES;
 
@@ -41,9 +40,9 @@ final class CompareAndCopy {
       final ResourceImpl state1, final long offsetBytes1, final long lengthBytes1,
       final ResourceImpl state2, final long offsetBytes2, final long lengthBytes2) {
     state1.checkValid();
-    checkBounds(offsetBytes1, lengthBytes1, state1.getCapacity());
+    ResourceImpl.checkBounds(offsetBytes1, lengthBytes1, state1.getCapacity());
     state2.checkValid();
-    checkBounds(offsetBytes2, lengthBytes2, state2.getCapacity());
+    ResourceImpl.checkBounds(offsetBytes2, lengthBytes2, state2.getCapacity());
     final long cumOff1 = state1.getCumulativeOffset(offsetBytes1);
     final long cumOff2 = state2.getCumulativeOffset(offsetBytes2);
     final Object arr1 = state1.getUnsafeObject();
@@ -73,9 +72,9 @@ final class CompareAndCopy {
       final ResourceImpl state1, final long offsetBytes1,
       final ResourceImpl state2, final long offsetBytes2, long lengthBytes) {
     state1.checkValid();
-    checkBounds(offsetBytes1, lengthBytes, state1.getCapacity());
+    ResourceImpl.checkBounds(offsetBytes1, lengthBytes, state1.getCapacity());
     state2.checkValid();
-    checkBounds(offsetBytes2, lengthBytes, state2.getCapacity());
+    ResourceImpl.checkBounds(offsetBytes2, lengthBytes, state2.getCapacity());
     long cumOff1 = state1.getCumulativeOffset(offsetBytes1);
     long cumOff2 = state2.getCumulativeOffset(offsetBytes2);
     final Object arr1 = state1.getUnsafeObject(); //could be null
@@ -115,9 +114,9 @@ final class CompareAndCopy {
   static void copy(final ResourceImpl srcState, final long srcOffsetBytes,
       final ResourceImpl dstState, final long dstOffsetBytes, final long lengthBytes) {
     srcState.checkValid();
-    checkBounds(srcOffsetBytes, lengthBytes, srcState.getCapacity());
+    ResourceImpl.checkBounds(srcOffsetBytes, lengthBytes, srcState.getCapacity());
     dstState.checkValid();
-    checkBounds(dstOffsetBytes, lengthBytes, dstState.getCapacity());
+    ResourceImpl.checkBounds(dstOffsetBytes, lengthBytes, dstState.getCapacity());
     final long srcAdd = srcState.getCumulativeOffset(srcOffsetBytes);
     final long dstAdd = dstState.getCumulativeOffset(dstOffsetBytes);
     copyMemory(srcState.getUnsafeObject(), srcAdd, dstState.getUnsafeObject(), dstAdd,
@@ -201,7 +200,7 @@ final class CompareAndCopy {
   static void getNonNativeChars(final Object unsafeObj, long cumOffsetBytes,
       long copyBytes, final char[] dstArray, int dstOffsetChars,
       int lengthChars) {
-    checkBounds(dstOffsetChars, lengthChars, dstArray.length);
+    ResourceImpl.checkBounds(dstOffsetChars, lengthChars, dstArray.length);
     while (copyBytes > UNSAFE_COPY_THRESHOLD_BYTES) {
       final long chunkBytes = Math.min(copyBytes, UNSAFE_COPY_THRESHOLD_BYTES);
       final int chunkChars = (int) (chunkBytes >> CHAR_SHIFT);
@@ -228,7 +227,7 @@ final class CompareAndCopy {
   static void getNonNativeDoubles(final Object unsafeObj, long cumOffsetBytes,
       long copyBytes, final double[] dstArray, int dstOffsetDoubles,
       int lengthDoubles) {
-    checkBounds(dstOffsetDoubles, lengthDoubles, dstArray.length);
+    ResourceImpl.checkBounds(dstOffsetDoubles, lengthDoubles, dstArray.length);
     while (copyBytes > UNSAFE_COPY_THRESHOLD_BYTES) {
       final long chunkBytes = Math.min(copyBytes, UNSAFE_COPY_THRESHOLD_BYTES);
       final int chunkDoubles = (int) (chunkBytes >> DOUBLE_SHIFT);
@@ -257,7 +256,7 @@ final class CompareAndCopy {
   static void getNonNativeFloats(final Object unsafeObj, long cumOffsetBytes,
       long copyBytes, final float[] dstArray, int dstOffsetFloats,
       int lengthFloats) {
-    checkBounds(dstOffsetFloats, lengthFloats, dstArray.length);
+    ResourceImpl.checkBounds(dstOffsetFloats, lengthFloats, dstArray.length);
     while (copyBytes > UNSAFE_COPY_THRESHOLD_BYTES) {
       final long chunkBytes = Math.min(copyBytes, UNSAFE_COPY_THRESHOLD_BYTES);
       final int chunkFloats = (int) (chunkBytes >> FLOAT_SHIFT);
@@ -284,7 +283,7 @@ final class CompareAndCopy {
   static void getNonNativeInts(final Object unsafeObj, long cumOffsetBytes,
       long copyBytes, final int[] dstArray, int dstOffsetInts,
       int lengthInts) {
-    checkBounds(dstOffsetInts, lengthInts, dstArray.length);
+    ResourceImpl.checkBounds(dstOffsetInts, lengthInts, dstArray.length);
     while (copyBytes > UNSAFE_COPY_THRESHOLD_BYTES) {
       final long chunkBytes = Math.min(copyBytes, UNSAFE_COPY_THRESHOLD_BYTES);
       final int chunkInts = (int) (chunkBytes >> INT_SHIFT);
@@ -311,7 +310,7 @@ final class CompareAndCopy {
   static void getNonNativeLongs(final Object unsafeObj, long cumOffsetBytes,
       long copyBytes, final long[] dstArray, int dstOffsetLongs,
       int lengthLongs) {
-    checkBounds(dstOffsetLongs, lengthLongs, dstArray.length);
+    ResourceImpl.checkBounds(dstOffsetLongs, lengthLongs, dstArray.length);
     while (copyBytes > UNSAFE_COPY_THRESHOLD_BYTES) {
       final long chunkBytes = Math.min(copyBytes, UNSAFE_COPY_THRESHOLD_BYTES);
       final int chunkLongs = (int) (chunkBytes >> LONG_SHIFT);
@@ -338,7 +337,7 @@ final class CompareAndCopy {
   static void getNonNativeShorts(final Object unsafeObj, long cumOffsetBytes,
       long copyBytes, final short[] dstArray, int dstOffsetShorts,
       int lengthShorts) {
-    checkBounds(dstOffsetShorts, lengthShorts, dstArray.length);
+    ResourceImpl.checkBounds(dstOffsetShorts, lengthShorts, dstArray.length);
     while (copyBytes > UNSAFE_COPY_THRESHOLD_BYTES) {
       final long chunkBytes = Math.min(copyBytes, UNSAFE_COPY_THRESHOLD_BYTES);
       final int chunkShorts = (int) (chunkBytes >> SHORT_SHIFT);
@@ -364,7 +363,7 @@ final class CompareAndCopy {
 
   static void putNonNativeChars(final char[] srcArray, int srcOffsetChars, int lengthChars,
       long copyBytes, final Object unsafeObj, long cumOffsetBytes) {
-    checkBounds(srcOffsetChars, lengthChars, srcArray.length);
+    ResourceImpl.checkBounds(srcOffsetChars, lengthChars, srcArray.length);
     while (copyBytes > UNSAFE_COPY_THRESHOLD_BYTES) {
       final long chunkBytes = Math.min(copyBytes, UNSAFE_COPY_THRESHOLD_BYTES);
       final int chunkChars = (int) (chunkBytes >> CHAR_SHIFT);
@@ -390,7 +389,7 @@ final class CompareAndCopy {
 
   static void putNonNativeDoubles(final double[] srcArray, int srcOffsetDoubles,
       int lengthDoubles, long copyBytes, final Object unsafeObj, long cumOffsetBytes) {
-    checkBounds(srcOffsetDoubles, lengthDoubles, srcArray.length);
+    ResourceImpl.checkBounds(srcOffsetDoubles, lengthDoubles, srcArray.length);
     while (copyBytes > UNSAFE_COPY_THRESHOLD_BYTES) {
       final long chunkBytes = Math.min(copyBytes, UNSAFE_COPY_THRESHOLD_BYTES);
       final int chunkDoubles = (int) (chunkBytes >> DOUBLE_SHIFT);
@@ -418,7 +417,7 @@ final class CompareAndCopy {
 
   static void putNonNativeFloats(final float[] srcArray, int srcOffsetFloats,
       int lengthFloats, long copyBytes, final Object unsafeObj, long cumOffsetBytes) {
-    checkBounds(srcOffsetFloats, lengthFloats, srcArray.length);
+    ResourceImpl.checkBounds(srcOffsetFloats, lengthFloats, srcArray.length);
     while (copyBytes > UNSAFE_COPY_THRESHOLD_BYTES) {
       final long chunkBytes = Math.min(copyBytes, UNSAFE_COPY_THRESHOLD_BYTES);
       final int chunkFloats = (int) (chunkBytes >> FLOAT_SHIFT);
@@ -444,7 +443,7 @@ final class CompareAndCopy {
 
   static void putNonNativeInts(final int[] srcArray, int srcOffsetInts, int lengthInts,
       long copyBytes, final Object unsafeObj, long cumOffsetBytes) {
-    checkBounds(srcOffsetInts, lengthInts, srcArray.length);
+    ResourceImpl.checkBounds(srcOffsetInts, lengthInts, srcArray.length);
     while (copyBytes > UNSAFE_COPY_THRESHOLD_BYTES) {
       final long chunkBytes = Math.min(copyBytes, UNSAFE_COPY_THRESHOLD_BYTES);
       final int chunkInts = (int) (chunkBytes >> INT_SHIFT);
@@ -470,7 +469,7 @@ final class CompareAndCopy {
 
   static void putNonNativeLongs(final long[] srcArray, int srcOffsetLongs, int lengthLongs,
       long copyBytes, final Object unsafeObj, long cumOffsetBytes) {
-    checkBounds(srcOffsetLongs, lengthLongs, srcArray.length);
+    ResourceImpl.checkBounds(srcOffsetLongs, lengthLongs, srcArray.length);
     while (copyBytes > UNSAFE_COPY_THRESHOLD_BYTES) {
       final long chunkBytes = Math.min(copyBytes, UNSAFE_COPY_THRESHOLD_BYTES);
       final int chunkLongs = (int) (chunkBytes >> LONG_SHIFT);
@@ -496,7 +495,7 @@ final class CompareAndCopy {
 
   static void putNonNativeShorts(final short[] srcArray, int srcOffsetShorts,
       int lengthShorts, long copyBytes, final Object unsafeObj, long cumOffsetBytes) {
-    checkBounds(srcOffsetShorts, lengthShorts, srcArray.length);
+    ResourceImpl.checkBounds(srcOffsetShorts, lengthShorts, srcArray.length);
     while (copyBytes > UNSAFE_COPY_THRESHOLD_BYTES) {
       final long chunkBytes = Math.min(copyBytes, UNSAFE_COPY_THRESHOLD_BYTES);
       final int chunkShorts = (int) (chunkBytes >> SHORT_SHIFT);
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 4394355..c98916c 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
@@ -31,30 +31,27 @@ import org.apache.datasketches.memory.WritableBuffer;
  * @author Lee Rhodes
  */
 final class DirectNonNativeWritableBufferImpl extends NonNativeWritableBufferImpl {
-  private final long nativeBaseOffset;
+  private final AllocateDirect direct;
   private final long offsetBytes;
   private final long capacityBytes;
   private final int typeId;
   private long cumOffsetBytes;
   private final MemoryRequestServer memReqSvr;
-  private final StepBoolean valid; //a reference only
 
   DirectNonNativeWritableBufferImpl(
-      final long nativeBaseOffset,
+      final AllocateDirect direct,
       final long offsetBytes,
       final long capacityBytes,
       final int typeId,
       final long cumOffsetBytes,
-      final MemoryRequestServer memReqSvr,
-      final StepBoolean valid) {
+      final MemoryRequestServer memReqSvr) {
     super(capacityBytes);
-    this.nativeBaseOffset = nativeBaseOffset;
+    this.direct = direct;
     this.offsetBytes = offsetBytes;
     this.capacityBytes = capacityBytes;
     this.typeId = removeNnBuf(typeId) | DIRECT | BUFFER | NONNATIVE; //initially cannot be ReadOnly
     this.cumOffsetBytes = cumOffsetBytes;
     this.memReqSvr = memReqSvr;
-    this.valid = valid;
   }
 
   @Override
@@ -69,11 +66,11 @@ final class DirectNonNativeWritableBufferImpl extends NonNativeWritableBufferImp
     if (Util.isNativeByteOrder(byteOrder)) {
       typeIdOut |= NATIVE;
       return new DirectWritableBufferImpl(
-          nativeBaseOffset, newOffsetBytes, capacityBytes, typeIdOut, newCumOffsetBytes, memReqSvr, valid);
+          direct, newOffsetBytes, capacityBytes, typeIdOut, newCumOffsetBytes, memReqSvr);
     } else {
       typeIdOut |= NONNATIVE;
       return new DirectNonNativeWritableBufferImpl(
-          nativeBaseOffset, newOffsetBytes, capacityBytes, typeIdOut, newCumOffsetBytes, memReqSvr, valid);
+          direct, newOffsetBytes, capacityBytes, typeIdOut, newCumOffsetBytes, memReqSvr);
     }
   }
 
@@ -84,11 +81,11 @@ final class DirectNonNativeWritableBufferImpl extends NonNativeWritableBufferImp
     if (byteOrder == ByteOrder.nativeOrder()) {
       typeIdOut |= NATIVE;
       return new DirectWritableMemoryImpl(
-          nativeBaseOffset, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, memReqSvr, valid);
+          direct, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, memReqSvr);
     } else {
       typeIdOut |= NONNATIVE;
       return new DirectNonNativeWritableMemoryImpl(
-          nativeBaseOffset, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, memReqSvr, valid);
+          direct, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, memReqSvr);
     }
   }
 
@@ -99,56 +96,63 @@ final class DirectNonNativeWritableBufferImpl extends NonNativeWritableBufferImp
     if (byteOrder == ByteOrder.nativeOrder()) {
       typeIdOut |= NATIVE;
       return new DirectWritableBufferImpl(
-          nativeBaseOffset, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, memReqSvr, valid);
+          direct, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, memReqSvr);
     } else {
       typeIdOut |= NONNATIVE;
       return new DirectNonNativeWritableBufferImpl(
-          nativeBaseOffset, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, memReqSvr, valid);
+          direct, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, memReqSvr);
     }
   }
 
   @Override
   public boolean isValid() {
-    return valid.get();
+    return direct.getValid().get();
   }
 
   @Override
   public long getCapacity() {
-    assertValid();
+    checkValid();
     return capacityBytes;
   }
 
+  @Override
+  public void close() {
+    direct.close();
+  }
+
   @Override
   public long getCumulativeOffset() {
-    assertValid();
+    checkValid();
     return cumOffsetBytes;
   }
 
   @Override
   public MemoryRequestServer getMemoryRequestServer() {
+    checkValid();
     return memReqSvr;
   }
 
   @Override
   public long getNativeBaseOffset() {
-    return nativeBaseOffset;
+    checkValid();
+    return direct.getNativeBaseOffset();
   }
 
   @Override
   public long getTotalOffset() {
-    assertValid();
+    checkValid();
     return offsetBytes;
   }
 
   @Override
   int getTypeId() {
-    assertValid();
+    checkValid();
     return typeId;
   }
 
   @Override
   Object getUnsafeObject() {
-    assertValid();
+    checkValid();
     return null;
   }
 
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 9d26441..7293386 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
@@ -31,30 +31,27 @@ import org.apache.datasketches.memory.WritableMemory;
  * @author Lee Rhodes
  */
 final class DirectNonNativeWritableMemoryImpl extends NonNativeWritableMemoryImpl {
-  private final long nativeBaseOffset;
+  private final AllocateDirect direct;
   private final long offsetBytes;
   private final long capacityBytes;
   private final int typeId;
   private long cumOffsetBytes;
   private final MemoryRequestServer memReqSvr;
-  private final StepBoolean valid; //a reference only
 
   DirectNonNativeWritableMemoryImpl(
-      final long nativeBaseOffset,
+      final AllocateDirect direct,
       final long offsetBytes,
       final long capacityBytes,
       final int typeId,
       final long cumOffsetBytes,
-      final MemoryRequestServer memReqSvr,
-      final StepBoolean valid) {
+      final MemoryRequestServer memReqSvr) {
     super();
-    this.nativeBaseOffset = nativeBaseOffset;
+    this.direct = direct;
     this.offsetBytes = offsetBytes;
     this.capacityBytes = capacityBytes;
     this.typeId = removeNnBuf(typeId) | DIRECT | MEMORY | NONNATIVE; //initially cannot be ReadOnly
     this.cumOffsetBytes = cumOffsetBytes;
     this.memReqSvr = memReqSvr;
-    this.valid = valid;
   }
 
   @Override
@@ -70,11 +67,11 @@ final class DirectNonNativeWritableMemoryImpl extends NonNativeWritableMemoryImp
     if (Util.isNativeByteOrder(byteOrder)) {
       typeIdOut |= NATIVE;
       return new DirectWritableMemoryImpl(
-          nativeBaseOffset, newOffsetBytes, capacityBytes, typeIdOut, newCumOffsetBytes, memReqSvr, valid);
+          direct, newOffsetBytes, capacityBytes, typeIdOut, newCumOffsetBytes, memReqSvr);
     } else {
       typeIdOut |= NONNATIVE;
       return new DirectNonNativeWritableMemoryImpl(
-          nativeBaseOffset, newOffsetBytes, capacityBytes, typeIdOut, newCumOffsetBytes, memReqSvr, valid);
+          direct, newOffsetBytes, capacityBytes, typeIdOut, newCumOffsetBytes, memReqSvr);
     }
   }
 
@@ -85,56 +82,64 @@ final class DirectNonNativeWritableMemoryImpl extends NonNativeWritableMemoryImp
     if (byteOrder == ByteOrder.nativeOrder()) {
       typeIdOut |= NATIVE;
       return new DirectWritableBufferImpl(
-          nativeBaseOffset, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, memReqSvr, valid);
+          direct, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, memReqSvr);
     } else {
       typeIdOut |= NONNATIVE;
       return new DirectNonNativeWritableBufferImpl(
-          nativeBaseOffset, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, memReqSvr, valid);
+          direct, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, memReqSvr);
     }
   }
 
   @Override
   public boolean isValid() {
-    return valid.get();
+    return direct.getValid().get();
   }
 
   @Override
   public long getCapacity() {
-    assertValid();
+    checkValid();
     return capacityBytes;
   }
 
+  @Override
+  public void close() {
+    direct.close();
+  }
+
   @Override
   public long getCumulativeOffset() {
-    assertValid();
+    checkValid();
     return cumOffsetBytes;
   }
 
   @Override
   public MemoryRequestServer getMemoryRequestServer() {
+    checkValid();
     return memReqSvr;
   }
 
   @Override
   public long getNativeBaseOffset() {
-    return nativeBaseOffset;
+    checkValid();
+    checkValid();
+    return direct.getNativeBaseOffset();
   }
 
   @Override
   public long getTotalOffset() {
-    assertValid();
+    checkValid();
     return offsetBytes;
   }
 
   @Override
   int getTypeId() {
-    assertValid();
+    checkValid();
     return typeId;
   }
 
   @Override
   Object getUnsafeObject() {
-    assertValid();
+    checkValid();
     return null;
   }
 
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 f338c54..c268024 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
@@ -31,30 +31,27 @@ import org.apache.datasketches.memory.WritableBuffer;
  * @author Lee Rhodes
  */
 final class DirectWritableBufferImpl extends NativeWritableBufferImpl {
-  private final long nativeBaseOffset;
+  private final AllocateDirect direct;
   private final long offsetBytes;
   private final long capacityBytes;
   private final int typeId;
   private long cumOffsetBytes;
   private final MemoryRequestServer memReqSvr;
-  private final StepBoolean valid; //a reference only
 
   DirectWritableBufferImpl(
-      final long nativeBaseOffset,
+      final AllocateDirect direct,
       final long offsetBytes,
       final long capacityBytes,
       final int typeId,
       final long cumOffsetBytes,
-      final MemoryRequestServer memReqSvr,
-      final StepBoolean valid) {
+      final MemoryRequestServer memReqSvr) {
     super(capacityBytes);
-    this.nativeBaseOffset = nativeBaseOffset;
+    this.direct = direct;
     this.offsetBytes = offsetBytes;
     this.capacityBytes = capacityBytes;
     this.typeId = removeNnBuf(typeId) | DIRECT | BUFFER | NATIVE; //initially cannot be ReadOnly
     this.cumOffsetBytes = cumOffsetBytes;
     this.memReqSvr = memReqSvr;
-    this.valid = valid;
   }
 
   @Override
@@ -70,11 +67,11 @@ final class DirectWritableBufferImpl extends NativeWritableBufferImpl {
     if (Util.isNativeByteOrder(byteOrder)) {
       typeIdOut |= NATIVE;
       return new DirectWritableBufferImpl(
-          nativeBaseOffset, newOffsetBytes, capacityBytes, typeIdOut, newCumOffsetBytes, memReqSvr, valid);
+          direct, newOffsetBytes, capacityBytes, typeIdOut, newCumOffsetBytes, memReqSvr);
     } else {
       typeIdOut |= NONNATIVE;
       return new DirectNonNativeWritableBufferImpl(
-          nativeBaseOffset, newOffsetBytes, capacityBytes, typeIdOut, newCumOffsetBytes, memReqSvr, valid);
+          direct, newOffsetBytes, capacityBytes, typeIdOut, newCumOffsetBytes, memReqSvr);
     }
   }
 
@@ -85,11 +82,11 @@ final class DirectWritableBufferImpl extends NativeWritableBufferImpl {
     if (byteOrder == ByteOrder.nativeOrder()) {
       typeIdOut |= NATIVE;
       return new DirectWritableMemoryImpl(
-          nativeBaseOffset, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, memReqSvr, valid);
+          direct, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, memReqSvr);
     } else {
       typeIdOut |= NONNATIVE;
       return new DirectNonNativeWritableMemoryImpl(
-          nativeBaseOffset, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, memReqSvr, valid);
+          direct, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, memReqSvr);
     }
   }
 
@@ -100,56 +97,63 @@ final class DirectWritableBufferImpl extends NativeWritableBufferImpl {
     if (byteOrder == ByteOrder.nativeOrder()) {
       typeIdOut |= NATIVE;
       return new DirectWritableBufferImpl(
-          nativeBaseOffset, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, memReqSvr, valid);
+          direct, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, memReqSvr);
     } else {
       typeIdOut |= NONNATIVE;
       return new DirectNonNativeWritableBufferImpl(
-          nativeBaseOffset, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, memReqSvr, valid);
+          direct, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, memReqSvr);
     }
   }
 
   @Override
   public boolean isValid() {
-    return valid.get();
+    return direct.getValid().get();
   }
 
   @Override
   public long getCapacity() {
-    assertValid();
+    checkValid();
     return capacityBytes;
   }
 
+  @Override
+  public void close() {
+    direct.close();
+  }
+
   @Override
   public long getCumulativeOffset() {
-    assertValid();
+    checkValid();
     return cumOffsetBytes;
   }
 
   @Override
   public MemoryRequestServer getMemoryRequestServer() {
+    checkValid();
     return memReqSvr;
   }
 
   @Override
   public long getNativeBaseOffset() {
-    return nativeBaseOffset;
+    checkValid();
+    return direct.getNativeBaseOffset();
   }
 
   @Override
   public long getTotalOffset() {
-    assertValid();
+    checkValid();
     return offsetBytes;
   }
 
   @Override
   int getTypeId() {
-    assertValid();
+    checkValid();
     return typeId;
   }
 
   @Override
   Object getUnsafeObject() {
-    assertValid();
+    checkValid();
     return null;
   }
 
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 f4162a7..1dbd041 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
@@ -31,30 +31,27 @@ import org.apache.datasketches.memory.WritableMemory;
  * @author Lee Rhodes
  */
 final class DirectWritableMemoryImpl extends NativeWritableMemoryImpl {
-  private final long nativeBaseOffset;
+  private final AllocateDirect direct;
   private final long offsetBytes;
   private final long capacityBytes;
   private final int typeId;
   private long cumOffsetBytes;
   private final MemoryRequestServer memReqSvr;
-  private final StepBoolean valid; //a reference only
 
   DirectWritableMemoryImpl(
-      final long nativeBaseOffset,
+      final AllocateDirect direct,
       final long offsetBytes,
       final long capacityBytes,
       final int typeId,
       final long cumOffsetBytes,
-      final MemoryRequestServer memReqSvr,
-      final StepBoolean valid) {
+      final MemoryRequestServer memReqSvr) {
     super();
-    this.nativeBaseOffset = nativeBaseOffset;
+    this.direct = direct;
     this.offsetBytes = offsetBytes;
     this.capacityBytes = capacityBytes;
     this.typeId = removeNnBuf(typeId) | DIRECT | MEMORY | NATIVE; //initially cannot be ReadOnly
     this.cumOffsetBytes = cumOffsetBytes;
     this.memReqSvr = memReqSvr;
-    this.valid = valid;
   }
 
   @Override
@@ -70,11 +67,11 @@ final class DirectWritableMemoryImpl extends NativeWritableMemoryImpl {
     if (Util.isNativeByteOrder(byteOrder)) {
       typeIdOut |= NATIVE;
       return new DirectWritableMemoryImpl(
-          nativeBaseOffset, newOffsetBytes, capacityBytes, typeIdOut, newCumOffsetBytes, memReqSvr, valid);
+          direct, newOffsetBytes, capacityBytes, typeIdOut, newCumOffsetBytes, memReqSvr);
     } else {
       typeIdOut |= NONNATIVE;
       return new DirectNonNativeWritableMemoryImpl(
-          nativeBaseOffset, newOffsetBytes, capacityBytes, typeIdOut, newCumOffsetBytes, memReqSvr, valid);
+          direct, newOffsetBytes, capacityBytes, typeIdOut, newCumOffsetBytes, memReqSvr);
     }
   }
 
@@ -85,56 +82,63 @@ final class DirectWritableMemoryImpl extends NativeWritableMemoryImpl {
     if (byteOrder == ByteOrder.nativeOrder()) {
       typeIdOut |= NATIVE;
       return new DirectWritableBufferImpl(
-          nativeBaseOffset, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, memReqSvr, valid);
+          direct, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, memReqSvr);
     } else {
       typeIdOut |= NONNATIVE;
       return new DirectNonNativeWritableBufferImpl(
-          nativeBaseOffset, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, memReqSvr, valid);
+          direct, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, memReqSvr);
     }
   }
 
   @Override
   public boolean isValid() {
-    return valid.get();
+    return direct.getValid().get();
   }
 
   @Override
   public long getCapacity() {
-    assertValid();
+    checkValid();
     return capacityBytes;
   }
 
+  @Override
+  public void close() {
+    direct.close();
+  }
+
   @Override
   public long getCumulativeOffset() {
-    assertValid();
+    checkValid();
     return cumOffsetBytes;
   }
 
   @Override
   public MemoryRequestServer getMemoryRequestServer() {
+    checkValid();
     return memReqSvr;
   }
 
   @Override
   public long getNativeBaseOffset() {
-    return nativeBaseOffset;
+    checkValid();
+    return direct.getNativeBaseOffset();
   }
 
   @Override
   public long getTotalOffset() {
-    assertValid();
+    checkValid();
     return offsetBytes;
   }
 
   @Override
   int getTypeId() {
-    assertValid();
+    checkValid();
     return typeId;
   }
 
   @Override
   Object getUnsafeObject() {
-    assertValid();
+    checkValid();
     return null;
   }
 
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 3b1386c..8143b2e 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
@@ -107,41 +107,43 @@ final class HeapNonNativeWritableBufferImpl extends NonNativeWritableBufferImpl
 
   @Override
   public long getCapacity() {
-    assertValid();
+    checkValid();
     return capacityBytes;
   }
 
   @Override
   public long getCumulativeOffset() {
-    assertValid();
+    checkValid();
     return cumOffsetBytes;
   }
 
   @Override
   public MemoryRequestServer getMemoryRequestServer() {
+    checkValid();
     return memReqSvr;
   }
 
   @Override
   public long getNativeBaseOffset() {
+    checkValid();
     return 0;
   }
 
   @Override
   public long getTotalOffset() {
-    assertValid();
+    checkValid();
     return offsetBytes;
   }
 
   @Override
   int getTypeId() {
-    assertValid();
+    checkValid();
     return typeId;
   }
 
   @Override
   Object getUnsafeObject() {
-    assertValid();
+    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 e528cef..a72fc10 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
@@ -92,41 +92,43 @@ final class HeapNonNativeWritableMemoryImpl extends NonNativeWritableMemoryImpl
 
   @Override
   public long getCapacity() {
-    assertValid();
+    checkValid();
     return capacityBytes;
   }
 
   @Override
   public long getCumulativeOffset() {
-    assertValid();
+    checkValid();
     return cumOffsetBytes;
   }
 
   @Override
   public MemoryRequestServer getMemoryRequestServer() {
+    checkValid();
     return memReqSvr;
   }
 
   @Override
   public long getNativeBaseOffset() {
+    checkValid();
     return 0;
   }
 
   @Override
   public long getTotalOffset() {
-    assertValid();
+    checkValid();
     return offsetBytes;
   }
 
   @Override
   int getTypeId() {
-    assertValid();
+    checkValid();
     return typeId;
   }
 
   @Override
   Object getUnsafeObject() {
-    assertValid();
+    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 33d8170..1e270ac 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
@@ -107,41 +107,43 @@ final class HeapWritableBufferImpl extends NativeWritableBufferImpl {
 
   @Override
   public long getCapacity() {
-    assertValid();
+    checkValid();
     return capacityBytes;
   }
 
   @Override
   public long getCumulativeOffset() {
-    assertValid();
+    checkValid();
     return cumOffsetBytes;
   }
 
   @Override
   public MemoryRequestServer getMemoryRequestServer() {
+    checkValid();
     return memReqSvr;
   }
 
   @Override
   public long getNativeBaseOffset() {
+    checkValid();
     return 0;
   }
 
   @Override
   public long getTotalOffset() {
-    assertValid();
+    checkValid();
     return offsetBytes;
   }
 
   @Override
   int getTypeId() {
-    assertValid();
+    checkValid();
     return typeId;
   }
 
   @Override
   Object getUnsafeObject() {
-    assertValid();
+    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 d70ac99..82f3a7a 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
@@ -92,41 +92,43 @@ final class HeapWritableMemoryImpl extends NativeWritableMemoryImpl {
 
   @Override
   public long getCapacity() {
-    assertValid();
+    checkValid();
     return capacityBytes;
   }
 
   @Override
   public long getCumulativeOffset() {
-    assertValid();
+    checkValid();
     return cumOffsetBytes;
   }
 
   @Override
   public MemoryRequestServer getMemoryRequestServer() {
+    checkValid();
     return memReqSvr;
   }
 
   @Override
   public long getNativeBaseOffset() {
+    checkValid();
     return 0;
   }
 
   @Override
   public long getTotalOffset() {
-    assertValid();
+    checkValid();
     return offsetBytes;
   }
 
   @Override
   int getTypeId() {
-    assertValid();
+    checkValid();
     return typeId;
   }
 
   @Override
   Object getUnsafeObject() {
-    assertValid();
+    checkValid();
     return unsafeObj;
   }
 
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapHandleImpl.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapHandleImpl.java
deleted file mode 100644
index 6dbf61c..0000000
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapHandleImpl.java
+++ /dev/null
@@ -1,57 +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 org.apache.datasketches.memory.MapHandle;
-import org.apache.datasketches.memory.Memory;
-
-class MapHandleImpl implements MapHandle {
-
-  final AllocateDirectWritableMap dirMap;
-  BaseWritableMemoryImpl wMem;
-
-  MapHandleImpl(final AllocateDirectWritableMap dirMap, final BaseWritableMemoryImpl wMem) {
-    this.dirMap = dirMap;
-    this.wMem = wMem;
-  }
-
-  @Override
-  public Memory get() {
-    return wMem;
-  }
-
-  @Override
-  public void close() {
-    if (dirMap.doClose("MapHandle")) {
-      wMem = null;
-    }
-  }
-
-  @Override
-  public void load() {
-    dirMap.load();
-  }
-
-  @Override
-  public boolean isLoaded() {
-    return dirMap.isLoaded();
-  }
-
-}
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 00eb965..01afc10 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
@@ -31,27 +31,24 @@ import org.apache.datasketches.memory.WritableBuffer;
  * @author Lee Rhodes
  */
 final class MapNonNativeWritableBufferImpl extends NonNativeWritableBufferImpl {
-  private final long nativeBaseOffset;
+  private final AllocateDirectWritableMap dirWMap;
   private final long offsetBytes;
   private final long capacityBytes;
   private final int typeId;
   private long cumOffsetBytes;
-  private final StepBoolean valid; //a reference only
 
   MapNonNativeWritableBufferImpl(
-      final long nativeBaseOffset,
+      final AllocateDirectWritableMap dirWMap,
       final long offsetBytes,
       final long capacityBytes,
       final int typeId,
-      final long cumOffsetBytes,
-      final StepBoolean valid) {
+      final long cumOffsetBytes) {
     super(capacityBytes);
-    this.nativeBaseOffset = nativeBaseOffset;
+    this.dirWMap = dirWMap;
     this.offsetBytes = offsetBytes;
     this.capacityBytes = capacityBytes;
     this.typeId = removeNnBuf(typeId) | MAP | BUFFER | NONNATIVE;
     this.cumOffsetBytes = cumOffsetBytes;
-    this.valid = valid;
   }
 
   @Override
@@ -67,11 +64,11 @@ final class MapNonNativeWritableBufferImpl extends NonNativeWritableBufferImpl {
     if (Util.isNativeByteOrder(byteOrder)) {
       typeIdOut |= NATIVE;
       return new MapWritableBufferImpl(
-          nativeBaseOffset, newOffsetBytes, capacityBytes, typeIdOut, newCumOffsetBytes, valid);
+          dirWMap, newOffsetBytes, capacityBytes, typeIdOut, newCumOffsetBytes);
     } else {
       typeIdOut |= NONNATIVE;
       return new MapNonNativeWritableBufferImpl(
-          nativeBaseOffset, newOffsetBytes, capacityBytes, typeIdOut, newCumOffsetBytes, valid);
+          dirWMap, newOffsetBytes, capacityBytes, typeIdOut, newCumOffsetBytes);
     }
   }
 
@@ -82,11 +79,11 @@ final class MapNonNativeWritableBufferImpl extends NonNativeWritableBufferImpl {
     if (byteOrder == ByteOrder.nativeOrder()) {
       typeIdOut |= NATIVE;
       return new MapWritableMemoryImpl(
-          nativeBaseOffset, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, valid);
+          dirWMap, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes);
     } else {
       typeIdOut |= NONNATIVE;
       return new MapNonNativeWritableMemoryImpl(
-          nativeBaseOffset, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, valid);
+          dirWMap, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes);
     }
   }
 
@@ -97,57 +94,79 @@ final class MapNonNativeWritableBufferImpl extends NonNativeWritableBufferImpl {
     if (byteOrder == ByteOrder.nativeOrder()) {
       typeIdOut |= NATIVE;
       return new MapWritableBufferImpl(
-          nativeBaseOffset, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, valid);
+          dirWMap, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes);
     } else {
       typeIdOut |= NONNATIVE;
       return new MapNonNativeWritableBufferImpl(
-          nativeBaseOffset, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, valid);
+          dirWMap, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes);
     }
   }
 
   @Override
   public boolean isValid() {
-    return valid.get();
+    return dirWMap.getValid().get();
   }
 
   @Override
   public long getCapacity() {
-    assertValid();
+    checkValid();
     return capacityBytes;
   }
 
   @Override
   public long getCumulativeOffset() {
-    assertValid();
+    checkValid();
     return cumOffsetBytes;
   }
 
   @Override
   public MemoryRequestServer getMemoryRequestServer() {
+    checkValid();
     return null;
   }
 
   @Override
   public long getNativeBaseOffset() {
-    return nativeBaseOffset;
+    checkValid();
+    return dirWMap.nativeBaseOffset;
   }
 
   @Override
   public long getTotalOffset() {
-    assertValid();
+    checkValid();
     return offsetBytes;
   }
 
   @Override
   int getTypeId() {
-    assertValid();
+    checkValid();
     return typeId;
   }
 
   @Override
   Object getUnsafeObject() {
-    assertValid();
+    checkValid();
     return null;
   }
 
+  @Override
+  public void close() {
+    dirWMap.close();
+  }
+
+  @Override
+  public void force() {
+    dirWMap.force();
+  }
+
+  @Override
+  public boolean isLoaded() {
+    return dirWMap.isLoaded();
+  }
+
+  @Override
+  public void load() {
+    dirWMap.load();
+  }
+
 }
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 9a4ace9..ea5e3a6 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
@@ -31,27 +31,24 @@ import org.apache.datasketches.memory.WritableMemory;
  * @author Lee Rhodes
  */
 final class MapNonNativeWritableMemoryImpl extends NonNativeWritableMemoryImpl {
-  private final long nativeBaseOffset;
+  private final AllocateDirectWritableMap dirWMap;
   private final long offsetBytes;
   private final long capacityBytes;
   private final int typeId;
   private long cumOffsetBytes;
-  private final StepBoolean valid; //a reference only
 
   MapNonNativeWritableMemoryImpl(
-      final long nativeBaseOffset,
+      final AllocateDirectWritableMap dirWMap,
       final long offsetBytes,
       final long capacityBytes,
       final int typeId,
-      final long cumOffsetBytes,
-      final StepBoolean valid) {
+      final long cumOffsetBytes) {
     super();
-    this.nativeBaseOffset = nativeBaseOffset;
+    this.dirWMap = dirWMap;
     this.offsetBytes = offsetBytes;
     this.capacityBytes = capacityBytes;
     this.typeId = removeNnBuf(typeId) | MAP | MEMORY | NONNATIVE;
     this.cumOffsetBytes = cumOffsetBytes;
-    this.valid = valid;
   }
 
   @Override
@@ -67,11 +64,11 @@ final class MapNonNativeWritableMemoryImpl extends NonNativeWritableMemoryImpl {
     if (Util.isNativeByteOrder(byteOrder)) {
       typeIdOut |= NATIVE;
       return new MapWritableMemoryImpl(
-          nativeBaseOffset, newOffsetBytes, capacityBytes, typeIdOut, newCumOffsetBytes, valid);
+          dirWMap, newOffsetBytes, capacityBytes, typeIdOut, newCumOffsetBytes);
     } else {
       typeIdOut |= NONNATIVE;
       return new MapNonNativeWritableMemoryImpl(
-          nativeBaseOffset, newOffsetBytes, capacityBytes, typeIdOut, newCumOffsetBytes, valid);
+          dirWMap, newOffsetBytes, capacityBytes, typeIdOut, newCumOffsetBytes);
     }
   }
 
@@ -82,57 +79,79 @@ final class MapNonNativeWritableMemoryImpl extends NonNativeWritableMemoryImpl {
     if (byteOrder == ByteOrder.nativeOrder()) {
       typeIdOut |= NATIVE;
       return new MapWritableBufferImpl(
-          nativeBaseOffset, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, valid);
+          dirWMap, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes);
     } else {
       typeIdOut |= NONNATIVE;
       return new MapNonNativeWritableBufferImpl(
-          nativeBaseOffset, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, valid);
+          dirWMap, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes);
     }
   }
 
   @Override
   public boolean isValid() {
-    return valid.get();
+    return dirWMap.getValid().get();
   }
 
   @Override
   public long getCapacity() {
-    assertValid();
+    checkValid();
     return capacityBytes;
   }
 
   @Override
   public long getCumulativeOffset() {
-    assertValid();
+    checkValid();
     return cumOffsetBytes;
   }
 
   @Override
   public MemoryRequestServer getMemoryRequestServer() {
+    checkValid();
     return null;
   }
 
   @Override
   public long getNativeBaseOffset() {
-    return nativeBaseOffset;
+    checkValid();
+    return dirWMap.nativeBaseOffset;
   }
 
   @Override
   public long getTotalOffset() {
-    assertValid();
+    checkValid();
     return offsetBytes;
   }
 
   @Override
   int getTypeId() {
-    assertValid();
+    checkValid();
     return typeId;
   }
 
   @Override
   Object getUnsafeObject() {
-    assertValid();
+    checkValid();
     return null;
   }
 
+  @Override
+  public void close() {
+    dirWMap.close();
+  }
+
+  @Override
+  public void force() {
+    dirWMap.force();
+  }
+
+  @Override
+  public boolean isLoaded() {
+    return dirWMap.isLoaded();
+  }
+
+  @Override
+  public void load() {
+    dirWMap.load();
+  }
+
 }
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 51ba0db..0470cab 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
@@ -31,27 +31,24 @@ import org.apache.datasketches.memory.WritableBuffer;
  * @author Lee Rhodes
  */
 final class MapWritableBufferImpl extends NativeWritableBufferImpl {
-  private final long nativeBaseOffset;
+  private final AllocateDirectWritableMap dirWMap;
   private final long offsetBytes;
   private final long capacityBytes;
   private final int typeId;
   private long cumOffsetBytes;
-  private final StepBoolean valid; //a reference only
 
   MapWritableBufferImpl(
-      final long nativeBaseOffset,
+      final AllocateDirectWritableMap dirWMap,
       final long offsetBytes,
       final long capacityBytes,
       final int typeId,
-      final long cumOffsetBytes,
-      final StepBoolean valid) {
+      final long cumOffsetBytes) {
     super(capacityBytes);
-    this.nativeBaseOffset = nativeBaseOffset;
+    this.dirWMap = dirWMap;
     this.offsetBytes = offsetBytes;
     this.capacityBytes = capacityBytes;
     this.typeId = removeNnBuf(typeId) | MAP | BUFFER | NATIVE;
     this.cumOffsetBytes = cumOffsetBytes;
-    this.valid = valid;
   }
 
   @Override
@@ -67,11 +64,11 @@ final class MapWritableBufferImpl extends NativeWritableBufferImpl {
     if (Util.isNativeByteOrder(byteOrder)) {
       typeIdOut |= NATIVE;
       return new MapWritableBufferImpl(
-          nativeBaseOffset, newOffsetBytes, capacityBytes, typeIdOut, newCumOffsetBytes, valid);
+          dirWMap, newOffsetBytes, capacityBytes, typeIdOut, newCumOffsetBytes);
     } else {
       typeIdOut |= NONNATIVE;
       return new MapNonNativeWritableBufferImpl(
-          nativeBaseOffset, newOffsetBytes, capacityBytes, typeIdOut, newCumOffsetBytes, valid);
+          dirWMap, newOffsetBytes, capacityBytes, typeIdOut, newCumOffsetBytes);
     }
   }
 
@@ -82,11 +79,11 @@ final class MapWritableBufferImpl extends NativeWritableBufferImpl {
     if (byteOrder == ByteOrder.nativeOrder()) {
       typeIdOut |= NATIVE;
       return new MapWritableMemoryImpl(
-          nativeBaseOffset, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, valid);
+          dirWMap, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes);
     } else {
       typeIdOut |= NONNATIVE;
       return new MapNonNativeWritableMemoryImpl(
-          nativeBaseOffset, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, valid);
+          dirWMap, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes);
     }
   }
 
@@ -97,57 +94,79 @@ final class MapWritableBufferImpl extends NativeWritableBufferImpl {
     if (byteOrder == ByteOrder.nativeOrder()) {
       typeIdOut |= NATIVE;
       return new MapWritableBufferImpl(
-          nativeBaseOffset, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, valid);
+          dirWMap, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes);
     } else {
       typeIdOut |= NONNATIVE;
       return new MapNonNativeWritableBufferImpl(
-          nativeBaseOffset, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, valid);
+          dirWMap, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes);
     }
   }
 
   @Override
   public boolean isValid() {
-    return valid.get();
+    return dirWMap.getValid().get();
   }
 
   @Override
   public long getCapacity() {
-    assertValid();
+    checkValid();
     return capacityBytes;
   }
 
   @Override
   public long getCumulativeOffset() {
-    assertValid();
+    checkValid();
     return cumOffsetBytes;
   }
 
   @Override
   public MemoryRequestServer getMemoryRequestServer() {
+    checkValid();
     return null;
   }
 
   @Override
   public long getNativeBaseOffset() {
-    return nativeBaseOffset;
+    checkValid();
+    return dirWMap.nativeBaseOffset;
   }
 
   @Override
   public long getTotalOffset() {
-    assertValid();
+    checkValid();
     return offsetBytes;
   }
 
   @Override
   int getTypeId() {
-    assertValid();
+    checkValid();
     return typeId;
   }
 
   @Override
   Object getUnsafeObject() {
-    assertValid();
+    checkValid();
     return null;
   }
 
+  @Override
+  public void close() {
+    dirWMap.close();
+  }
+
+  @Override
+  public void force() {
+    dirWMap.force();
+  }
+
+  @Override
+  public boolean isLoaded() {
+    return dirWMap.isLoaded();
+  }
+
+  @Override
+  public void load() {
+    dirWMap.load();
+  }
+
 }
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 2417281..b6b6c2b 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
@@ -31,27 +31,24 @@ import org.apache.datasketches.memory.WritableMemory;
  * @author Lee Rhodes
  */
 final class MapWritableMemoryImpl extends NativeWritableMemoryImpl {
-  private final long nativeBaseOffset;
+  private final AllocateDirectWritableMap dirWMap;
   private final long offsetBytes;
   private final long capacityBytes;
   private final int typeId;
   private long cumOffsetBytes;
-  private final StepBoolean valid; //a reference only
 
   MapWritableMemoryImpl(
-      final long nativeBaseOffset,
+      final AllocateDirectWritableMap dirWMap,
       final long offsetBytes,
       final long capacityBytes,
       final int typeId,
-      final long cumOffsetBytes,
-      final StepBoolean valid) {
+      final long cumOffsetBytes) {
     super();
-    this.nativeBaseOffset = nativeBaseOffset;
+    this.dirWMap = dirWMap;
     this.offsetBytes = offsetBytes;
     this.capacityBytes = capacityBytes;
     this.typeId = removeNnBuf(typeId) | MAP | MEMORY | NATIVE;
     this.cumOffsetBytes = cumOffsetBytes;
-    this.valid = valid;
   }
 
   @Override
@@ -60,7 +57,6 @@ final class MapWritableMemoryImpl extends NativeWritableMemoryImpl {
       final long capacityBytes,
       final boolean readOnly,
       final ByteOrder byteOrder) {
-    //this.regionOffsetBytes = regionOffsetBytes;
     final long newOffsetBytes = offsetBytes + regionOffsetBytes;
     final long newCumOffsetBytes = cumOffsetBytes + regionOffsetBytes;
     int typeIdOut = removeNnBuf(typeId) | MAP | REGION | (readOnly ? READONLY : 0);
@@ -68,11 +64,11 @@ final class MapWritableMemoryImpl extends NativeWritableMemoryImpl {
     if (Util.isNativeByteOrder(byteOrder)) {
       typeIdOut |= NATIVE;
       return new MapWritableMemoryImpl(
-          nativeBaseOffset, newOffsetBytes, capacityBytes, typeIdOut, newCumOffsetBytes, valid);
+          dirWMap, newOffsetBytes, capacityBytes, typeIdOut, newCumOffsetBytes);
     } else {
       typeIdOut |= NONNATIVE;
       return new MapNonNativeWritableMemoryImpl(
-          nativeBaseOffset, newOffsetBytes, capacityBytes, typeIdOut, newCumOffsetBytes, valid);
+          dirWMap, newOffsetBytes, capacityBytes, typeIdOut, newCumOffsetBytes);
     }
   }
 
@@ -83,28 +79,28 @@ final class MapWritableMemoryImpl extends NativeWritableMemoryImpl {
     if (byteOrder == ByteOrder.nativeOrder()) {
       typeIdOut |= NATIVE;
       return new MapWritableBufferImpl(
-          nativeBaseOffset, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, valid);
+          dirWMap, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes);
     } else {
       typeIdOut |= NONNATIVE;
       return new MapNonNativeWritableBufferImpl(
-          nativeBaseOffset, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes, valid);
+          dirWMap, offsetBytes, capacityBytes, typeIdOut, cumOffsetBytes);
     }
   }
 
   @Override
   public boolean isValid() {
-    return valid.get();
+    return dirWMap.getValid().get();
   }
 
   @Override
   public long getCapacity() {
-    assertValid();
+    checkValid();
     return capacityBytes;
   }
 
   @Override
   public long getCumulativeOffset() {
-    assertValid();
+    checkValid();
     return cumOffsetBytes;
   }
 
@@ -115,25 +111,45 @@ final class MapWritableMemoryImpl extends NativeWritableMemoryImpl {
 
   @Override
   public long getNativeBaseOffset() {
-    return nativeBaseOffset;
+    return dirWMap.nativeBaseOffset;
   }
 
   @Override
   public long getTotalOffset() {
-    assertValid();
+    checkValid();
     return offsetBytes;
   }
 
   @Override
   int getTypeId() {
-    assertValid();
+    checkValid();
     return typeId;
   }
 
   @Override
   Object getUnsafeObject() {
-    assertValid();
+    checkValid();
     return null;
   }
 
+  @Override
+  public void close() {
+    dirWMap.close();
+  }
+
+  @Override
+  public void force() {
+    dirWMap.force();
+  }
+
+  @Override
+  public boolean isLoaded() {
+    return dirWMap.isLoaded();
+  }
+
+  @Override
+  public void load() {
+    dirWMap.load();
+  }
+
 }
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/NativeWritableBufferImpl.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/NativeWritableBufferImpl.java
index 3b14993..f092bb3 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/NativeWritableBufferImpl.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/NativeWritableBufferImpl.java
@@ -27,30 +27,10 @@ import static org.apache.datasketches.memory.internal.UnsafeUtil.ARRAY_FLOAT_IND
 import static org.apache.datasketches.memory.internal.UnsafeUtil.ARRAY_INT_BASE_OFFSET;
 import static org.apache.datasketches.memory.internal.UnsafeUtil.ARRAY_LONG_BASE_OFFSET;
 import static org.apache.datasketches.memory.internal.UnsafeUtil.ARRAY_SHORT_BASE_OFFSET;
-import static org.apache.datasketches.memory.internal.UnsafeUtil.CHAR_SHIFT;
-import static org.apache.datasketches.memory.internal.UnsafeUtil.DOUBLE_SHIFT;
-import static org.apache.datasketches.memory.internal.UnsafeUtil.FLOAT_SHIFT;
-import static org.apache.datasketches.memory.internal.UnsafeUtil.INT_SHIFT;
-import static org.apache.datasketches.memory.internal.UnsafeUtil.LONG_SHIFT;
-import static org.apache.datasketches.memory.internal.UnsafeUtil.SHORT_SHIFT;
-import static org.apache.datasketches.memory.internal.UnsafeUtil.checkBounds;
 import static org.apache.datasketches.memory.internal.UnsafeUtil.unsafe;
 
 import org.apache.datasketches.memory.WritableBuffer;
 
-/*
- * Developer notes: The heavier methods, such as put/get arrays, duplicate, region, clear, fill,
- * compareTo, etc., use hard checks (check*() and incrementAndCheck*() methods), which execute at
- * runtime and throw exceptions if violated. The cost of the runtime checks are minor compared to
- * the rest of the work these methods are doing.
- *
- * <p>The light weight methods, such as put/get primitives, use asserts (assert*() and
- * incrementAndAssert*() methods), which only execute when asserts are enabled and JIT will remove
- * them entirely from production runtime code. The offset versions of the light weight methods will
- * simplify to a single unsafe call, which is further simplified by JIT to an intrinsic that is
- * often a single CPU instruction.
- */
-
 /**
  * Implementation of {@link WritableBuffer} for native endian byte order.
  * @author Roman Leventov
@@ -78,7 +58,7 @@ abstract class NativeWritableBufferImpl extends BaseWritableBufferImpl {
     final long pos = getPosition();
     final long copyBytes = ((long) lengthChars) << CHAR_SHIFT;
     incrementAndCheckPositionForRead(pos, copyBytes);
-    checkBounds(dstOffsetChars, lengthChars, dstArray.length);
+    ResourceImpl.checkBounds(dstOffsetChars, lengthChars, dstArray.length);
     CompareAndCopy.copyMemoryCheckingDifferentObject(
             getUnsafeObject(),
             getCumulativeOffset(pos),
@@ -90,13 +70,13 @@ abstract class NativeWritableBufferImpl extends BaseWritableBufferImpl {
   @Override
   public double getDouble() {
     final long pos = getPosition();
-    incrementAndAssertPositionForRead(pos, ARRAY_DOUBLE_INDEX_SCALE);
+    incrementAndCheckPositionForRead(pos, ARRAY_DOUBLE_INDEX_SCALE);
     return unsafe.getDouble(getUnsafeObject(), getCumulativeOffset(pos));
   }
 
   @Override
   public double getDouble(final long offsetBytes) {
-    assertValidAndBoundsForRead(offsetBytes, ARRAY_DOUBLE_INDEX_SCALE);
+    checkValidAndBounds(offsetBytes, ARRAY_DOUBLE_INDEX_SCALE);
     return unsafe.getDouble(getUnsafeObject(), getCumulativeOffset(offsetBytes));
   }
 
@@ -106,7 +86,7 @@ abstract class NativeWritableBufferImpl extends BaseWritableBufferImpl {
     final long pos = getPosition();
     final long copyBytes = ((long) lengthDoubles) << DOUBLE_SHIFT;
     incrementAndCheckPositionForRead(pos, copyBytes);
-    checkBounds(dstOffsetDoubles, lengthDoubles, dstArray.length);
+    ResourceImpl.checkBounds(dstOffsetDoubles, lengthDoubles, dstArray.length);
     CompareAndCopy.copyMemoryCheckingDifferentObject(
             getUnsafeObject(),
             getCumulativeOffset(pos),
@@ -118,13 +98,13 @@ abstract class NativeWritableBufferImpl extends BaseWritableBufferImpl {
   @Override
   public float getFloat() {
     final long pos = getPosition();
-    incrementAndAssertPositionForRead(pos, ARRAY_FLOAT_INDEX_SCALE);
+    incrementAndCheckPositionForRead(pos, ARRAY_FLOAT_INDEX_SCALE);
     return unsafe.getFloat(getUnsafeObject(), getCumulativeOffset(pos));
   }
 
   @Override
   public float getFloat(final long offsetBytes) {
-    assertValidAndBoundsForRead(offsetBytes, ARRAY_FLOAT_INDEX_SCALE);
+    checkValidAndBounds(offsetBytes, ARRAY_FLOAT_INDEX_SCALE);
     return unsafe.getFloat(getUnsafeObject(), getCumulativeOffset(offsetBytes));
   }
 
@@ -134,7 +114,7 @@ abstract class NativeWritableBufferImpl extends BaseWritableBufferImpl {
     final long pos = getPosition();
     final long copyBytes = ((long) lengthFloats) << FLOAT_SHIFT;
     incrementAndCheckPositionForRead(pos, copyBytes);
-    checkBounds(dstOffsetFloats, lengthFloats, dstArray.length);
+    ResourceImpl.checkBounds(dstOffsetFloats, lengthFloats, dstArray.length);
     CompareAndCopy.copyMemoryCheckingDifferentObject(
             getUnsafeObject(),
             getCumulativeOffset(pos),
@@ -158,7 +138,7 @@ abstract class NativeWritableBufferImpl extends BaseWritableBufferImpl {
     final long pos = getPosition();
     final long copyBytes = ((long) lengthInts) << INT_SHIFT;
     incrementAndCheckPositionForRead(pos, copyBytes);
-    checkBounds(dstOffsetInts, lengthInts, dstArray.length);
+    ResourceImpl.checkBounds(dstOffsetInts, lengthInts, dstArray.length);
     CompareAndCopy.copyMemoryCheckingDifferentObject(
             getUnsafeObject(),
             getCumulativeOffset(pos),
@@ -182,7 +162,7 @@ abstract class NativeWritableBufferImpl extends BaseWritableBufferImpl {
     final long pos = getPosition();
     final long copyBytes = ((long) lengthLongs) << LONG_SHIFT;
     incrementAndCheckPositionForRead(pos, copyBytes);
-    checkBounds(dstOffsetLongs, lengthLongs, dstArray.length);
+    ResourceImpl.checkBounds(dstOffsetLongs, lengthLongs, dstArray.length);
     CompareAndCopy.copyMemoryCheckingDifferentObject(
             getUnsafeObject(),
             getCumulativeOffset(pos),
@@ -207,7 +187,7 @@ abstract class NativeWritableBufferImpl extends BaseWritableBufferImpl {
     final long pos = getPosition();
     final long copyBytes = ((long) lengthShorts) << SHORT_SHIFT;
     incrementAndCheckPositionForRead(pos, copyBytes);
-    checkBounds(dstOffsetShorts, lengthShorts, dstArray.length);
+    ResourceImpl.checkBounds(dstOffsetShorts, lengthShorts, dstArray.length);
     CompareAndCopy.copyMemoryCheckingDifferentObject(
             getUnsafeObject(),
             getCumulativeOffset(pos),
@@ -232,7 +212,7 @@ abstract class NativeWritableBufferImpl extends BaseWritableBufferImpl {
     final long pos = getPosition();
     final long copyBytes = ((long) lengthChars) << CHAR_SHIFT;
     incrementAndCheckPositionForWrite(pos, copyBytes);
-    checkBounds(srcOffsetChars, lengthChars, srcArray.length);
+    ResourceImpl.checkBounds(srcOffsetChars, lengthChars, srcArray.length);
     CompareAndCopy.copyMemoryCheckingDifferentObject(
             srcArray,
             ARRAY_CHAR_BASE_OFFSET + (((long) srcOffsetChars) << CHAR_SHIFT),
@@ -244,13 +224,13 @@ abstract class NativeWritableBufferImpl extends BaseWritableBufferImpl {
   @Override
   public void putDouble(final double value) {
     final long pos = getPosition();
-    incrementAndAssertPositionForWrite(pos, ARRAY_DOUBLE_INDEX_SCALE);
+    incrementAndCheckPositionForWrite(pos, ARRAY_DOUBLE_INDEX_SCALE);
     unsafe.putDouble(getUnsafeObject(), getCumulativeOffset(pos), value);
   }
 
   @Override
   public void putDouble(final long offsetBytes, final double value) {
-    assertValidAndBoundsForWrite(offsetBytes, ARRAY_DOUBLE_INDEX_SCALE);
+    checkValidAndBoundsForWrite(offsetBytes, ARRAY_DOUBLE_INDEX_SCALE);
     unsafe.putDouble(getUnsafeObject(), getCumulativeOffset(offsetBytes), value);
   }
 
@@ -260,7 +240,7 @@ abstract class NativeWritableBufferImpl extends BaseWritableBufferImpl {
     final long pos = getPosition();
     final long copyBytes = ((long) lengthDoubles) << DOUBLE_SHIFT;
     incrementAndCheckPositionForWrite(pos, copyBytes);
-    checkBounds(srcOffsetDoubles, lengthDoubles, srcArray.length);
+    ResourceImpl.checkBounds(srcOffsetDoubles, lengthDoubles, srcArray.length);
     CompareAndCopy.copyMemoryCheckingDifferentObject(
             srcArray,
             ARRAY_DOUBLE_BASE_OFFSET + (((long) srcOffsetDoubles) << DOUBLE_SHIFT),
@@ -272,13 +252,13 @@ abstract class NativeWritableBufferImpl extends BaseWritableBufferImpl {
   @Override
   public void putFloat(final float value) {
     final long pos = getPosition();
-    incrementAndAssertPositionForWrite(pos, ARRAY_FLOAT_INDEX_SCALE);
+    incrementAndCheckPositionForWrite(pos, ARRAY_FLOAT_INDEX_SCALE);
     unsafe.putFloat(getUnsafeObject(), getCumulativeOffset(pos), value);
   }
 
   @Override
   public void putFloat(final long offsetBytes, final float value) {
-    assertValidAndBoundsForWrite(offsetBytes, ARRAY_FLOAT_INDEX_SCALE);
+    checkValidAndBoundsForWrite(offsetBytes, ARRAY_FLOAT_INDEX_SCALE);
     unsafe.putFloat(getUnsafeObject(), getCumulativeOffset(offsetBytes), value);
   }
 
@@ -288,7 +268,7 @@ abstract class NativeWritableBufferImpl extends BaseWritableBufferImpl {
     final long pos = getPosition();
     final long copyBytes = ((long) lengthFloats) << FLOAT_SHIFT;
     incrementAndCheckPositionForWrite(pos, copyBytes);
-    checkBounds(srcOffsetFloats, lengthFloats, srcArray.length);
+    ResourceImpl.checkBounds(srcOffsetFloats, lengthFloats, srcArray.length);
     CompareAndCopy.copyMemoryCheckingDifferentObject(
             srcArray,
             ARRAY_FLOAT_BASE_OFFSET + (((long) srcOffsetFloats) << FLOAT_SHIFT),
@@ -312,7 +292,7 @@ abstract class NativeWritableBufferImpl extends BaseWritableBufferImpl {
     final long pos = getPosition();
     final long copyBytes = ((long) lengthInts) << INT_SHIFT;
     incrementAndCheckPositionForWrite(pos, copyBytes);
-    checkBounds(srcOffsetInts, lengthInts, srcArray.length);
+    ResourceImpl.checkBounds(srcOffsetInts, lengthInts, srcArray.length);
     CompareAndCopy.copyMemoryCheckingDifferentObject(
             srcArray,
             ARRAY_INT_BASE_OFFSET + (((long) srcOffsetInts) << INT_SHIFT),
@@ -336,7 +316,7 @@ abstract class NativeWritableBufferImpl extends BaseWritableBufferImpl {
     final long pos = getPosition();
     final long copyBytes = ((long) lengthLongs) << LONG_SHIFT;
     incrementAndCheckPositionForWrite(pos, copyBytes);
-    checkBounds(srcOffsetLongs, lengthLongs, srcArray.length);
+    ResourceImpl.checkBounds(srcOffsetLongs, lengthLongs, srcArray.length);
     CompareAndCopy.copyMemoryCheckingDifferentObject(
             srcArray,
             ARRAY_LONG_BASE_OFFSET + (((long) srcOffsetLongs) << LONG_SHIFT),
@@ -361,7 +341,7 @@ abstract class NativeWritableBufferImpl extends BaseWritableBufferImpl {
     final long pos = getPosition();
     final long copyBytes = ((long) lengthShorts) << SHORT_SHIFT;
     incrementAndCheckPositionForWrite(pos, copyBytes);
-    checkBounds(srcOffsetShorts, lengthShorts, srcArray.length);
+    ResourceImpl.checkBounds(srcOffsetShorts, lengthShorts, srcArray.length);
     CompareAndCopy.copyMemoryCheckingDifferentObject(
             srcArray,
             ARRAY_SHORT_BASE_OFFSET + (((long) srcOffsetShorts) << SHORT_SHIFT),
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/NativeWritableMemoryImpl.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/NativeWritableMemoryImpl.java
index 1a7b375..b53d957 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/NativeWritableMemoryImpl.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/NativeWritableMemoryImpl.java
@@ -28,29 +28,10 @@ import static org.apache.datasketches.memory.internal.UnsafeUtil.ARRAY_INT_BASE_
 import static org.apache.datasketches.memory.internal.UnsafeUtil.ARRAY_LONG_BASE_OFFSET;
 import static org.apache.datasketches.memory.internal.UnsafeUtil.ARRAY_LONG_INDEX_SCALE;
 import static org.apache.datasketches.memory.internal.UnsafeUtil.ARRAY_SHORT_BASE_OFFSET;
-import static org.apache.datasketches.memory.internal.UnsafeUtil.CHAR_SHIFT;
-import static org.apache.datasketches.memory.internal.UnsafeUtil.DOUBLE_SHIFT;
-import static org.apache.datasketches.memory.internal.UnsafeUtil.FLOAT_SHIFT;
-import static org.apache.datasketches.memory.internal.UnsafeUtil.INT_SHIFT;
-import static org.apache.datasketches.memory.internal.UnsafeUtil.LONG_SHIFT;
-import static org.apache.datasketches.memory.internal.UnsafeUtil.SHORT_SHIFT;
-import static org.apache.datasketches.memory.internal.UnsafeUtil.checkBounds;
 import static org.apache.datasketches.memory.internal.UnsafeUtil.unsafe;
 
 import org.apache.datasketches.memory.WritableMemory;
 
-/*
- * Developer notes: The heavier methods, such as put/get arrays, duplicate, region, clear, fill,
- * compareTo, etc., use hard checks (checkValid*() and checkBounds()), which execute at runtime and
- * throw exceptions if violated. The cost of the runtime checks are minor compared to the rest of
- * the work these methods are doing.
- *
- * <p>The light weight methods, such as put/get primitives, use asserts (assertValid*()), which only
- * execute when asserts are enabled and JIT will remove them entirely from production runtime code.
- * The light weight methods will simplify to a single unsafe call, which is further simplified by
- * JIT to an intrinsic that is often a single CPU instruction.
- */
-
 /**
  * Implementation of {@link WritableMemory} for native endian byte order.
  * @author Roman Leventov
@@ -73,7 +54,7 @@ abstract class NativeWritableMemoryImpl extends BaseWritableMemoryImpl {
       final int lengthChars) {
     final long copyBytes = ((long) lengthChars) << CHAR_SHIFT;
     checkValidAndBounds(offsetBytes, copyBytes);
-    checkBounds(dstOffsetChars, lengthChars, dstArray.length);
+    ResourceImpl.checkBounds(dstOffsetChars, lengthChars, dstArray.length);
     CompareAndCopy.copyMemoryCheckingDifferentObject(
         getUnsafeObject(),
         getCumulativeOffset(offsetBytes),
@@ -84,7 +65,7 @@ abstract class NativeWritableMemoryImpl extends BaseWritableMemoryImpl {
 
   @Override
   public double getDouble(final long offsetBytes) {
-    assertValidAndBoundsForRead(offsetBytes, ARRAY_DOUBLE_INDEX_SCALE);
+    checkValidAndBounds(offsetBytes, ARRAY_DOUBLE_INDEX_SCALE);
     return unsafe.getDouble(getUnsafeObject(), getCumulativeOffset(offsetBytes));
   }
 
@@ -93,7 +74,7 @@ abstract class NativeWritableMemoryImpl extends BaseWritableMemoryImpl {
       final int dstOffsetDoubles, final int lengthDoubles) {
     final long copyBytes = ((long) lengthDoubles) << DOUBLE_SHIFT;
     checkValidAndBounds(offsetBytes, copyBytes);
-    checkBounds(dstOffsetDoubles, lengthDoubles, dstArray.length);
+    ResourceImpl.checkBounds(dstOffsetDoubles, lengthDoubles, dstArray.length);
     CompareAndCopy.copyMemoryCheckingDifferentObject(
         getUnsafeObject(),
         getCumulativeOffset(offsetBytes),
@@ -104,7 +85,7 @@ abstract class NativeWritableMemoryImpl extends BaseWritableMemoryImpl {
 
   @Override
   public float getFloat(final long offsetBytes) {
-    assertValidAndBoundsForRead(offsetBytes, ARRAY_FLOAT_INDEX_SCALE);
+    checkValidAndBounds(offsetBytes, ARRAY_FLOAT_INDEX_SCALE);
     return unsafe.getFloat(getUnsafeObject(), getCumulativeOffset(offsetBytes));
   }
 
@@ -113,7 +94,7 @@ abstract class NativeWritableMemoryImpl extends BaseWritableMemoryImpl {
       final int dstOffsetFloats, final int lengthFloats) {
     final long copyBytes = ((long) lengthFloats) << FLOAT_SHIFT;
     checkValidAndBounds(offsetBytes, copyBytes);
-    checkBounds(dstOffsetFloats, lengthFloats, dstArray.length);
+    ResourceImpl.checkBounds(dstOffsetFloats, lengthFloats, dstArray.length);
     CompareAndCopy.copyMemoryCheckingDifferentObject(
         getUnsafeObject(),
         getCumulativeOffset(offsetBytes),
@@ -132,7 +113,7 @@ abstract class NativeWritableMemoryImpl extends BaseWritableMemoryImpl {
       final int lengthInts) {
     final long copyBytes = ((long) lengthInts) << INT_SHIFT;
     checkValidAndBounds(offsetBytes, copyBytes);
-    checkBounds(dstOffsetInts, lengthInts, dstArray.length);
+    ResourceImpl.checkBounds(dstOffsetInts, lengthInts, dstArray.length);
     CompareAndCopy.copyMemoryCheckingDifferentObject(
         getUnsafeObject(),
         getCumulativeOffset(offsetBytes),
@@ -151,7 +132,7 @@ abstract class NativeWritableMemoryImpl extends BaseWritableMemoryImpl {
       final int dstOffsetLongs, final int lengthLongs) {
     final long copyBytes = ((long) lengthLongs) << LONG_SHIFT;
     checkValidAndBounds(offsetBytes, copyBytes);
-    checkBounds(dstOffsetLongs, lengthLongs, dstArray.length);
+    ResourceImpl.checkBounds(dstOffsetLongs, lengthLongs, dstArray.length);
     CompareAndCopy.copyMemoryCheckingDifferentObject(
         getUnsafeObject(),
         getCumulativeOffset(offsetBytes),
@@ -170,7 +151,7 @@ abstract class NativeWritableMemoryImpl extends BaseWritableMemoryImpl {
       final int dstOffsetShorts, final int lengthShorts) {
     final long copyBytes = ((long) lengthShorts) << SHORT_SHIFT;
     checkValidAndBounds(offsetBytes, copyBytes);
-    checkBounds(dstOffsetShorts, lengthShorts, dstArray.length);
+    ResourceImpl.checkBounds(dstOffsetShorts, lengthShorts, dstArray.length);
     CompareAndCopy.copyMemoryCheckingDifferentObject(
         getUnsafeObject(),
         getCumulativeOffset(offsetBytes),
@@ -190,7 +171,7 @@ abstract class NativeWritableMemoryImpl extends BaseWritableMemoryImpl {
       final int srcOffsetChars, final int lengthChars) {
     final long copyBytes = ((long) lengthChars) << CHAR_SHIFT;
     checkValidAndBoundsForWrite(offsetBytes, copyBytes);
-    checkBounds(srcOffsetChars, lengthChars, srcArray.length);
+    ResourceImpl.checkBounds(srcOffsetChars, lengthChars, srcArray.length);
     CompareAndCopy.copyMemoryCheckingDifferentObject(
         srcArray,
         ARRAY_CHAR_BASE_OFFSET + (((long) srcOffsetChars) << CHAR_SHIFT),
@@ -202,7 +183,7 @@ abstract class NativeWritableMemoryImpl extends BaseWritableMemoryImpl {
 
   @Override
   public void putDouble(final long offsetBytes, final double value) {
-    assertValidAndBoundsForWrite(offsetBytes, ARRAY_DOUBLE_INDEX_SCALE);
+    checkValidAndBoundsForWrite(offsetBytes, ARRAY_DOUBLE_INDEX_SCALE);
     unsafe.putDouble(getUnsafeObject(), getCumulativeOffset(offsetBytes), value);
   }
 
@@ -211,7 +192,7 @@ abstract class NativeWritableMemoryImpl extends BaseWritableMemoryImpl {
       final int srcOffsetDoubles, final int lengthDoubles) {
     final long copyBytes = ((long) lengthDoubles) << DOUBLE_SHIFT;
     checkValidAndBoundsForWrite(offsetBytes, copyBytes);
-    checkBounds(srcOffsetDoubles, lengthDoubles, srcArray.length);
+    ResourceImpl.checkBounds(srcOffsetDoubles, lengthDoubles, srcArray.length);
     CompareAndCopy.copyMemoryCheckingDifferentObject(
         srcArray,
         ARRAY_DOUBLE_BASE_OFFSET + (((long) srcOffsetDoubles) << DOUBLE_SHIFT),
@@ -223,7 +204,7 @@ abstract class NativeWritableMemoryImpl extends BaseWritableMemoryImpl {
 
   @Override
   public void putFloat(final long offsetBytes, final float value) {
-    assertValidAndBoundsForWrite(offsetBytes, ARRAY_FLOAT_INDEX_SCALE);
+    checkValidAndBoundsForWrite(offsetBytes, ARRAY_FLOAT_INDEX_SCALE);
     unsafe.putFloat(getUnsafeObject(), getCumulativeOffset(offsetBytes), value);
   }
 
@@ -232,7 +213,7 @@ abstract class NativeWritableMemoryImpl extends BaseWritableMemoryImpl {
       final int srcOffsetFloats, final int lengthFloats) {
     final long copyBytes = ((long) lengthFloats) << FLOAT_SHIFT;
     checkValidAndBoundsForWrite(offsetBytes, copyBytes);
-    checkBounds(srcOffsetFloats, lengthFloats, srcArray.length);
+    ResourceImpl.checkBounds(srcOffsetFloats, lengthFloats, srcArray.length);
     CompareAndCopy.copyMemoryCheckingDifferentObject(
         srcArray,
         ARRAY_FLOAT_BASE_OFFSET + (((long) srcOffsetFloats) << FLOAT_SHIFT),
@@ -252,7 +233,7 @@ abstract class NativeWritableMemoryImpl extends BaseWritableMemoryImpl {
       final int lengthInts) {
     final long copyBytes = ((long) lengthInts) << INT_SHIFT;
     checkValidAndBoundsForWrite(offsetBytes, copyBytes);
-    checkBounds(srcOffsetInts, lengthInts, srcArray.length);
+    ResourceImpl.checkBounds(srcOffsetInts, lengthInts, srcArray.length);
     CompareAndCopy.copyMemoryCheckingDifferentObject(
         srcArray,
         ARRAY_INT_BASE_OFFSET + (((long) srcOffsetInts) << INT_SHIFT),
@@ -272,7 +253,7 @@ abstract class NativeWritableMemoryImpl extends BaseWritableMemoryImpl {
       final int lengthLongs) {
     final long copyBytes = ((long) lengthLongs) << LONG_SHIFT;
     checkValidAndBoundsForWrite(offsetBytes, copyBytes);
-    checkBounds(srcOffsetLongs, lengthLongs, srcArray.length);
+    ResourceImpl.checkBounds(srcOffsetLongs, lengthLongs, srcArray.length);
     CompareAndCopy.copyMemoryCheckingDifferentObject(
         srcArray,
         ARRAY_LONG_BASE_OFFSET + (((long) srcOffsetLongs) << LONG_SHIFT),
@@ -292,7 +273,7 @@ abstract class NativeWritableMemoryImpl extends BaseWritableMemoryImpl {
       final int srcOffsetShorts, final int lengthShorts) {
     final long copyBytes = ((long) lengthShorts) << SHORT_SHIFT;
     checkValidAndBoundsForWrite(offsetBytes, copyBytes);
-    checkBounds(srcOffsetShorts, lengthShorts, srcArray.length);
+    ResourceImpl.checkBounds(srcOffsetShorts, lengthShorts, srcArray.length);
     CompareAndCopy.copyMemoryCheckingDifferentObject(
         srcArray,
         ARRAY_SHORT_BASE_OFFSET + (((long) srcOffsetShorts) << SHORT_SHIFT),
@@ -305,21 +286,21 @@ abstract class NativeWritableMemoryImpl extends BaseWritableMemoryImpl {
   //Atomic Write Methods
   @Override
   public long getAndAddLong(final long offsetBytes, final long delta) { //JDK 8+
-    assertValidAndBoundsForWrite(offsetBytes, ARRAY_LONG_INDEX_SCALE);
+    checkValidAndBoundsForWrite(offsetBytes, ARRAY_LONG_INDEX_SCALE);
     final long addr = getCumulativeOffset(offsetBytes);
     return unsafe.getAndAddLong(getUnsafeObject(), addr, delta);
   }
 
   @Override
   public long getAndSetLong(final long offsetBytes, final long newValue) { //JDK 8+
-    assertValidAndBoundsForWrite(offsetBytes, ARRAY_LONG_INDEX_SCALE);
+    checkValidAndBoundsForWrite(offsetBytes, ARRAY_LONG_INDEX_SCALE);
     final long addr = getCumulativeOffset(offsetBytes);
     return unsafe.getAndSetLong(getUnsafeObject(), addr, newValue);
   }
 
   @Override
   public boolean compareAndSwapLong(final long offsetBytes, final long expect, final long update) {
-    assertValidAndBoundsForWrite(offsetBytes, ARRAY_LONG_INDEX_SCALE);
+    checkValidAndBoundsForWrite(offsetBytes, ARRAY_LONG_INDEX_SCALE);
     return unsafe.compareAndSwapLong(
         getUnsafeObject(), getCumulativeOffset(offsetBytes), expect, update);
   }
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/NonNativeWritableBufferImpl.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/NonNativeWritableBufferImpl.java
index 8df6111..8202ebf 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/NonNativeWritableBufferImpl.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/NonNativeWritableBufferImpl.java
@@ -21,29 +21,10 @@ package org.apache.datasketches.memory.internal;
 
 import static org.apache.datasketches.memory.internal.UnsafeUtil.ARRAY_DOUBLE_INDEX_SCALE;
 import static org.apache.datasketches.memory.internal.UnsafeUtil.ARRAY_FLOAT_INDEX_SCALE;
-import static org.apache.datasketches.memory.internal.UnsafeUtil.CHAR_SHIFT;
-import static org.apache.datasketches.memory.internal.UnsafeUtil.DOUBLE_SHIFT;
-import static org.apache.datasketches.memory.internal.UnsafeUtil.FLOAT_SHIFT;
-import static org.apache.datasketches.memory.internal.UnsafeUtil.INT_SHIFT;
-import static org.apache.datasketches.memory.internal.UnsafeUtil.LONG_SHIFT;
-import static org.apache.datasketches.memory.internal.UnsafeUtil.SHORT_SHIFT;
 import static org.apache.datasketches.memory.internal.UnsafeUtil.unsafe;
 
 import org.apache.datasketches.memory.WritableBuffer;
 
-/*
- * Developer notes: The heavier methods, such as put/get arrays, duplicate, region, clear, fill,
- * compareTo, etc., use hard checks (check*() and incrementAndCheck*() methods), which execute at
- * runtime and throw exceptions if violated. The cost of the runtime checks are minor compared to
- * the rest of the work these methods are doing.
- *
- * <p>The light weight methods, such as put/get primitives, use asserts (assert*() and
- * incrementAndAssert*() methods), which only execute when asserts are enabled and JIT will remove
- * them entirely from production runtime code. The offset versions of the light weight methods will
- * simplify to a single unsafe call, which is further simplified by JIT to an intrinsic that is
- * often a single CPU instruction.
- */
-
 /**
  * Implementation of {@link WritableBuffer} for non-native endian byte order.
  * @author Roman Leventov
@@ -78,14 +59,14 @@ abstract class NonNativeWritableBufferImpl extends BaseWritableBufferImpl {
   @Override
   public double getDouble() {
     final long pos = getPosition();
-    incrementAndAssertPositionForRead(pos, ARRAY_DOUBLE_INDEX_SCALE);
+    incrementAndCheckPositionForRead(pos, ARRAY_DOUBLE_INDEX_SCALE);
     return Double.longBitsToDouble(
         Long.reverseBytes(unsafe.getLong(getUnsafeObject(), getCumulativeOffset(pos))));
   }
 
   @Override
   public double getDouble(final long offsetBytes) {
-    assertValidAndBoundsForRead(offsetBytes, ARRAY_DOUBLE_INDEX_SCALE);
+    checkValidAndBounds(offsetBytes, ARRAY_DOUBLE_INDEX_SCALE);
     return Double.longBitsToDouble(
         Long.reverseBytes(unsafe.getLong(getUnsafeObject(), getCumulativeOffset(offsetBytes))));
   }
@@ -103,14 +84,14 @@ abstract class NonNativeWritableBufferImpl extends BaseWritableBufferImpl {
   @Override
   public float getFloat() {
     final long pos = getPosition();
-    incrementAndAssertPositionForRead(pos, ARRAY_FLOAT_INDEX_SCALE);
+    incrementAndCheckPositionForRead(pos, ARRAY_FLOAT_INDEX_SCALE);
     return Float.intBitsToFloat(
         Integer.reverseBytes(unsafe.getInt(getUnsafeObject(), getCumulativeOffset(pos))));
   }
 
   @Override
   public float getFloat(final long offsetBytes) {
-    assertValidAndBoundsForRead(offsetBytes, ARRAY_FLOAT_INDEX_SCALE);
+    checkValidAndBounds(offsetBytes, ARRAY_FLOAT_INDEX_SCALE);
     return Float.intBitsToFloat(
         Integer.reverseBytes(unsafe.getInt(getUnsafeObject(), getCumulativeOffset(offsetBytes))));
   }
@@ -206,14 +187,14 @@ abstract class NonNativeWritableBufferImpl extends BaseWritableBufferImpl {
   @Override
   public void putDouble(final double value) {
     final long pos = getPosition();
-    incrementAndAssertPositionForWrite(pos, ARRAY_DOUBLE_INDEX_SCALE);
+    incrementAndCheckPositionForWrite(pos, ARRAY_DOUBLE_INDEX_SCALE);
     unsafe.putLong(getUnsafeObject(), getCumulativeOffset(pos),
         Long.reverseBytes(Double.doubleToRawLongBits(value)));
   }
 
   @Override
   public void putDouble(final long offsetBytes, final double value) {
-    assertValidAndBoundsForWrite(offsetBytes, ARRAY_DOUBLE_INDEX_SCALE);
+    checkValidAndBoundsForWrite(offsetBytes, ARRAY_DOUBLE_INDEX_SCALE);
     unsafe.putLong(getUnsafeObject(), getCumulativeOffset(offsetBytes),
         Long.reverseBytes(Double.doubleToRawLongBits(value)));
   }
@@ -231,14 +212,14 @@ abstract class NonNativeWritableBufferImpl extends BaseWritableBufferImpl {
   @Override
   public void putFloat(final float value) {
     final long pos = getPosition();
-    incrementAndAssertPositionForWrite(pos, ARRAY_FLOAT_INDEX_SCALE);
+    incrementAndCheckPositionForWrite(pos, ARRAY_FLOAT_INDEX_SCALE);
     unsafe.putInt(getUnsafeObject(), getCumulativeOffset(pos),
         Integer.reverseBytes(Float.floatToRawIntBits(value)));
   }
 
   @Override
   public void putFloat(final long offsetBytes, final float value) {
-    assertValidAndBoundsForWrite(offsetBytes, ARRAY_FLOAT_INDEX_SCALE);
+    checkValidAndBoundsForWrite(offsetBytes, ARRAY_FLOAT_INDEX_SCALE);
     unsafe.putInt(getUnsafeObject(), getCumulativeOffset(offsetBytes),
         Integer.reverseBytes(Float.floatToRawIntBits(value)));
   }
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/NonNativeWritableMemoryImpl.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/NonNativeWritableMemoryImpl.java
index 6d1e460..ad2133d 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/NonNativeWritableMemoryImpl.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/NonNativeWritableMemoryImpl.java
@@ -22,28 +22,10 @@ package org.apache.datasketches.memory.internal;
 import static org.apache.datasketches.memory.internal.UnsafeUtil.ARRAY_DOUBLE_INDEX_SCALE;
 import static org.apache.datasketches.memory.internal.UnsafeUtil.ARRAY_FLOAT_INDEX_SCALE;
 import static org.apache.datasketches.memory.internal.UnsafeUtil.ARRAY_LONG_INDEX_SCALE;
-import static org.apache.datasketches.memory.internal.UnsafeUtil.CHAR_SHIFT;
-import static org.apache.datasketches.memory.internal.UnsafeUtil.DOUBLE_SHIFT;
-import static org.apache.datasketches.memory.internal.UnsafeUtil.FLOAT_SHIFT;
-import static org.apache.datasketches.memory.internal.UnsafeUtil.INT_SHIFT;
-import static org.apache.datasketches.memory.internal.UnsafeUtil.LONG_SHIFT;
-import static org.apache.datasketches.memory.internal.UnsafeUtil.SHORT_SHIFT;
 import static org.apache.datasketches.memory.internal.UnsafeUtil.unsafe;
 
 import org.apache.datasketches.memory.WritableMemory;
 
-/*
- * Developer notes: The heavier methods, such as put/get arrays, duplicate, region, clear, fill,
- * compareTo, etc., use hard checks (checkValid*() and checkBounds()), which execute at runtime and
- * throw exceptions if violated. The cost of the runtime checks are minor compared to the rest of
- * the work these methods are doing.
- *
- * <p>The light weight methods, such as put/get primitives, use asserts (assertValid*()), which only
- * execute when asserts are enabled and JIT will remove them entirely from production runtime code.
- * The light weight methods will simplify to a single unsafe call, which is further simplified by
- * JIT to an intrinsic that is often a single CPU instruction.
- */
-
 /**
  * Implementation of {@link WritableMemory} for non-native endian byte order.
  * @author Roman Leventov
@@ -72,7 +54,7 @@ abstract class NonNativeWritableMemoryImpl extends BaseWritableMemoryImpl {
 
   @Override
   public double getDouble(final long offsetBytes) {
-    assertValidAndBoundsForRead(offsetBytes, ARRAY_DOUBLE_INDEX_SCALE);
+    checkValidAndBounds(offsetBytes, ARRAY_DOUBLE_INDEX_SCALE);
     return Double.longBitsToDouble(
         Long.reverseBytes(unsafe.getLong(getUnsafeObject(), getCumulativeOffset(offsetBytes))));
   }
@@ -88,7 +70,7 @@ abstract class NonNativeWritableMemoryImpl extends BaseWritableMemoryImpl {
 
   @Override
   public float getFloat(final long offsetBytes) {
-    assertValidAndBoundsForRead(offsetBytes, ARRAY_FLOAT_INDEX_SCALE);
+    checkValidAndBounds(offsetBytes, ARRAY_FLOAT_INDEX_SCALE);
     return Float.intBitsToFloat(
         Integer.reverseBytes(unsafe.getInt(getUnsafeObject(), getCumulativeOffset(offsetBytes))));
   }
@@ -161,7 +143,7 @@ abstract class NonNativeWritableMemoryImpl extends BaseWritableMemoryImpl {
 
   @Override
   public void putDouble(final long offsetBytes, final double value) {
-    assertValidAndBoundsForWrite(offsetBytes, ARRAY_DOUBLE_INDEX_SCALE);
+    checkValidAndBoundsForWrite(offsetBytes, ARRAY_DOUBLE_INDEX_SCALE);
     unsafe.putLong(getUnsafeObject(), getCumulativeOffset(offsetBytes),
         Long.reverseBytes(Double.doubleToRawLongBits(value)));
   }
@@ -177,7 +159,7 @@ abstract class NonNativeWritableMemoryImpl extends BaseWritableMemoryImpl {
 
   @Override
   public void putFloat(final long offsetBytes, final float value) {
-    assertValidAndBoundsForWrite(offsetBytes, ARRAY_FLOAT_INDEX_SCALE);
+    checkValidAndBoundsForWrite(offsetBytes, ARRAY_FLOAT_INDEX_SCALE);
     unsafe.putInt(getUnsafeObject(), getCumulativeOffset(offsetBytes),
         Integer.reverseBytes(Float.floatToRawIntBits(value)));
   }
@@ -236,7 +218,7 @@ abstract class NonNativeWritableMemoryImpl extends BaseWritableMemoryImpl {
   //Atomic Write Methods
   @Override
   public long getAndAddLong(final long offsetBytes, final long delta) { //JDK 8+
-    assertValidAndBoundsForWrite(offsetBytes, ARRAY_LONG_INDEX_SCALE);
+    checkValidAndBoundsForWrite(offsetBytes, ARRAY_LONG_INDEX_SCALE);
     final long addr = getCumulativeOffset(offsetBytes);
     long oldValReverseBytes, oldVal, newValReverseBytes;
     final Object unsafeObj = getUnsafeObject();
@@ -251,7 +233,7 @@ abstract class NonNativeWritableMemoryImpl extends BaseWritableMemoryImpl {
 
   @Override
   public long getAndSetLong(final long offsetBytes, final long newValue) { //JDK 8+
-    assertValidAndBoundsForWrite(offsetBytes, ARRAY_LONG_INDEX_SCALE);
+    checkValidAndBoundsForWrite(offsetBytes, ARRAY_LONG_INDEX_SCALE);
     final long addr = getCumulativeOffset(offsetBytes);
     final long newValueReverseBytes = Long.reverseBytes(newValue);
     return Long.reverseBytes(unsafe.getAndSetLong(getUnsafeObject(), addr, newValueReverseBytes));
@@ -259,7 +241,7 @@ abstract class NonNativeWritableMemoryImpl extends BaseWritableMemoryImpl {
 
   @Override
   public boolean compareAndSwapLong(final long offsetBytes, final long expect, final long update) {
-    assertValidAndBoundsForWrite(offsetBytes, ARRAY_LONG_INDEX_SCALE);
+    checkValidAndBoundsForWrite(offsetBytes, ARRAY_LONG_INDEX_SCALE);
     return unsafe.compareAndSwapLong(getUnsafeObject(), getCumulativeOffset(offsetBytes),
         Long.reverseBytes(expect), Long.reverseBytes(update));
   }
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 178495f..d6411a3 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
@@ -19,104 +19,125 @@
 
 package org.apache.datasketches.memory.internal;
 
-import static org.apache.datasketches.memory.internal.UnsafeUtil.LS;
-import static org.apache.datasketches.memory.internal.UnsafeUtil.assertBounds;
-import static org.apache.datasketches.memory.internal.UnsafeUtil.checkBounds;
 import static org.apache.datasketches.memory.internal.UnsafeUtil.unsafe;
+import static org.apache.datasketches.memory.internal.Util.characterPad;
 
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
-import java.util.concurrent.atomic.AtomicLong;
 
+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;
 
 /**
- * Keeps key configuration state for MemoryImpl and BufferImpl plus some common static variables
- * and check methods.
+ * Implements the root Resource methods.
  *
  * @author Lee Rhodes
  */
 @SuppressWarnings("restriction")
 public abstract class ResourceImpl implements Resource {
-
-  //Monitoring
-  static final AtomicLong currentDirectMemoryAllocations_ = new AtomicLong();
-  static final AtomicLong currentDirectMemoryAllocated_ = new AtomicLong();
-  static final AtomicLong currentDirectMemoryMapAllocations_ = new AtomicLong();
-  static final AtomicLong currentDirectMemoryMapAllocated_ = new AtomicLong();
+  static final String JDK; //must be at least "1.8"
+  static final int JDK_MAJOR; //8, 11, 17, etc
+
+  //Used to convert "type" to bytes:  bytes = longs << LONG_SHIFT
+  static final int BOOLEAN_SHIFT    = 0;
+  static final int BYTE_SHIFT       = 0;
+  static final long SHORT_SHIFT     = 1;
+  static final long CHAR_SHIFT      = 1;
+  static final long INT_SHIFT       = 2;
+  static final long LONG_SHIFT      = 3;
+  static final long FLOAT_SHIFT     = 2;
+  static final long DOUBLE_SHIFT    = 3;
 
   //class type IDs. Do not change the bit orders
-  //The first 3 bits are set dynamically
-  // 0000 0XXX
+  //The lowest 3 bits are set dynamically
+  // 0000 0XXX Group 1
   static final int WRITABLE = 0;
   static final int READONLY = 1;
-  static final int REGION = 2;
-  static final int DUPLICATE = 4;
+  static final int REGION = 1 << 1;
+  static final int DUPLICATE = 1 << 2; //for Buffer only
 
-  //The following 4 bits are set by the 16 leaf nodes
-  // 000X X000
+  // 000X X000 Group 2
   static final int HEAP = 0;
   static final int DIRECT = 1 << 3;
-  static final int MAP = 2 << 3;
+  static final int MAP = 1 << 4; //Map is always Direct also
 
-  // 00X0 0000
+  // 00X0 0000 Group 3
   static final int NATIVE = 0;
   static final int NONNATIVE = 1 << 5;
 
-  // 0X00 0000
+  // 0X00 0000 Group 4
   static final int MEMORY = 0;
   static final int BUFFER = 1 << 6;
 
-  // X000 0000
+  // X000 0000 Group 5
   static final int BYTEBUF = 1 << 7;
 
   /**
-   * The root of the Memory inheritance hierarchy
+   * The java line separator character as a String.
    */
-  ResourceImpl() { }
+  public static final String LS = System.getProperty("line.separator");
+
+  public static final ByteOrder NATIVE_BYTE_ORDER = ByteOrder.nativeOrder();
+
+  public static final ByteOrder NON_NATIVE_BYTE_ORDER =
+      (NATIVE_BYTE_ORDER == ByteOrder.LITTLE_ENDIAN) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
 
-  final void assertValid() {
-    assert isValid() : "MemoryImpl not valid.";
+  static {
+    final String jdkVer = System.getProperty("java.version");
+    final int[] p = parseJavaVersion(jdkVer);
+    JDK = p[0] + "." + p[1];
+    JDK_MAJOR = (p[0] == 1) ? p[1] : p[0];
   }
 
-  final void assertValidAndBoundsForRead(final long offsetBytes, final long lengthBytes) {
-    assertValid();
-    // capacityBytes_ is intentionally read directly instead of calling getCapacity()
-    // because the later can make JVM to not inline the assert code path (and entirely remove it)
-    // even though it does nothing in production code path.
-    assertBounds(offsetBytes, lengthBytes, getCapacity());
+  MemoryRequestServer memReqSvr = null; //selected by the user
+
+  /**
+   * The root of the Memory inheritance hierarchy
+   */
+  ResourceImpl() { }
+
+  /**
+   * 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.
+   * @param reqOff the requested offset
+   * @param reqLen the requested length
+   * @param allocSize the allocated size.
+   */
+  public static void checkBounds(final long reqOff, final long reqLen, final long allocSize) {
+    if ((reqOff | reqLen | (reqOff + reqLen) | (allocSize - (reqOff + reqLen))) < 0) {
+      throw new MemoryBoundsException(
+          "reqOffset: " + reqOff + ", reqLength: " + reqLen
+              + ", (reqOff + reqLen): " + (reqOff + reqLen) + ", allocSize: " + allocSize);
+    }
   }
 
-  final void assertValidAndBoundsForWrite(final long offsetBytes, final long lengthBytes) {
-    assertValid();
-    // capacityBytes_ is intentionally read directly instead of calling getCapacity()
-    // because the later can make JVM to not inline the assert code path (and entirely remove it)
-    // even though it does nothing in production code path.
-    assertBounds(offsetBytes, lengthBytes, getCapacity());
-    assert !isReadOnly() : "MemoryImpl is read-only.";
+  public static final void checkThread(final Thread owner) {
+    if (owner != Thread.currentThread()) {
+      throw new IllegalStateException("Attempted access outside owning thread");
+    }
   }
 
   void checkValid() {
     if (!isValid()) {
-      throw new IllegalStateException("MemoryImpl not valid.");
+      throw new MemoryInvalidException();
     }
   }
 
   @Override
   public final void checkValidAndBounds(final long offsetBytes, final long lengthBytes) {
     checkValid();
-    //read capacityBytes_ directly to eliminate extra checkValid() call
-    checkBounds(offsetBytes, lengthBytes, getCapacity());
+    ResourceImpl.checkBounds(offsetBytes, lengthBytes, getCapacity());
   }
 
   final void checkValidAndBoundsForWrite(final long offsetBytes, final long lengthBytes) {
     checkValid();
-    //read capacityBytes_ directly to eliminate extra checkValid() call
-    checkBounds(offsetBytes, lengthBytes, getCapacity());
+    ResourceImpl.checkBounds(offsetBytes, lengthBytes, getCapacity());
     if (isReadOnly()) {
-      throw new ReadOnlyException("MemoryImpl is read-only.");
+      throw new ReadOnlyException("Memory is read-only.");
     }
   }
 
@@ -129,11 +150,15 @@ public abstract class ResourceImpl implements Resource {
   }
 
   @Override
-  public final boolean equalTo(final long thisOffsetBytes, final Object that,
+  public final boolean equalTo(final long thisOffsetBytes, final Resource that,
       final long thatOffsetBytes, final long lengthBytes) {
-    return that instanceof ResourceImpl
-      ? CompareAndCopy.equals(this, thisOffsetBytes, (ResourceImpl) that, thatOffsetBytes, lengthBytes)
-      : false;
+    if (that == null) { return false; }
+    return CompareAndCopy.equals(this, thisOffsetBytes, (ResourceImpl) that, thatOffsetBytes, lengthBytes);
+  }
+
+  @Override
+  public void force() { //overridden by Map Leaves
+    throw new IllegalStateException("This resource is not a memory-mapped file type.");
   }
 
   //Overridden by ByteBuffer Leafs
@@ -164,46 +189,12 @@ public abstract class ResourceImpl implements Resource {
     return getCumulativeOffset() + localOffsetBytes;
   }
 
-  //MONITORING
-
-  /**
-   * Gets the current size of active direct memory allocated.
-   * @return the current size of active direct memory allocated.
-   */
-  public static final long getCurrentDirectMemoryAllocated() {
-    return ResourceImpl.currentDirectMemoryAllocated_.get();
-  }
-
-  /**
-   * Gets the current number of active direct memory allocations.
-   * @return the current number of active direct memory allocations.
-   */
-  public static final long getCurrentDirectMemoryAllocations() {
-    return ResourceImpl.currentDirectMemoryAllocations_.get();
-  }
-
-  /**
-   * Gets the current size of active direct memory map allocated.
-   * @return the current size of active direct memory map allocated.
-   */
-  public static final long getCurrentDirectMemoryMapAllocated() {
-    return ResourceImpl.currentDirectMemoryMapAllocated_.get();
-  }
-
-  /**
-   * Gets the current number of active direct memory map allocations.
-   * @return the current number of active direct memory map allocations.
-   */
-  public static final long getCurrentDirectMemoryMapAllocations() {
-    return ResourceImpl.currentDirectMemoryMapAllocations_.get();
-  }
-  //END monitoring
-
   //Documented in WritableMemory and WritableBuffer interfaces.
   //Implemented in the Leaf nodes; Required here by toHex(...).
-  abstract MemoryRequestServer getMemoryRequestServer();
+  @Override
+  public abstract MemoryRequestServer getMemoryRequestServer();
 
-  //Overridden by ByteBuffer, Direct and Map leafs
+  //Overridden by ByteBuffer, Direct and Map Leaves
   abstract long getNativeBaseOffset();
 
   @Override
@@ -220,15 +211,9 @@ public abstract class ResourceImpl implements Resource {
     return null;
   }
 
-  @Override
-  public final boolean hasByteBuffer() {
-    assertValid();
-    return getByteBuffer() != null;
-  }
-
   @Override
   public final boolean hasArray() {
-    assertValid();
+    checkValid();
     return getUnsafeObject() != null;
   }
 
@@ -237,6 +222,11 @@ public abstract class ResourceImpl implements Resource {
     return (int) xxHash64(0, getCapacity(), 0); //xxHash64() calls checkValid()
   }
 
+  @Override
+  public boolean isByteBufferResource() {
+    return (getTypeId() & BYTEBUF) > 0;
+  }
+
   final boolean isByteBufferType(final int typeId) {
     return (typeId & BYTEBUF) > 0;
   }
@@ -252,12 +242,13 @@ public abstract class ResourceImpl implements Resource {
   }
 
   @Override
-  public final boolean isDirect() {
+  public final boolean isDirectResource() {
     return getUnsafeObject() == null;
   }
 
-  final boolean isDirectType(final int typeId) {
-    return (typeId & (MAP | DIRECT)) > 0;
+  @Override
+  public boolean isDuplicateBufferView() {
+    return (getTypeId() & DUPLICATE) > 0;
   }
 
   final boolean isDuplicateType(final int typeId) {
@@ -268,10 +259,25 @@ public abstract class ResourceImpl implements Resource {
     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.");
+  }
+
+  @Override
+  public boolean isMapped() {
+    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;
   }
@@ -280,13 +286,18 @@ public abstract class ResourceImpl implements Resource {
     return (typeId & NONNATIVE) == 0;
   }
 
+  @Override
+  public boolean isNonNativeOrder() {
+    return (getTypeId() & NONNATIVE) > 0;
+  }
+
   final boolean isNonNativeType(final int typeId) {
     return (typeId & NONNATIVE) > 0;
   }
 
   @Override
   public final boolean isReadOnly() {
-    assertValid();
+    checkValid();
     return isReadOnlyType(getTypeId());
   }
 
@@ -294,6 +305,11 @@ public abstract class ResourceImpl implements Resource {
     return (typeId & READONLY) > 0;
   }
 
+  @Override
+  public boolean isRegionView() {
+    return (getTypeId() & REGION) > 0;
+  }
+
   final boolean isRegionType(final int typeId) {
     return (typeId & REGION) > 0;
   }
@@ -302,16 +318,19 @@ public abstract class ResourceImpl implements Resource {
     return (typeId & READONLY) == 0;
   }
 
+  @Override
+  public void load() { //overridden by Map leafs
+    throw new IllegalStateException("This resource is not a memory-mapped file type.");
+  }
+
   final static int removeNnBuf(final int typeId) { return typeId & ~NONNATIVE & ~BUFFER; }
 
   final static int setReadOnlyType(final int typeId, final boolean readOnly) {
     return readOnly ? typeId | READONLY : typeId & ~READONLY;
   }
 
-  final
-
   @Override
-  public boolean isSameResource(final Object that) {
+  public boolean isSameResource(final Resource that) {
     checkValid();
     if (that == null) { return false; }
     final ResourceImpl that1 = (ResourceImpl) that;
@@ -330,10 +349,44 @@ public abstract class ResourceImpl implements Resource {
     return true;
   }
 
+  static void checkJavaVersion(final String jdkVer, final int p0, final int p1 ) {
+    final boolean ok = ((p0 == 1) && (p1 == 8)) || (p0 == 8) || (p0 == 11);
+    if (!ok) { throw new IllegalArgumentException(
+        "Unsupported JDK Major Version. It must be one of 1.8, 8, 11: " + jdkVer);
+    }
+  }
+
+  private static String pad(final String s, final int fieldLen) {
+    return characterPad(s, fieldLen, ' ' , true);
+  }
+
+  /**
+   * Returns first two number groups of the java version string.
+   * @param jdkVer the java version string from System.getProperty("java.version").
+   * @return first two number groups of the java version string.
+   * @throws IllegalArgumentException for an improper Java version string.
+   */
+  static int[] parseJavaVersion(final String jdkVer) {
+    final int p0, p1;
+    try {
+      String[] parts = jdkVer.trim().split("^0-9\\.");//grab only number groups and "."
+      parts = parts[0].split("\\."); //split out the number groups
+      p0 = Integer.parseInt(parts[0]); //the first number group
+      p1 = (parts.length > 1) ? Integer.parseInt(parts[1]) : 0; //2nd number group, or 0
+    } catch (final NumberFormatException | ArrayIndexOutOfBoundsException  e) {
+      throw new IllegalArgumentException("Improper Java -version string: " + jdkVer + "\n" + e);
+    }
+    checkJavaVersion(jdkVer, p0, p1);
+    return new int[] {p0, p1};
+  }
+
   //REACHABILITY FENCE
   static void reachabilityFence(final Object obj) { }
 
-  //TO STRING
+  @Override
+  public void setMemoryRequestServer(final MemoryRequestServer memReqSvr) {
+    this.memReqSvr = memReqSvr;
+  }
 
   /**
    * Returns a formatted hex string of an area of this object.
@@ -347,7 +400,7 @@ public abstract class ResourceImpl implements Resource {
   static final String toHex(final ResourceImpl state, final String preamble, final long offsetBytes,
       final int lengthBytes) {
     final long capacity = state.getCapacity();
-    UnsafeUtil.checkBounds(offsetBytes, lengthBytes, capacity);
+    ResourceImpl.checkBounds(offsetBytes, lengthBytes, capacity);
     final StringBuilder sb = new StringBuilder();
     final Object uObj = state.getUnsafeObject();
     final String uObjStr;
@@ -415,43 +468,45 @@ public abstract class ResourceImpl implements Resource {
    * @param typeId the given typeId
    * @return a human readable string.
    */
-  public static final String typeDecode(final int typeId) {
+  static final String typeDecode(final int typeId) {
     final StringBuilder sb = new StringBuilder();
-    sb.append(typeId + ": ");
     final int group1 = typeId & 0x7;
-    switch (group1) {
-      case 1 : sb.append("ReadOnly, "); break;
-      case 2 : sb.append("Region, "); break;
-      case 3 : sb.append("ReadOnly Region, "); break;
-      case 4 : sb.append("Duplicate, "); break;
-      case 5 : sb.append("ReadOnly Duplicate, "); break;
-      case 6 : sb.append("Region Duplicate, "); break;
-      case 7 : sb.append("ReadOnly Region Duplicate, "); break;
+    switch (group1) { // 0000 0XXX
+      case 0 : sb.append(pad("Writable + ",32)); break;
+      case 1 : sb.append(pad("ReadOnly + ",32)); break;
+      case 2 : sb.append(pad("Writable + Region + ",32)); break;
+      case 3 : sb.append(pad("ReadOnly + Region + ",32)); break;
+      case 4 : sb.append(pad("Writable + Duplicate + ",32)); break;
+      case 5 : sb.append(pad("ReadOnly + Duplicate + ",32)); break;
+      case 6 : sb.append(pad("Writable + Region + Duplicate + ",32)); break;
+      case 7 : sb.append(pad("ReadOnly + Region + Duplicate + ",32)); break;
       default: break;
     }
     final int group2 = (typeId >>> 3) & 0x3;
-    switch (group2) {
-      case 0 : sb.append("Heap, "); break;
-      case 1 : sb.append("Direct, "); break;
-      case 2 : sb.append("Map, "); break;
-      case 3 : sb.append("Map Direct, "); break;
+    switch (group2) { // 000X X000
+      case 0 : sb.append(pad("Heap + ",15)); break;
+      case 1 : sb.append(pad("Direct + ",15)); break;
+      case 2 : sb.append(pad("Map + Direct + ",15)); break;
+      case 3 : sb.append(pad("Map + Direct + ",15)); break;
       default: break;
     }
     final int group3 = (typeId >>> 5) & 0x1;
-    switch (group3) {
-      case 0 : sb.append("Native, "); break;
-      case 1 : sb.append("NonNative, "); break;
+    switch (group3) { // 00X0 0000
+      case 0 : sb.append(pad("NativeOrder + ",17)); break;
+      case 1 : sb.append(pad("NonNativeOrder + ",17)); break;
       default: break;
     }
     final int group4 = (typeId >>> 6) & 0x1;
-    switch (group4) {
-      case 0 : sb.append("Memory, "); break;
-      case 1 : sb.append("Buffer, "); break;
+    switch (group4) { // 0X00 0000
+      case 0 : sb.append(pad("Memory + ",9)); break;
+      case 1 : sb.append(pad("Buffer + ",9)); break;
       default: break;
     }
     final int group5 = (typeId >>> 7) & 0x1;
-    switch (group5) {
-      case 1 : sb.append("ByteBuffer"); break;
+    switch (group5) { // X000 0000
+      case 0 : sb.append(pad("",10)); break;
+      case 1 : sb.append(pad("ByteBuffer",10)); break;
+      default: break;
     }
     return sb.toString();
   }
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 0a99211..f213615 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
@@ -189,34 +189,4 @@ public final class UnsafeUtil {
     }
   }
 
-  /**
-   * Assert 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 and assertions are enabled, an {@link AssertionError} will
-   * be thrown.
-   * @param reqOff the requested offset
-   * @param reqLen the requested length
-   * @param allocSize the allocated size.
-   */
-  public static void assertBounds(final long reqOff, final long reqLen, final long allocSize) {
-    assert ((reqOff | reqLen | (reqOff + reqLen) | (allocSize - (reqOff + reqLen))) >= 0) :
-      "reqOffset: " + reqOff + ", reqLength: " + reqLen
-      + ", (reqOff + reqLen): " + (reqOff + reqLen) + ", allocSize: " + allocSize;
-  }
-
-  /**
-   * 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.
-   * @param reqOff the requested offset
-   * @param reqLen the requested length
-   * @param allocSize the allocated size.
-   */
-  public static void checkBounds(final long reqOff, final long reqLen, final long allocSize) {
-    if ((reqOff | reqLen | (reqOff + reqLen) | (allocSize - (reqOff + reqLen))) < 0) {
-      throw new IllegalArgumentException(
-          "reqOffset: " + reqOff + ", reqLength: " + reqLen
-              + ", (reqOff + reqLen): " + (reqOff + reqLen) + ", allocSize: " + allocSize);
-    }
-  }
 }
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/Util.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/Util.java
index 182053a..d60a67d 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/Util.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/Util.java
@@ -92,7 +92,7 @@ public final class Util {
    */
   public static long binarySearchLongs(final Memory mem, final long fromLongIndex,
       final long toLongIndex, final long key) {
-    UnsafeUtil.checkBounds(fromLongIndex << 3, (toLongIndex - fromLongIndex) << 3, mem.getCapacity());
+    ResourceImpl.checkBounds(fromLongIndex << 3, (toLongIndex - fromLongIndex) << 3, mem.getCapacity());
     long low = fromLongIndex;
     long high = toLongIndex - 1L;
 
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/VirtualMachineMemory.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/VirtualMachineMemory.java
index c4497e9..5ba5387 100644
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/VirtualMachineMemory.java
+++ b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/VirtualMachineMemory.java
@@ -19,6 +19,8 @@
 
 package org.apache.datasketches.memory.internal;
 
+import static org.apache.datasketches.memory.internal.UnsafeUtil.unsafe;
+
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 
@@ -36,6 +38,8 @@ public final class VirtualMachineMemory {
     private static final Method VM_IS_DIRECT_MEMORY_PAGE_ALIGNED_METHOD;
     private static final long maxDBBMemory;
     private static final boolean isPageAligned;
+    @SuppressWarnings("restriction")
+    private static int pageSize = unsafe.pageSize();
 
     static {
         try {
@@ -71,4 +75,8 @@ public final class VirtualMachineMemory {
     public static boolean getIsPageAligned() {
         return isPageAligned;
     }
+
+    public static int getPageSize() {
+      return pageSize;
+    }
 }
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/WritableDirectHandleImpl.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/WritableDirectHandleImpl.java
deleted file mode 100644
index 76882ca..0000000
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/WritableDirectHandleImpl.java
+++ /dev/null
@@ -1,67 +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 org.apache.datasketches.memory.Handle;
-import org.apache.datasketches.memory.Memory;
-import org.apache.datasketches.memory.WritableHandle;
-import org.apache.datasketches.memory.WritableMemory;
-
-/**
- * A Handle for a writable direct memory resource.
- * Joins an AutoCloseable WritableHandle with a WritableMemory and AllocateDirect resource.
- * Please read Javadocs for {@link Handle}.
- *
- * @author Lee Rhodes
- * @author Roman Leventov
- */
-public final class WritableDirectHandleImpl implements WritableHandle {
-
-  /**
-   * Having at least one final field makes this class safe for concurrent publication.
-   */
-  final AllocateDirect direct;
-  private BaseWritableMemoryImpl wMem;
-
-  WritableDirectHandleImpl(final AllocateDirect allocatedDirect, final BaseWritableMemoryImpl wMem) {
-    direct = allocatedDirect;
-    this.wMem = wMem;
-  }
-
-  @Override
-  public Memory get() {
-    return wMem;
-  }
-
-  @Override
-  public WritableMemory getWritable() {
-    return wMem;
-  }
-
-  //AutoCloseable
-
-  @Override
-  public void close() {
-    if (direct.doClose()) {
-      wMem = null;
-    }
-
-  }
-}
diff --git a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/WritableMapHandleImpl.java b/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/WritableMapHandleImpl.java
deleted file mode 100644
index 7683bf7..0000000
--- a/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/WritableMapHandleImpl.java
+++ /dev/null
@@ -1,52 +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 org.apache.datasketches.memory.Handle;
-import org.apache.datasketches.memory.WritableMapHandle;
-import org.apache.datasketches.memory.WritableMemory;
-
-/**
- * A Handle for a memory-mapped, writable file resource.
- * Joins a WritableHandle with an AutoCloseable WritableMap resource
- * Please read Javadocs for {@link Handle}.
- *
- * @author Roman Leventov
- * @author Lee Rhodes
- */
-public final class WritableMapHandleImpl extends MapHandleImpl
-    implements WritableMapHandle {
-
-  WritableMapHandleImpl(
-      final AllocateDirectWritableMap dirWmap,
-      final BaseWritableMemoryImpl wMem) {
-    super(dirWmap, wMem);
-  }
-
-  @Override
-  public WritableMemory getWritable() {
-    return wMem;
-  }
-
-  @Override
-  public void force() {
-    ((AllocateDirectWritableMap)dirMap).force();
-  }
-}
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 8ee0f5c..1da9dc6 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
@@ -25,22 +25,20 @@ package org.apache.datasketches.memory.internal;
 
 import static org.apache.datasketches.memory.internal.Util.getResourceFile;
 import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.fail;
 
 import java.io.File;
 import java.nio.ByteOrder;
 
-import org.apache.datasketches.memory.MapHandle;
 import org.apache.datasketches.memory.Memory;
-import org.testng.annotations.AfterClass;
+import org.apache.datasketches.memory.MemoryCloseException;
+import org.apache.datasketches.memory.MemoryInvalidException;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
 public class AllocateDirectMapMemoryTest {
   private static final String LS = System.getProperty("line.separator");
-  MapHandle hand = null;
 
   @BeforeClass
   public void setReadOnly() {
@@ -48,20 +46,19 @@ public class AllocateDirectMapMemoryTest {
   }
 
   @Test
-  public void simpleMap() throws Exception {
+  public void simpleMap() {
     File file = getResourceFile("GettysburgAddress.txt");
     assertTrue(AllocateDirectWritableMap.isFileReadOnly(file));
-    try (MapHandle rh = Memory.map(file)) {
-      rh.close();
-    }
+    try (Memory mem = Memory.map(file)) {
+      mem.close(); //redundant close
+    } catch (MemoryCloseException e) { }
   }
 
   @Test
-  public void simpleMap2() throws Exception {
+  public void simpleMap2()  {
     File file = getResourceFile("GettysburgAddress.txt");
-    try (MapHandle rh = Memory.map(file))
+    try (Memory mem = Memory.map(file))
     {
-      Memory mem = rh.get();
       println("Mem Cap:       " + mem.getCapacity());
       println("Native Off:    " + ((ResourceImpl)mem).getNativeBaseOffset());
       println("Total Offset:  " + mem.getTotalOffset());
@@ -81,100 +78,65 @@ public class AllocateDirectMapMemoryTest {
       StringBuilder sb2 = new StringBuilder();
       mem2.getCharsFromUtf8(0, 12, sb2);
       println(sb2.toString());
-
-      rh.close();
     }
   }
 
   @Test
-  public void testIllegalArguments() throws Exception {
+  public void testIllegalArguments() {
     File file = getResourceFile("GettysburgAddress.txt");
-    try (MapHandle rh = Memory.map(file, -1, Integer.MAX_VALUE, ByteOrder.nativeOrder())) {
-      fail("Failed: testIllegalArgumentException: Position was negative.");
+    try (Memory mem = Memory.map(file, -1, Integer.MAX_VALUE, ByteOrder.nativeOrder())) {
+      fail("Failed: Position was negative.");
     } catch (IllegalArgumentException e) {
       //ok
     }
 
-    try (MapHandle rh = Memory.map(file, 0, -1, ByteOrder.nativeOrder())) {
-      fail("Failed: testIllegalArgumentException: Size was negative.");
+    try (Memory mem = Memory.map(file, 0, -1, ByteOrder.nativeOrder())) {
+      fail("Failed: Size was negative.");
     } catch (IllegalArgumentException e) {
       //ok
     }
   }
 
   @Test
-  public void testMapAndMultipleClose() throws Exception {
+  public void testMapAndMultipleClose() {
     File file = getResourceFile("GettysburgAddress.txt");
     long memCapacity = file.length();
-    try (MapHandle rh = Memory.map(file, 0, memCapacity, ByteOrder.nativeOrder())) {
-      Memory map = rh.get();
-      assertEquals(memCapacity, map.getCapacity());
-      rh.close();
-      rh.close();
-      map.getCapacity(); //throws assertion error
-    } catch (AssertionError e) {
-      //OK
+    try (Memory mem = Memory.map(file, 0, memCapacity, ByteOrder.nativeOrder())) {
+      assertEquals(memCapacity, mem.getCapacity());
     }
-  }
-
-  @Test
-  public void testReadFailAfterClose() throws Exception {
-    File file = getResourceFile("GettysburgAddress.txt");
-    long memCapacity = file.length();
-    try (MapHandle rh = Memory.map(file, 0, memCapacity, ByteOrder.nativeOrder())) {
-      Memory mmf = rh.get();
-      rh.close();
-      mmf.getByte(0);
-    } catch (AssertionError e) {
-      //OK
+    try {
+      Memory mem = Memory.map(file, 0, memCapacity, ByteOrder.nativeOrder());
+      mem.close();
+      mem.close(); //redundant close
+    } catch (MemoryCloseException e) { /* OK */ }
+    try {
+      Memory mem = Memory.map(file, 0, memCapacity, ByteOrder.nativeOrder());
+      mem.close();
+      mem.getCapacity(); //already closed
     }
+    catch (MemoryInvalidException e) { /* OK */ }
   }
 
   @Test
-  public void testLoad() throws Exception {
+  public void testReadFailAfterClose()  {
     File file = getResourceFile("GettysburgAddress.txt");
     long memCapacity = file.length();
-    try (MapHandle rh = Memory.map(file, 0, memCapacity, ByteOrder.nativeOrder())) {
-      rh.load();
-      assertTrue(rh.isLoaded());
-      rh.close();
+    try {
+      Memory mem = Memory.map(file, 0, memCapacity, ByteOrder.nativeOrder());
+      mem.close();
+      mem.getByte(0);
+    } catch (MemoryInvalidException e) {
+      //OK
     }
   }
 
   @Test
-  public void testHandlerHandoffWithTWR() throws Exception {
-    File file = getResourceFile("GettysburgAddress.txt");
-    long memCapacity = file.length();
-    Memory mem;
-    try (MapHandle rh = Memory.map(file, 0, memCapacity, ByteOrder.nativeOrder())) {
-      rh.load();
-      assertTrue(rh.isLoaded());
-      hand = rh;
-      mem = rh.get();
-    } //TWR closes
-    assertFalse(mem.isValid());
-    //println(""+mem.isValid());
-  }
-
-  @Test
-  public void testHandoffWithoutClose() throws Exception {
+  public void testLoad()  {
     File file = getResourceFile("GettysburgAddress.txt");
     long memCapacity = file.length();
-    MapHandle rh = Memory.map(file, 0, memCapacity, ByteOrder.nativeOrder());
-    rh.load();
-    assertTrue(rh.isLoaded());
-    hand = rh;
-    //The receiver of the handler must close the resource, in this case it is the class.
-  }
-
-  @AfterClass
-  public void afterAllTests() throws Exception {
-      if (hand != null) {
-      Memory mem = hand.get();
-      if ((mem != null) && mem.isValid()) {
-        hand.close();
-        assertFalse(mem.isValid());
-      }
+    try (Memory mem = Memory.map(file, 0, memCapacity, ByteOrder.nativeOrder())) {
+      mem.load();
+      assertTrue(mem.isLoaded());
     }
   }
 
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 7e2e89a..72b83b5 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
@@ -21,24 +21,19 @@ package org.apache.datasketches.memory.internal;
 
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.fail;
 
-import org.apache.datasketches.memory.Resource;
 import org.apache.datasketches.memory.DefaultMemoryRequestServer;
 import org.apache.datasketches.memory.MemoryRequestServer;
-import org.apache.datasketches.memory.WritableHandle;
+import org.apache.datasketches.memory.Resource;
 import org.apache.datasketches.memory.WritableMemory;
-import org.testng.annotations.AfterClass;
 import org.testng.annotations.Test;
 
 public class AllocateDirectMemoryTest {
 
   @Test
-  public void simpleAllocateDirect() throws Exception {
+  public void simpleAllocateDirect()  {
     int longs = 32;
-    WritableMemory wMem;
-    try (WritableHandle wh = WritableMemory.allocateDirect(longs << 3)) {
-      wMem = wh.getWritable();
+    try (WritableMemory wMem = WritableMemory.allocateDirect(longs << 3)) {
       for (int i = 0; i < longs; i++) {
         wMem.putLong(i << 3, i);
         assertEquals(wMem.getLong(i << 3), i);
@@ -47,21 +42,13 @@ public class AllocateDirectMemoryTest {
       ((ResourceImpl)wMem).checkValid();
       //OK
     }
-    //The TWR block has exited, so the memory should be invalid
-    try {
-      ((ResourceImpl)wMem).checkValid();
-      fail();
-    } catch (final RuntimeException e) {
-      //OK
-    }
   }
 
   @Test
-  public void checkDefaultMemoryRequestServer() throws Exception {
+  public void checkDefaultMemoryRequestServer()  {
     int longs1 = 32;
     int bytes1 = longs1 << 3;
-    try (WritableHandle wh = WritableMemory.allocateDirect(bytes1)) {
-      WritableMemory origWmem = wh.getWritable();
+    try (WritableMemory origWmem = WritableMemory.allocateDirect(bytes1)) {
       for (int i = 0; i < longs1; i++) { //puts data in wMem1
         origWmem.putLong(i << 3, i);
         assertEquals(origWmem.getLong(i << 3), i);
@@ -77,7 +64,7 @@ public class AllocateDirectMemoryTest {
         memReqSvr = origWmem.getMemoryRequestServer();
       }
       WritableMemory newWmem = memReqSvr.request(origWmem, bytes2);
-      assertFalse(newWmem.isDirect()); //on heap by default
+      assertFalse(newWmem.isDirectResource()); //on heap by default
       for (int i = 0; i < longs2; i++) {
           newWmem.putLong(i << 3, i);
           assertEquals(newWmem.getLong(i << 3), i);
@@ -89,30 +76,18 @@ public class AllocateDirectMemoryTest {
   }
 
   @Test
-  public void checkNonNativeDirect() throws Exception {
-    try (WritableHandle h = WritableMemory.allocateDirect(128, Util.NON_NATIVE_BYTE_ORDER, null)) {
-      WritableMemory wmem = h.getWritable();
+  public void checkNonNativeDirect()  {
+    try (WritableMemory wmem = WritableMemory.allocateDirect(128, Util.NON_NATIVE_BYTE_ORDER, null)) {
       wmem.putChar(0, (char) 1);
       assertEquals(wmem.getByte(1), (byte) 1);
     }
   }
 
   @Test
-  public void checkExplicitClose() throws Exception {
+  public void checkExplicitClose() {
     final long cap = 128;
-    try (WritableHandle wdh = WritableMemory.allocateDirect(cap)) {
-      wdh.close(); //explicit close. Does the work of closing
-    } //end of scope call to Cleaner/Deallocator also will be redundant
-  }
-
-  @AfterClass
-  public void checkDirectCounter() {
-    WritableMemory.writableWrap(new byte[8]);
-    long count = Resource.getCurrentDirectMemoryAllocations();
-    if (count != 0) {
-      println("" + count);
-      fail();
-    }
+    WritableMemory wMem = WritableMemory.allocateDirect(cap);
+    wMem.close();
   }
 
   @Test
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/AllocateDirectWritableMapMemoryTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/AllocateDirectWritableMapMemoryTest.java
index 2997c0e..98d3c2a 100644
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/AllocateDirectWritableMapMemoryTest.java
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/AllocateDirectWritableMapMemoryTest.java
@@ -36,14 +36,9 @@ import java.io.PrintWriter;
 import java.io.UnsupportedEncodingException;
 import java.nio.ByteOrder;
 
-import org.apache.datasketches.memory.Resource;
-import org.apache.datasketches.memory.MapHandle;
 import org.apache.datasketches.memory.Memory;
 import org.apache.datasketches.memory.ReadOnlyException;
-import org.apache.datasketches.memory.WritableHandle;
-import org.apache.datasketches.memory.WritableMapHandle;
 import org.apache.datasketches.memory.WritableMemory;
-import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
@@ -58,14 +53,13 @@ public class AllocateDirectWritableMapMemoryTest {
   @Test
   public void simpleMap() throws Exception {
     File file = getResourceFile("GettysburgAddress.txt");
-    try (MapHandle h = Memory.map(file); WritableMapHandle wh = (WritableMapHandle) h) {
-      Memory mem = h.get();
+    try (Memory mem = Memory.map(file)) {
       byte[] bytes = new byte[(int)mem.getCapacity()];
       mem.getByteArray(0, bytes, 0, bytes.length);
       String text = new String(bytes, UTF_8);
       println(text);
       try {
-        wh.force();
+        mem.force();
         fail();
       } catch (ReadOnlyException e) {
         //OK
@@ -92,12 +86,8 @@ public class AllocateDirectWritableMapMemoryTest {
     file.deleteOnExit();  //comment out if you want to examine the file.
 
     try (
-        WritableMapHandle dstHandle
-          = WritableMemory.writableMap(file, 0, bytes, ByteOrder.nativeOrder());
-        WritableHandle srcHandle = WritableMemory.allocateDirect(bytes)) {
-
-      WritableMemory dstMem = dstHandle.getWritable();
-      WritableMemory srcMem = srcHandle.getWritable();
+        WritableMemory dstMem = WritableMemory.writableMap(file, 0, bytes, ByteOrder.nativeOrder());
+        WritableMemory srcMem = WritableMemory.allocateDirect(bytes)) {
 
       for (long i = 0; i < longs; i++) {
         srcMem.putLong(i << 3, i); //load source with consecutive longs
@@ -105,7 +95,7 @@ public class AllocateDirectWritableMapMemoryTest {
 
       srcMem.copyTo(0, dstMem, 0, srcMem.getCapacity()); //off-heap to off-heap copy
 
-      dstHandle.force(); //push any remaining to the file
+      dstMem.force(); //push any remaining to the file
 
       //check end value
       assertEquals(dstMem.getLong(longs - 1L << 3), longs - 1L);
@@ -128,8 +118,7 @@ public class AllocateDirectWritableMapMemoryTest {
     file.deleteOnExit();  //comment out if you want to examine the file.
 
     final long bytes = 8;
-    try (WritableMapHandle h = WritableMemory.writableMap(file, 0L, bytes, Util.NON_NATIVE_BYTE_ORDER)) {
-      WritableMemory wmem = h.getWritable();
+    try (WritableMemory wmem = WritableMemory.writableMap(file, 0L, bytes, Util.NON_NATIVE_BYTE_ORDER)) {
       wmem.putChar(0, (char) 1);
       assertEquals(wmem.getByte(1), (byte) 1);
     }
@@ -138,16 +127,15 @@ public class AllocateDirectWritableMapMemoryTest {
   @Test(expectedExceptions = RuntimeException.class)
   public void testMapException() throws IOException {
     File dummy = createFile("dummy.txt", ""); //zero length
-    //throws java.lang.reflect.InvocationTargetException
+    //throws IOException "Invalid Argument"
     Memory.map(dummy, 0, dummy.length(), ByteOrder.nativeOrder());
   }
 
   @Test(expectedExceptions = ReadOnlyException.class)
-  public void simpleMap2() throws Exception {
+  public void simpleMap2() throws IOException {
     File file = getResourceFile("GettysburgAddress.txt");
     assertTrue(file.canRead() && !file.canWrite());
-    try (WritableMapHandle rh =
-        WritableMemory.writableMap(file)) { //throws
+    try (WritableMemory wmem = WritableMemory.writableMap(file)) { //throws
       //
     }
   }
@@ -155,12 +143,7 @@ public class AllocateDirectWritableMapMemoryTest {
   @Test(expectedExceptions = ReadOnlyException.class)
   public void checkOverLength() throws Exception  {
     File file = getResourceFile("GettysburgAddress.txt");
-    try (WritableMapHandle rh =
-        WritableMemory.writableMap(file, 0, 1 << 20, ByteOrder.nativeOrder())) {
-      //
-    } catch (IOException e) {
-      throw new RuntimeException(e);
-    }
+    WritableMemory.writableMap(file, 0, 1 << 20, ByteOrder.nativeOrder());
   }
 
   @Test
@@ -173,10 +156,9 @@ public class AllocateDirectWritableMapMemoryTest {
     byte[] correctByteArr = correctStr.getBytes(UTF_8);
     long corrBytes = correctByteArr.length;
 
-    try (MapHandle rh = Memory.map(origFile, 0, origBytes, ByteOrder.nativeOrder())) {
-      Memory map = rh.get();
-      rh.load();
-      assertTrue(rh.isLoaded());
+    try (Memory map = Memory.map(origFile, 0, origBytes, ByteOrder.nativeOrder())) {
+      map.load();
+      assertTrue(map.isLoaded());
       //confirm orig string
       byte[] buf = new byte[(int)origBytes];
       map.getByteArray(0, buf, 0, (int)origBytes);
@@ -184,14 +166,12 @@ public class AllocateDirectWritableMapMemoryTest {
       assertEquals(bufStr, origStr);
     }
 
-    try (WritableMapHandle wrh = WritableMemory.writableMap(origFile, 0, corrBytes,
-        ByteOrder.nativeOrder())) {
-      WritableMemory wMap = wrh.getWritable();
-      wrh.load();
-      assertTrue(wrh.isLoaded());
+    try (WritableMemory wMap = WritableMemory.writableMap(origFile, 0, corrBytes, ByteOrder.nativeOrder())) {
+      wMap.load();
+      assertTrue(wMap.isLoaded());
       // over write content
       wMap.putByteArray(0, correctByteArr, 0, (int)corrBytes);
-      wrh.force();
+      wMap.force();
       //confirm correct string
       byte[] buf = new byte[(int)corrBytes];
       wMap.getByteArray(0, buf, 0, (int)corrBytes);
@@ -214,23 +194,6 @@ public class AllocateDirectWritableMapMemoryTest {
     return file;
   }
 
-  @Test
-  public void checkExplicitClose() throws Exception {
-    File file = getResourceFile("GettysburgAddress.txt");
-    try (MapHandle wmh = Memory.map(file)) {
-      wmh.close(); //explicit close.
-    } //end of scope call to Cleaner/Deallocator also will be redundant
-  }
-
-  @AfterClass
-  public void checkDirectCounter() {
-    long count =  Resource.getCurrentDirectMemoryMapAllocations();
-      if (count != 0) {
-        println("" + count);
-        fail();
-      }
-    }
-
   @Test
   public void printlnTest() {
     println("PRINTING: " + this.getClass().getName());
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 4e8bfff..22e8c83 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
@@ -22,8 +22,9 @@ package org.apache.datasketches.memory.internal;
 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.WritableHandle;
+import org.apache.datasketches.memory.MemoryInvalidException;
 import org.apache.datasketches.memory.WritableMemory;
 import org.testng.annotations.Test;
 
@@ -40,7 +41,7 @@ public class BaseBufferTest {
     try {
       buf.setStartPositionEnd(0, 0, 101);
       fail();
-    } catch (AssertionError e) {
+    } catch (BufferPositionInvariantsException e) {
       //ok
     }
   }
@@ -53,14 +54,14 @@ public class BaseBufferTest {
     try {
       buf.setAndCheckStartPositionEnd(0, 0, 101);
       fail();
-    } catch (IllegalArgumentException e) {
+    } catch (BufferPositionInvariantsException e) {
       //ok
     }
     buf.setAndCheckPosition(100);
     try {
       buf.setAndCheckPosition(101);
       fail();
-    } catch (IllegalArgumentException e) {
+    } catch (BufferPositionInvariantsException e) {
       //ok
     }
     buf.setPosition(99);
@@ -68,22 +69,21 @@ public class BaseBufferTest {
     try {
       buf.incrementAndCheckPosition(1L);
       fail();
-    } catch (IllegalArgumentException e) {
+    } catch (BufferPositionInvariantsException e) {
       //ok
     }
   }
 
   @Test
-  public void checkCheckValid() throws Exception {
-    WritableMemory wmem;
+  public void checkCheckValid() {
+
     Buffer buf;
-    try (WritableHandle hand = WritableMemory.allocateDirect(100)) {
-      wmem = hand.getWritable();
+    try (WritableMemory wmem = WritableMemory.allocateDirect(100)) {
       buf = wmem.asBuffer();
     }
     try {
       @SuppressWarnings("unused")
-      Memory mem = buf.asMemory();
-    } catch (AssertionError ae) { }
+      Memory mem = buf.asMemory(); //wmem, buf no longer valid
+    } catch (MemoryInvalidException ae) { }
   }
 }
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/Buffer2Test.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/Buffer2Test.java
index 22e60e0..e90b956 100644
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/Buffer2Test.java
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/Buffer2Test.java
@@ -56,7 +56,7 @@ public class Buffer2Test {
     }
 
     assertEquals(true, buffer.hasArray());
-    assertEquals(true, buffer.hasByteBuffer());
+    assertEquals(true, buffer.isByteBufferResource());
   }
 
   @Test
@@ -76,7 +76,7 @@ public class Buffer2Test {
     }
 
     assertEquals(false, buffer.hasArray());
-    assertEquals(true, buffer.hasByteBuffer());
+    assertEquals(true, buffer.isByteBufferResource());
   }
 
   @Test
@@ -99,7 +99,7 @@ public class Buffer2Test {
     assertEquals(byteArray, copyByteArray);
 
     assertEquals(true, buffer.hasArray());
-    assertEquals(false, buffer.hasByteBuffer());
+    assertEquals(false, buffer.isByteBufferResource());
   }
 
   @Test
@@ -382,7 +382,7 @@ public class Buffer2Test {
     }
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testROByteBuffer() {
     byte[] arr = new byte[64];
     ByteBuffer roBB = ByteBuffer.wrap(arr).asReadOnlyBuffer();
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BufferBoundaryCheckTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BufferBoundaryCheckTest.java
index 535b0ca..8edbd46 100644
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BufferBoundaryCheckTest.java
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BufferBoundaryCheckTest.java
@@ -19,6 +19,7 @@
 
 package org.apache.datasketches.memory.internal;
 
+import org.apache.datasketches.memory.MemoryBoundsException;
 import org.apache.datasketches.memory.WritableMemory;
 import org.testng.annotations.Test;
 
@@ -26,212 +27,98 @@ public class BufferBoundaryCheckTest {
 
   private final WritableMemory writableMemory = WritableMemory.allocate(8);
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testGetBoolean() {
-    writableMemory.getBoolean(7);
-    try {
-      writableMemory.getBoolean(8);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableMemory.getBoolean(8);
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testPutBoolean() {
-    writableMemory.putBoolean(7, true);
-    try {
-      writableMemory.putBoolean(8, true);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableMemory.putBoolean(8, true);
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testGetByte() {
-    writableMemory.getByte(7);
-    try {
-      writableMemory.getByte(8);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableMemory.getByte(8);
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testPutByte() {
-    writableMemory.putByte(7, (byte) 1);
-    try {
-      writableMemory.putByte(8, (byte) 1);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableMemory.putByte(8, (byte) 1);
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testGetChar() {
-    writableMemory.getChar(6);
-    try {
-      writableMemory.getChar(7);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableMemory.getChar(7);
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testPutChar() {
-    writableMemory.putChar(6, 'a');
-    try {
-      writableMemory.putChar(7, 'a');
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableMemory.putChar(7, 'a');
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testGetShort() {
-    writableMemory.getShort(6);
-    try {
-      writableMemory.getShort(7);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableMemory.getShort(7);
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testPutShort() {
-    writableMemory.putShort(6, (short) 1);
-    try {
-      writableMemory.putShort(7, (short) 1);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableMemory.putShort(7, (short) 1);
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testGetInt() {
-    writableMemory.getInt(4);
-    try {
-      writableMemory.getInt(5);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableMemory.getInt(5);
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testPutInt() {
-    writableMemory.putInt(4, 1);
-    try {
-      writableMemory.putInt(5, 1);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableMemory.putInt(5, 1);
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testGetFloat() {
-    writableMemory.getFloat(4);
-    try {
-      writableMemory.getFloat(5);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableMemory.getFloat(5);
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testPutFloat() {
-    writableMemory.putFloat(4, 1f);
-    try {
-      writableMemory.putFloat(5, 1f);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableMemory.putFloat(5, 1f);
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testGetLong() {
-    writableMemory.getLong(0);
-    try {
-      writableMemory.getLong(1);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableMemory.getLong(1);
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testPutLong() {
-    writableMemory.putLong(0, 1L);
-    try {
-      writableMemory.putLong(1, 1L);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableMemory.putLong(1, 1L);
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testGetDouble() {
-    writableMemory.getDouble(0);
-    try {
-      writableMemory.getDouble(1);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableMemory.getDouble(1);
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testPutDouble() {
-    writableMemory.putDouble(0, 1d);
-    try {
-      writableMemory.putDouble(1, 1d);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableMemory.putDouble(1, 1d);
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testGetAndAddLong() {
-    writableMemory.getAndAddLong(0, 1L);
-    try {
-      writableMemory.getAndAddLong(1, 1L);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableMemory.getAndAddLong(1, 1L);
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testGetAndSetLong() {
-    writableMemory.getAndSetLong(0, 1L);
-    try {
-      writableMemory.getAndSetLong(1, 1L);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableMemory.getAndSetLong(1, 1L);
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testCompareAndSwapLong() {
-    writableMemory.compareAndSwapLong(0, 0L, 1L);
-    try {
-      writableMemory.compareAndSwapLong(1, 0L, 1L);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableMemory.compareAndSwapLong(1, 0L, 1L);
   }
 }
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BufferInvariantsTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BufferInvariantsTest.java
index e5256f1..acc7f79 100644
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BufferInvariantsTest.java
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BufferInvariantsTest.java
@@ -25,8 +25,8 @@ import static org.testng.Assert.fail;
 import java.nio.ByteBuffer;
 
 import org.apache.datasketches.memory.Buffer;
+import org.apache.datasketches.memory.BufferPositionInvariantsException;
 import org.apache.datasketches.memory.WritableBuffer;
-import org.apache.datasketches.memory.WritableHandle;
 import org.apache.datasketches.memory.WritableMemory;
 import org.testng.annotations.Test;
 
@@ -161,15 +161,14 @@ public class BufferInvariantsTest {
 
   @Test
   public void checkLimitsDirect() throws Exception {
-    try (WritableHandle hand = WritableMemory.allocateDirect(100)) {
-      WritableMemory wmem = hand.getWritable();
+    try (WritableMemory wmem = WritableMemory.allocateDirect(100)) {
       Buffer buf = wmem.asBuffer();
       buf.setStartPositionEnd(40, 45, 50);
       buf.setStartPositionEnd(0, 0, 100);
       try {
         buf.setStartPositionEnd(0, 0, 101);
         fail();
-      } catch (AssertionError e) {
+      } catch (BufferPositionInvariantsException e) {
         //ok
       }
     }
@@ -232,8 +231,7 @@ public class BufferInvariantsTest {
   @Test
   public void testBufDirect() throws Exception {
     int n = 25;
-    try (WritableHandle whand = WritableMemory.allocateDirect(n)) {
-    WritableMemory wmem = whand.getWritable();
+    try (WritableMemory wmem = WritableMemory.allocateDirect(n)) {
     WritableBuffer buf = wmem.asWritableBuffer();
     for (byte i = 0; i < n; i++) { buf.putByte(i); }
     buf.setPosition(0);
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BufferReadWriteSafetyTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BufferReadWriteSafetyTest.java
index 6f9f62a..73a9da2 100644
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BufferReadWriteSafetyTest.java
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/BufferReadWriteSafetyTest.java
@@ -33,82 +33,82 @@ public class BufferReadWriteSafetyTest {
 
   private final WritableBuffer buf = (WritableBuffer) Buffer.wrap(ByteBuffer.allocate(8));
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testPutByte() {
     buf.putByte(0, (byte) 1);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testPutBytePositional() {
     buf.putByte((byte) 1);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testPutBoolean() {
     buf.putBoolean(0, true);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testPutBooleanPositional() {
     buf.putBoolean(true);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testPutShort() {
     buf.putShort(0, (short) 1);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testPutShortPositional() {
     buf.putShort((short) 1);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testPutChar() {
     buf.putChar(0, (char) 1);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testPutCharPositional() {
     buf.putChar((char) 1);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testPutInt() {
     buf.putInt(0, 1);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testPutIntPositional() {
     buf.putInt(1);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testPutLong() {
     buf.putLong(0, 1);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testPutLongPositional() {
     buf.putLong(1);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testPutFloat() {
     buf.putFloat(0, 1);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testPutFloatPositional() {
     buf.putFloat(1);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testPutDouble() {
     buf.putDouble(0, 1);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testPutDoublePositional() {
     buf.putDouble(1);
   }
@@ -155,19 +155,19 @@ public class BufferReadWriteSafetyTest {
 
   // Now, test that various ways to obtain a read-only buffer produce a read-only buffer indeed
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testWritableMemoryAsBuffer() {
     WritableBuffer buf1 = (WritableBuffer) WritableMemory.allocate(8).asBuffer();
     buf1.putInt(1);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testWritableBufferRegion() {
     WritableBuffer buf1 = (WritableBuffer) WritableMemory.allocate(8).asWritableBuffer().region();
     buf1.putInt(1);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testWritableBufferDuplicate() {
     WritableBuffer buf1 = (WritableBuffer) WritableMemory.allocate(8).asWritableBuffer().duplicate();
     buf1.putInt(1);
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 3242cf1..ae05e43 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
@@ -26,9 +26,10 @@ import java.nio.ByteOrder;
 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.WritableHandle;
 import org.apache.datasketches.memory.WritableMemory;
 import org.testng.annotations.Test;
 import org.testng.collections.Lists;
@@ -38,8 +39,7 @@ public class BufferTest {
   @Test
   public void checkDirectRoundTrip() throws Exception {
     int n = 1024; //longs
-    try (WritableHandle wh = WritableMemory.allocateDirect(n * 8)) {
-      WritableMemory wmem = wh.getWritable();
+    try (WritableMemory wmem = WritableMemory.allocateDirect(n * 8)) {
       WritableBuffer wbuf = wmem.asWritableBuffer();
       for (int i = 0; i < n; i++) {
         wbuf.putLong(i);
@@ -276,36 +276,34 @@ public class BufferTest {
     wbuf.resetPosition();
     for (int i = 0; i < n; i++) {
       println("" + wbuf.getLong(i * 8));
-      assertEquals(wbuf.getLong(), i % 8); //fail got 1 not 0
+      assertEquals(wbuf.getLong(), i % 8);
     }
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = MemoryInvalidException.class)
   public void checkParentUseAfterFree() throws Exception {
     int bytes = 64 * 8;
-    WritableHandle wh = WritableMemory.allocateDirect(bytes);
-    WritableMemory wmem = wh.getWritable();
+    WritableMemory wmem = WritableMemory.allocateDirect(bytes);
     WritableBuffer wbuf = wmem.asWritableBuffer();
-    wh.close();
+    wmem.close();
     //with -ea assert: Memory not valid.
     //with -da sometimes segfaults, sometimes passes!
     wbuf.getLong();
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = MemoryInvalidException.class)
   public void checkRegionUseAfterFree() throws Exception {
     int bytes = 64;
-    WritableHandle wh = WritableMemory.allocateDirect(bytes);
-    Memory wmem = wh.get();
+    WritableMemory wmem = WritableMemory.allocateDirect(bytes);
 
     Buffer reg = wmem.asBuffer().region();
-    wh.close();
+    wmem.close();
     //with -ea assert: Memory not valid.
     //with -da sometimes segfaults, sometimes passes!
     reg.getByte();
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = BufferPositionInvariantsException.class)
   public void checkBaseBufferInvariants() {
     WritableBuffer wbuf = WritableMemory.allocate(64).asWritableBuffer();
     wbuf.setStartPositionEnd(1, 0, 2); //out of order
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CommonBufferTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CommonBufferTest.java
index 14d8566..3cbe87d 100644
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CommonBufferTest.java
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CommonBufferTest.java
@@ -22,7 +22,6 @@ package org.apache.datasketches.memory.internal;
 import static org.testng.Assert.assertEquals;
 
 import org.apache.datasketches.memory.WritableBuffer;
-import org.apache.datasketches.memory.WritableHandle;
 import org.apache.datasketches.memory.WritableMemory;
 import org.testng.annotations.Test;
 
@@ -31,8 +30,7 @@ public class CommonBufferTest {
   @Test
   public void checkSetGet() throws Exception {
     int memCapacity = 60; //must be at least 60
-    try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem = wrh.getWritable();
+    try (WritableMemory mem = WritableMemory.allocateDirect(memCapacity)) {
       WritableBuffer buf = mem.asWritableBuffer();
       assertEquals(buf.getCapacity(), memCapacity);
       setGetTests(buf);
@@ -133,8 +131,7 @@ public class CommonBufferTest {
   @Test
   public void checkSetGetArrays() throws Exception {
     int memCapacity = 32;
-    try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem = wrh.getWritable();
+    try (WritableMemory mem = WritableMemory.allocateDirect(memCapacity)) {
       WritableBuffer buf = mem.asWritableBuffer();
       assertEquals(buf.getCapacity(), memCapacity);
       setGetArraysTests(buf);
@@ -230,8 +227,7 @@ public class CommonBufferTest {
   @Test
   public void checkSetGetPartialArraysWithOffset() throws Exception {
     int memCapacity = 32;
-    try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem = wrh.getWritable();
+    try (WritableMemory mem = WritableMemory.allocateDirect(memCapacity)) {
       WritableBuffer buf = mem.asWritableBuffer();
       assertEquals(buf.getCapacity(), memCapacity);
       setGetPartialArraysWithOffsetTests(buf);
@@ -324,11 +320,9 @@ public class CommonBufferTest {
   @Test
   public void checkSetClearMemoryRegions() throws Exception {
     int memCapacity = 64; //must be 64
-    try (WritableHandle wrh1 = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem = wrh1.getWritable();
+    try (WritableMemory mem = WritableMemory.allocateDirect(memCapacity)) {
       WritableBuffer buf = mem.asWritableBuffer();
       assertEquals(buf.getCapacity(), memCapacity);
-
       setClearMemoryRegionsTests(buf); //requires println enabled to visually check
       buf.resetPosition();
       for (int i = 0; i < memCapacity; i++) {
@@ -413,8 +407,7 @@ public class CommonBufferTest {
   @Test
   public void checkToHexStringAllMem() throws Exception {
     int memCapacity = 48; //must be 48
-    try (WritableHandle wrh1 = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem = wrh1.getWritable();
+    try (WritableMemory mem = WritableMemory.allocateDirect(memCapacity)) {
       WritableBuffer buf = mem.asWritableBuffer();
       assertEquals(buf.getCapacity(), memCapacity);
       toHexStringAllMemTests(buf); //requires println enabled to visually check
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CommonMemoryTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CommonMemoryTest.java
index 695c688..dbac94a 100644
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CommonMemoryTest.java
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CommonMemoryTest.java
@@ -27,7 +27,6 @@ import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertTrue;
 
-import org.apache.datasketches.memory.WritableHandle;
 import org.apache.datasketches.memory.WritableMemory;
 import org.testng.annotations.Test;
 
@@ -36,8 +35,7 @@ public class CommonMemoryTest {
   @Test
   public void checkSetGet() throws Exception {
     int memCapacity = 16; //must be at least 8
-    try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem = wrh.getWritable();
+    try (WritableMemory mem = WritableMemory.allocateDirect(memCapacity)) {
       assertEquals(mem.getCapacity(), memCapacity);
       setGetTests(mem);
     }
@@ -88,8 +86,7 @@ public class CommonMemoryTest {
   @Test
   public void checkSetGetArrays() throws Exception {
     int memCapacity = 32;
-    try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem = wrh.getWritable();
+    try (WritableMemory mem = WritableMemory.allocateDirect(memCapacity)) {
       assertEquals(memCapacity, mem.getCapacity());
       setGetArraysTests(mem);
     }
@@ -168,8 +165,7 @@ public class CommonMemoryTest {
   @Test
   public void checkSetGetPartialArraysWithOffset() throws Exception {
     int memCapacity = 32;
-    try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem = wrh.getWritable();
+    try (WritableMemory mem = WritableMemory.allocateDirect(memCapacity)) {
       assertEquals(memCapacity, mem.getCapacity());
       setGetPartialArraysWithOffsetTests(mem);
     }
@@ -245,8 +241,7 @@ public class CommonMemoryTest {
   @Test
   public void checkSetClearIsBits() throws Exception {
     int memCapacity = 8;
-    try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem = wrh.getWritable();
+    try (WritableMemory mem = WritableMemory.allocateDirect(memCapacity)) {
       assertEquals(memCapacity, mem.getCapacity());
       mem.clear();
       setClearIsBitsTests(mem);
@@ -286,8 +281,7 @@ public class CommonMemoryTest {
   @Test
   public void checkAtomicMethods() throws Exception {
     int memCapacity = 8;
-    try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem = wrh.getWritable();
+    try (WritableMemory mem = WritableMemory.allocateDirect(memCapacity)) {
       assertEquals(mem.getCapacity(), memCapacity);
       atomicMethodTests(mem);
     }
@@ -313,9 +307,7 @@ public class CommonMemoryTest {
   @Test
   public void checkSetClearMemoryRegions() throws Exception {
     int memCapacity = 64; //must be 64
-    try (WritableHandle wrh1 = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem = wrh1.getWritable();
-
+    try (WritableMemory mem = WritableMemory.allocateDirect(memCapacity)) {
       setClearMemoryRegionsTests(mem); //requires println enabled to visually check
       for (int i = 0; i < memCapacity; i++) {
         assertEquals(mem.getByte(i), 0);
@@ -323,7 +315,7 @@ public class CommonMemoryTest {
     }
   }
 
-  //enable println stmts to visually check
+  //enable println statements to visually check
   public static void setClearMemoryRegionsTests(WritableMemory mem) {
     int accessCapacity = (int)mem.getCapacity();
 
@@ -384,8 +376,7 @@ public class CommonMemoryTest {
   @Test
   public void checkToHexStringAllMem() throws Exception {
     int memCapacity = 48; //must be 48
-    try (WritableHandle wrh1 = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem = wrh1.getWritable();
+    try (WritableMemory mem = WritableMemory.allocateDirect(memCapacity)) {
       toHexStringAllMemTests(mem); //requires println enabled to visually check
     }
   }
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CopyMemoryOverlapTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CopyMemoryOverlapTest.java
index 9b30a42..9529c1a 100644
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CopyMemoryOverlapTest.java
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CopyMemoryOverlapTest.java
@@ -22,7 +22,6 @@ package org.apache.datasketches.memory.internal;
 import static org.testng.Assert.assertEquals;
 
 import org.apache.datasketches.memory.Memory;
-import org.apache.datasketches.memory.WritableHandle;
 import org.apache.datasketches.memory.WritableMemory;
 import org.testng.annotations.Test;
 
@@ -92,8 +91,7 @@ public class CopyMemoryOverlapTest {
     println("CopyUp       : " + copyUp);
     println("Backing longs: " + backingLongs + "\t bytes: " + backingBytes);
 
-    try (WritableHandle backHandle = WritableMemory.allocateDirect(backingBytes)) {
-      WritableMemory backingMem = backHandle.getWritable();
+    try (WritableMemory backingMem = WritableMemory.allocateDirect(backingBytes)) {
       fill(backingMem); //fill mem with 0 thru copyLongs -1
       //listMem(backingMem, "Original");
       backingMem.copyTo(fromOffsetBytes, backingMem, toOffsetBytes, copyBytes);
@@ -132,8 +130,7 @@ public class CopyMemoryOverlapTest {
     println("CopyUp       : " + copyUp);
     println("Backing longs: " + backingLongs + "\t bytes: " + backingBytes);
 
-    try (WritableHandle backHandle = WritableMemory.allocateDirect(backingBytes)) {
-      WritableMemory backingMem = backHandle.getWritable();
+    try (WritableMemory backingMem = WritableMemory.allocateDirect(backingBytes)) {
       fill(backingMem); //fill mem with 0 thru copyLongs -1
       //listMem(backingMem, "Original");
       WritableMemory reg1 = backingMem.writableRegion(fromOffsetBytes, copyBytes);
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CopyMemoryTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CopyMemoryTest.java
index ab40139..3de76d7 100644
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CopyMemoryTest.java
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/CopyMemoryTest.java
@@ -25,7 +25,6 @@ import static org.testng.Assert.assertEquals;
 import java.util.concurrent.ThreadLocalRandom;
 
 import org.apache.datasketches.memory.Memory;
-import org.apache.datasketches.memory.WritableHandle;
 import org.apache.datasketches.memory.WritableMemory;
 import org.testng.Assert;
 import org.testng.annotations.Test;
@@ -58,8 +57,7 @@ public class CopyMemoryTest {
   public void directWSource() throws Exception {
     int k1 = 1 << 20; //longs
     int k2 = 2 * k1;
-    try (WritableHandle wrh = genWRH(k1, false)) {
-      WritableMemory srcMem = wrh.getWritable();
+    try (WritableMemory srcMem = genWRH(k1, false)) {
       WritableMemory dstMem = genMem(k2, true);
       srcMem.copyTo(0, dstMem, k1 << 3, k1 << 3);
       check(dstMem, k1, k1, 1);
@@ -70,8 +68,7 @@ public class CopyMemoryTest {
   public void directROSource() throws Exception {
     int k1 = 1 << 20; //longs
     int k2 = 2 * k1;
-    try (WritableHandle wrh = genWRH(k1, false)) {
-      Memory srcMem = wrh.get();
+    try (Memory srcMem = genWRH(k1, false)) {
       WritableMemory dstMem = genMem(k2, true);
       srcMem.copyTo(0, dstMem, k1 << 3, k1 << 3);
       check(dstMem, k1, k1, 1);
@@ -107,8 +104,7 @@ public class CopyMemoryTest {
   public void directROSrcRegion() throws Exception {
     int k1 = 1 << 20; //longs
     //gen baseMem of k1 longs w data, direct
-    try (WritableHandle wrh = genWRH(k1, false)) {
-      Memory baseMem = wrh.get();
+    try (Memory baseMem = genWRH(k1, false)) {
       //gen src region of k1/2 longs, off= k1/2
       Memory srcReg = baseMem.region((k1 / 2) << 3, (k1 / 2) << 3);
       WritableMemory dstMem = genMem(2 * k1, true); //empty
@@ -150,15 +146,14 @@ public class CopyMemoryTest {
     }
   }
 
-  private static WritableHandle genWRH(int longs, boolean empty) {
-    WritableHandle wrh = WritableMemory.allocateDirect(longs << 3);
-    WritableMemory mem = wrh.getWritable();
+  private static WritableMemory genWRH(int longs, boolean empty) {
+    WritableMemory mem = WritableMemory.allocateDirect(longs << 3);
     if (empty) {
       mem.clear();
     } else {
       for (int i = 0; i < longs; i++) { mem.putLong(i << 3, i + 1); }
     }
-    return wrh;
+    return mem;
   }
 
   private static WritableMemory genMem(int longs, boolean empty) {
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/DruidIssue11544Test.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/DruidIssue11544Test.java
index 66e88d7..6862bec 100644
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/DruidIssue11544Test.java
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/DruidIssue11544Test.java
@@ -61,7 +61,7 @@ public class DruidIssue11544Test {
 
     //Wrap bb into WritableMemory
     WritableMemory mem1 = WritableMemory.writableWrap(bb);
-    assertTrue(mem1.isDirect()); //confirm mem1 is off-heap
+    assertTrue(mem1.isDirectResource()); //confirm mem1 is off-heap
 
     //Acquire the DefaultMemoryRequestServer
     //NOTE: it is a policy decision to allow the DefaultMemoryServer to be set as a default.
@@ -77,7 +77,7 @@ public class DruidIssue11544Test {
     WritableMemory mem2 = svr.request(mem1, size2);
 
     //Confirm that mem2 is on the heap (the default) and 2X size1
-    assertFalse(mem2.isDirect());
+    assertFalse(mem2.isDirectResource());
     assertEquals(mem2.getCapacity(), size2);
 
     //Move data to new memory
@@ -94,7 +94,7 @@ public class DruidIssue11544Test {
     WritableMemory mem3 = svr.request(mem2, size3);
 
     //Confirm that mem3 is still on the heap and 2X of size2
-    assertFalse(mem3.isDirect());
+    assertFalse(mem3.isDirectResource());
     assertEquals(mem3.getCapacity(), size3);
 
     //Move data to new memory
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/ExampleMemoryRequestServerTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/ExampleMemoryRequestServerTest.java
deleted file mode 100644
index 9f0256b..0000000
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/ExampleMemoryRequestServerTest.java
+++ /dev/null
@@ -1,177 +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.assertFalse;
-
-import java.nio.ByteOrder;
-import java.util.IdentityHashMap;
-
-import org.apache.datasketches.memory.MemoryRequestServer;
-import org.apache.datasketches.memory.WritableHandle;
-import org.apache.datasketches.memory.WritableMemory;
-import org.testng.annotations.Test;
-
-/**
- * Examples of how to use the MemoryRequestServer with a memory hungry client.
- * @author Lee Rhodes
- */
-public class ExampleMemoryRequestServerTest {
-
-  /**
-   * This version is without a TWR block.all of the memory allocations are done through the MemoryRequestServer
-   * and each is closed by the MemoryClient when it is done with each.
-   * @throws Exception  thrown by automatic close() invocation on WritableHandle.
-   */
-  @Test
-  public void checkExampleMemoryRequestServer1() throws Exception {
-    int bytes = 8;
-    ExampleMemoryRequestServer svr = new ExampleMemoryRequestServer();
-    try (WritableHandle wh = WritableMemory.allocateDirect(8)) {
-      WritableMemory memStart = wh.getWritable();
-      WritableMemory wMem = svr.request(memStart, bytes);
-      MemoryClient client = new MemoryClient(wMem);
-      client.process();
-      svr.cleanup();
-    }
-  }
-
-  /**
-   * In this version the first memory allocation is done up front in a TWR block.
-   * And then the MemoryClient allocates new memories as needed, which are then closed
-   * by the MemoryClient when it is done with the new memory allocations.
-   * The initial allocation stays open until the end where it is closed at the end of the
-   * TWR scope.
-   * @throws Exception thrown by automatic close() invocation on WritableHandle.
-   */
-  @Test
-  public void checkExampleMemoryRequestServer2() throws Exception {
-    int bytes = 8;
-    ExampleMemoryRequestServer svr = new ExampleMemoryRequestServer();
-    try (WritableHandle handle = WritableMemory.allocateDirect(bytes, ByteOrder.nativeOrder(), svr)) {
-      WritableMemory memStart = handle.getWritable();
-      MemoryClient client = new MemoryClient(memStart);
-      client.process();
-      svr.cleanup(); //just to be sure all are closed.
-    }
-  }
-
-  @Test(expectedExceptions = IllegalArgumentException.class)
-  public void checkZeroCapacity() throws Exception {
-    ExampleMemoryRequestServer svr = new ExampleMemoryRequestServer();
-    try (WritableHandle wh = WritableMemory.allocateDirect(0, ByteOrder.nativeOrder(), svr)) {
-      //empty
-    }
-  }
-
-  /**
-   * This little client is never happy with how much memory it has been allocated and keeps
-   * requesting for more. When it does ask for more, it must copy its old data into the new
-   * memory, release the prior memory, and then continue working from there.
-   *
-   * <p>In reality, these memory requests should be quite rare.</p>
-   */
-  static class MemoryClient {
-    WritableMemory smallMem;
-    MemoryRequestServer svr;
-
-    MemoryClient(WritableMemory memStart) {
-      smallMem = memStart;
-      svr = memStart.getMemoryRequestServer();
-    }
-
-    void process() {
-      long cap1 = smallMem.getCapacity();
-      smallMem.fill((byte) 1);                //fill it, but not big enough
-      println(smallMem.toHexString("Small", 0, (int)cap1));
-
-      WritableMemory bigMem = svr.request(smallMem, 2 * cap1); //get bigger mem
-      long cap2 = bigMem.getCapacity();
-      smallMem.copyTo(0, bigMem, 0, cap1);    //copy data from small to big
-      svr.requestClose(smallMem, bigMem);     //done with smallMem, release it
-
-      bigMem.fill(cap1, cap1, (byte) 2);      //fill the rest of bigMem, still not big enough
-      println(bigMem.toHexString("Big", 0, (int)cap2));
-
-      WritableMemory giantMem = svr.request(bigMem, 2 * cap2); //get giant mem
-      long cap3 = giantMem.getCapacity();
-      bigMem.copyTo(0, giantMem, 0, cap2);    //copy data from small to big
-      svr.requestClose(bigMem, giantMem);     //done with bigMem, release it
-
-      giantMem.fill(cap2, cap2, (byte) 3);    //fill the rest of giantMem
-      println(giantMem.toHexString("Giant", 0, (int)cap3));
-      svr.requestClose(giantMem, null);                 //done with giantMem, release it
-    }
-  }
-
-  /**
-   * This example MemoryRequestServer is simplistic but demonstrates one of many ways to
-   * possibly manage the continuous requests for larger memory and to track the associations between
-   * handles and their associated memory.
-   */
-  public static class ExampleMemoryRequestServer implements MemoryRequestServer {
-    IdentityHashMap<WritableMemory, WritableHandle> map = new IdentityHashMap<>();
-
-    @Override
-    public WritableMemory request(WritableMemory currentWMem, long capacityBytes) {
-     ByteOrder order = currentWMem.getByteOrder();
-     WritableHandle handle = WritableMemory.allocateDirect(capacityBytes, order, this);
-     WritableMemory wmem = handle.getWritable();
-     map.put(wmem, handle); //We track the newly allocated memory and its handle.
-     return wmem;
-    }
-
-    @Override
-    //here we actually release it, in reality it might be a lot more complex.
-    public void requestClose(WritableMemory memToRelease, WritableMemory newMemory) {
-      WritableHandle handle = map.get(memToRelease);
-      if (handle != null && handle.getWritable() == memToRelease) {
-        try {
-          handle.close();
-        } catch (Exception e) {
-          throw new RuntimeException(e);
-        }
-      }
-    }
-
-    public void cleanup() {
-      map.forEach((k,v) -> {
-        assertFalse(k.isValid()); //all entries in the map should be invalid
-        try {
-          v.close();
-        } catch (Exception e) {
-          throw new RuntimeException(e);
-        }
-      });
-    }
-  }
-
-  @Test
-  public void printlnTest() {
-    println("PRINTING: " + this.getClass().getName());
-  }
-
-  /**
-   * @param s value to print
-   */
-  static void println(String s) {
-    //System.out.println(s); //disable here
-  }
-}
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/IgnoredArrayOverflowTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/IgnoredArrayOverflowTest.java
index d9e0773..842cab2 100644
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/IgnoredArrayOverflowTest.java
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/IgnoredArrayOverflowTest.java
@@ -19,7 +19,6 @@
 
 package org.apache.datasketches.memory.internal;
 
-import org.apache.datasketches.memory.WritableHandle;
 import org.apache.datasketches.memory.WritableMemory;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
@@ -27,19 +26,17 @@ import org.testng.annotations.Test;
 
 public class IgnoredArrayOverflowTest {
 
-  private WritableHandle h;
   private WritableMemory memory;
-  private static final long MAX_SIZE = (1L << 10); // use 1L << 31 to test int overrange
+  private static final long MAX_SIZE = (1L << 10); // use 1L << 31 to test int over range
 
   @BeforeClass
   public void allocate() {
-    h = WritableMemory.allocateDirect(MAX_SIZE);
-    memory = h.getWritable();
+    memory = WritableMemory.allocateDirect(MAX_SIZE);
   }
 
   @AfterClass
-  public void close() throws Exception {
-    h.close();
+  public void close() {
+    memory.close();
   }
 
   @Test
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 01e9577..5dad4ec 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
@@ -34,8 +34,6 @@ import java.nio.ByteOrder;
 
 import org.apache.datasketches.memory.MemoryRequestServer;
 import org.apache.datasketches.memory.WritableBuffer;
-import org.apache.datasketches.memory.WritableHandle;
-import org.apache.datasketches.memory.WritableMapHandle;
 import org.apache.datasketches.memory.WritableMemory;
 import org.testng.annotations.Test;
 
@@ -61,20 +59,18 @@ public class LeafImplTest {
     long off = 0;
     long cap = 128;
     // Off Heap, Native order, No ByteBuffer, has MemReqSvr
-    try (WritableHandle wdh = WritableMemory.allocateDirect(cap, NBO, dummyMemReqSvr)) {
-      WritableMemory memNO = wdh.getWritable();
+    try (WritableMemory memNO = WritableMemory.allocateDirect(cap, NBO, dummyMemReqSvr)) {
       memNO.putShort(0, (short) 1);
       assertNull(((ResourceImpl)memNO).getUnsafeObject());
-      assertTrue(memNO.isDirect());
-      checkCombinations(memNO, off, cap, memNO.isDirect(), NBO, false, true);
+      assertTrue(memNO.isDirectResource());
+      checkCombinations(memNO, off, cap, memNO.isDirectResource(), NBO, false, true);
     }
     // Off Heap, Non Native order, No ByteBuffer, has MemReqSvr
-    try (WritableHandle wdh = WritableMemory.allocateDirect(cap, NNBO, dummyMemReqSvr)) {
-      WritableMemory memNNO = wdh.getWritable();
+    try (WritableMemory memNNO = WritableMemory.allocateDirect(cap, NNBO, dummyMemReqSvr)) {
       memNNO.putShort(0, (short) 1);
       assertNull(((ResourceImpl)memNNO).getUnsafeObject());
-      assertTrue(memNNO.isDirect());
-      checkCombinations(memNNO, off, cap, memNNO.isDirect(), NNBO, false, true);
+      assertTrue(memNNO.isDirectResource());
+      checkCombinations(memNNO, off, cap, memNNO.isDirectResource(), NNBO, false, true);
     }
   }
 
@@ -87,36 +83,36 @@ public class LeafImplTest {
     bb.order(NBO);
     bb.putShort(0, (short) 1);
     WritableMemory mem = WritableMemory.writableWrap(bb, NBO, dummyMemReqSvr);
-    assertEquals(bb.isDirect(), mem.isDirect());
+    assertEquals(bb.isDirect(), mem.isDirectResource());
     assertNotNull(((ResourceImpl)mem).getUnsafeObject());
-    checkCombinations(mem, off, cap, mem.isDirect(), mem.getByteOrder(), true, true);
+    checkCombinations(mem, off, cap, mem.isDirectResource(), mem.getByteOrder(), true, true);
 
     //BB off heap, native order, has ByteBuffer, has MemReqSvr
     ByteBuffer dbb = ByteBuffer.allocateDirect((int)cap);
     dbb.order(NBO);
     dbb.putShort(0, (short) 1);
     mem = WritableMemory.writableWrap(dbb, NBO, dummyMemReqSvr);
-    assertEquals(dbb.isDirect(), mem.isDirect());
+    assertEquals(dbb.isDirect(), mem.isDirectResource());
     assertNull(((ResourceImpl)mem).getUnsafeObject());
-    checkCombinations(mem, off, cap,  mem.isDirect(), mem.getByteOrder(), true, true);
+    checkCombinations(mem, off, cap,  mem.isDirectResource(), mem.getByteOrder(), true, true);
 
     //BB on heap, non native order, has ByteBuffer, has MemReqSvr
     bb = ByteBuffer.allocate((int)cap);
     bb.order(NNBO);
     bb.putShort(0, (short) 1);
     mem = WritableMemory.writableWrap(bb, NNBO, dummyMemReqSvr);
-    assertEquals(bb.isDirect(), mem.isDirect());
+    assertEquals(bb.isDirect(), mem.isDirectResource());
     assertNotNull(((ResourceImpl)mem).getUnsafeObject());
-    checkCombinations(mem, off, cap, mem.isDirect(), mem.getByteOrder(), true, true);
+    checkCombinations(mem, off, cap, mem.isDirectResource(), mem.getByteOrder(), true, true);
 
     //BB off heap, non native order, has ByteBuffer, has MemReqSvr
     dbb = ByteBuffer.allocateDirect((int)cap);
     dbb.order(NNBO);
     dbb.putShort(0, (short) 1);
     mem = WritableMemory.writableWrap(dbb, NNBO, dummyMemReqSvr);
-    assertEquals(dbb.isDirect(), mem.isDirect());
+    assertEquals(dbb.isDirect(), mem.isDirectResource());
     assertNull(((ResourceImpl)mem).getUnsafeObject());
-    checkCombinations(mem, off, cap,  mem.isDirect(), mem.getByteOrder(), true, true);
+    checkCombinations(mem, off, cap,  mem.isDirectResource(), mem.getByteOrder(), true, true);
   }
 
   @Test
@@ -136,20 +132,18 @@ public class LeafImplTest {
     assertTrue(file.isFile());
     file.deleteOnExit();  //comment out if you want to examine the file.
     // Off Heap, Native order, No ByteBuffer, No MemReqSvr
-    try (WritableMapHandle wmh = WritableMemory.writableMap(file, off, cap, NBO)) {
-      WritableMemory memNO = wmh.getWritable();
+    try (WritableMemory memNO = WritableMemory.writableMap(file, off, cap, NBO)) {
       memNO.putShort(0, (short) 1);
       assertNull(((ResourceImpl)memNO).getUnsafeObject());
-      assertTrue(memNO.isDirect());
-      checkCombinations(memNO, off, cap, memNO.isDirect(), NBO, false, false);
+      assertTrue(memNO.isDirectResource());
+      checkCombinations(memNO, off, cap, memNO.isDirectResource(), NBO, false, false);
     }
     // Off heap, Non Native order, No ByteBuffer, no MemReqSvr
-    try (WritableMapHandle wmh = WritableMemory.writableMap(file, off, cap, NNBO)) {
-      WritableMemory memNNO = wmh.getWritable();
+    try (WritableMemory memNNO = WritableMemory.writableMap(file, off, cap, NNBO)) {
       memNNO.putShort(0, (short) 1);
       assertNull(((ResourceImpl)memNNO).getUnsafeObject());
-      assertTrue(memNNO.isDirect());
-      checkCombinations(memNNO, off, cap, memNNO.isDirect(), NNBO, false, false);
+      assertTrue(memNNO.isDirectResource());
+      checkCombinations(memNNO, off, cap, memNNO.isDirectResource(), NNBO, false, false);
     }
   }
 
@@ -161,14 +155,14 @@ public class LeafImplTest {
     WritableMemory memNO = WritableMemory.allocate((int)cap); //assumes NBO
     memNO.putShort(0, (short) 1);
     assertNotNull(((ResourceImpl)memNO).getUnsafeObject());
-    assertFalse(memNO.isDirect());
-    checkCombinations(memNO, off, cap, memNO.isDirect(), NBO, false, false);
+    assertFalse(memNO.isDirectResource());
+    checkCombinations(memNO, off, cap, memNO.isDirectResource(), NBO, false, false);
     // On Heap, Non-native order, No ByteBuffer, No MemReqSvr
     WritableMemory memNNO = WritableMemory.allocate((int)cap, NNBO);
     memNNO.putShort(0, (short) 1);
     assertNotNull(((ResourceImpl)memNNO).getUnsafeObject());
-    assertFalse(memNNO.isDirect());
-    checkCombinations(memNNO, off, cap, memNNO.isDirect(), NNBO, false, false);
+    assertFalse(memNNO.isDirectResource());
+    checkCombinations(memNNO, off, cap, memNNO.isDirectResource(), NNBO, false, false);
   }
 
   private static void checkCombinations(WritableMemory mem, long off, long cap,
@@ -191,11 +185,11 @@ public class LeafImplTest {
 
     Object obj = ((ResourceImpl)mem).getUnsafeObject();
     if (direct) {
-      assertTrue(mem.isDirect());
+      assertTrue(mem.isDirectResource());
       assertNull(obj);
       assertTrue(((ResourceImpl)mem).getNativeBaseOffset() != 0);
     } else {
-      assertFalse(mem.isDirect());
+      assertFalse(mem.isDirectResource());
       assertNotNull(obj);
       assertTrue(((ResourceImpl)mem).getNativeBaseOffset() == 0);
     }
@@ -220,11 +214,11 @@ public class LeafImplTest {
 
     obj = ((ResourceImpl)buf).getUnsafeObject();
     if (direct) {
-      assertTrue(buf.isDirect());
+      assertTrue(buf.isDirectResource());
       assertNull(obj);
       assertTrue(((ResourceImpl)buf).getNativeBaseOffset() != 0);
     } else {
-      assertFalse(buf.isDirect());
+      assertFalse(buf.isDirectResource());
       assertNotNull(obj);
       assertTrue(((ResourceImpl)buf).getNativeBaseOffset() == 0);
     }
@@ -247,11 +241,11 @@ public class LeafImplTest {
 
     obj = ((ResourceImpl)nnMem).getUnsafeObject();
     if (direct) {
-      assertTrue(nnMem.isDirect());
+      assertTrue(nnMem.isDirectResource());
       assertNull(obj);
       assertTrue(((ResourceImpl)nnMem).getNativeBaseOffset() != 0);
     } else {
-      assertFalse(nnMem.isDirect());
+      assertFalse(nnMem.isDirectResource());
       assertNotNull(obj);
       assertTrue(((ResourceImpl)nnMem).getNativeBaseOffset() == 0);
     }
@@ -274,11 +268,11 @@ public class LeafImplTest {
 
     obj = ((ResourceImpl)nnBuf).getUnsafeObject();
     if (direct) {
-      assertTrue(nnBuf.isDirect());
+      assertTrue(nnBuf.isDirectResource());
       assertNull(obj);
       assertTrue(((ResourceImpl)nnBuf).getNativeBaseOffset() != 0);
     } else {
-      assertFalse(nnBuf.isDirect());
+      assertFalse(nnBuf.isDirectResource());
       assertNotNull(obj);
       assertTrue(((ResourceImpl)nnBuf).getNativeBaseOffset() == 0);
     }
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryBoundaryCheckTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryBoundaryCheckTest.java
index 1362f44..7ddf404 100644
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryBoundaryCheckTest.java
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryBoundaryCheckTest.java
@@ -19,6 +19,7 @@
 
 package org.apache.datasketches.memory.internal;
 
+import org.apache.datasketches.memory.MemoryBoundsException;
 import org.apache.datasketches.memory.WritableBuffer;
 import org.apache.datasketches.memory.WritableMemory;
 import org.testng.annotations.Test;
@@ -27,179 +28,83 @@ public class MemoryBoundaryCheckTest {
 
   private final WritableBuffer writableBuffer = WritableMemory.allocate(8).asWritableBuffer();
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testGetBoolean() {
-    writableBuffer.getBoolean(7);
-    try {
-      writableBuffer.getBoolean(8);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableBuffer.getBoolean(8);
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testPutBoolean() {
-    writableBuffer.putBoolean(7, true);
-    try {
-      writableBuffer.putBoolean(8, true);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableBuffer.putBoolean(8, true);
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testGetByte() {
-    writableBuffer.getByte(7);
-    try {
-      writableBuffer.getByte(8);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableBuffer.getByte(8);
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testPutByte() {
-    writableBuffer.putByte(7, (byte) 1);
-    try {
-      writableBuffer.putByte(8, (byte) 1);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableBuffer.putByte(8, (byte) 1);
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testGetChar() {
-    writableBuffer.getChar(6);
-    try {
-      writableBuffer.getChar(7);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableBuffer.getChar(7);
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testPutChar() {
-    writableBuffer.putChar(6, 'a');
-    try {
-      writableBuffer.putChar(7, 'a');
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableBuffer.putChar(7, 'a');
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testGetShort() {
-    writableBuffer.getShort(6);
-    try {
-      writableBuffer.getShort(7);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableBuffer.getShort(7);
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testPutShort() {
-    writableBuffer.putShort(6, (short) 1);
-    try {
-      writableBuffer.putShort(7, (short) 1);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableBuffer.putShort(7, (short) 1);
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testGetInt() {
-    writableBuffer.getInt(4);
-    try {
-      writableBuffer.getInt(5);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableBuffer.getInt(5);
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testPutInt() {
-    writableBuffer.putInt(4, 1);
-    try {
-      writableBuffer.putInt(5, 1);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableBuffer.putInt(5, 1);
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testGetFloat() {
-    writableBuffer.getFloat(4);
-    try {
-      writableBuffer.getFloat(5);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableBuffer.getFloat(5);
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testPutFloat() {
-    writableBuffer.putFloat(4, 1f);
-    try {
-      writableBuffer.putFloat(5, 1f);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableBuffer.putFloat(5, 1f);
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testGetLong() {
-    writableBuffer.getLong(0);
-    try {
-      writableBuffer.getLong(1);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableBuffer.getLong(1);
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testPutLong() {
-    writableBuffer.putLong(0, 1L);
-    try {
-      writableBuffer.putLong(1, 1L);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableBuffer.putLong(1, 1L);
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testGetDouble() {
-    writableBuffer.getDouble(0);
-    try {
-      writableBuffer.getDouble(1);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableBuffer.getDouble(1);
   }
 
-  @Test
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void testPutDouble() {
-    writableBuffer.putDouble(0, 1d);
-    try {
-      writableBuffer.putDouble(1, 1d);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
-      // ignore
-    }
+    writableBuffer.putDouble(1, 1d);
   }
 }
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryReadWriteSafetyTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryReadWriteSafetyTest.java
index d6ba564..1a2ae5d 100644
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryReadWriteSafetyTest.java
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryReadWriteSafetyTest.java
@@ -20,11 +20,12 @@
 package org.apache.datasketches.memory.internal;
 
 import java.io.File;
-import java.io.RandomAccessFile;
+import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
+import java.nio.file.Files;
+import java.nio.file.StandardOpenOption;
 
-import org.apache.datasketches.memory.MapHandle;
 import org.apache.datasketches.memory.Memory;
 import org.apache.datasketches.memory.ReadOnlyException;
 import org.apache.datasketches.memory.WritableMemory;
@@ -36,42 +37,42 @@ public class MemoryReadWriteSafetyTest {
 
   final WritableMemory mem = (WritableMemory) Memory.wrap(new byte[8]);
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testPutByte() {
     mem.putByte(0, (byte) 1);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testPutBoolean() {
     mem.putBoolean(0, true);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testPutShort() {
     mem.putShort(0, (short) 1);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testPutChar() {
     mem.putChar(0, (char) 1);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testPutInt() {
     mem.putInt(0, 1);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testPutLong() {
     mem.putLong(0, 1);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testPutFloat() {
     mem.putFloat(0, 1);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testPutDouble() {
     mem.putDouble(0, 1);
   }
@@ -118,111 +119,132 @@ public class MemoryReadWriteSafetyTest {
 
   // Now, test that various ways to obtain a read-only memory produce a read-only memory indeed
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testWritableMemoryRegion() {
     WritableMemory mem1 = (WritableMemory) WritableMemory.allocate(8).region(0, 8);
     mem1.putInt(0, 1);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testByteArrayWrap() {
     WritableMemory mem1 = (WritableMemory) Memory.wrap(new byte[8]);
     mem1.putInt(0, 1);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testByteArrayWrapWithBO() {
     WritableMemory mem1 = (WritableMemory) Memory.wrap(new byte[8], ByteOrder.nativeOrder());
     mem1.putInt(0, 1);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testByteArrayWrapWithOffsetsAndBO() {
     WritableMemory mem1 = (WritableMemory) Memory.wrap(new byte[8], 0, 4, ByteOrder.nativeOrder());
     mem1.putInt(0, 1);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testBooleanArrayWrap() {
     WritableMemory mem1 = (WritableMemory) Memory.wrap(new boolean[8]);
     mem1.putInt(0, 1);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testShortArrayWrap() {
     WritableMemory mem1 = (WritableMemory) Memory.wrap(new short[8]);
     mem1.putInt(0, 1);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testCharArrayWrap() {
     WritableMemory mem1 = (WritableMemory) Memory.wrap(new char[8]);
     mem1.putInt(0, 1);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testIntArrayWrap() {
     WritableMemory mem1 = (WritableMemory) Memory.wrap(new int[8]);
     mem1.putInt(0, 1);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testLongArrayWrap() {
     WritableMemory mem1 = (WritableMemory) Memory.wrap(new long[8]);
     mem1.putInt(0, 1);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testFloatArrayWrap() {
     WritableMemory mem1 = (WritableMemory) Memory.wrap(new float[8]);
     mem1.putInt(0, 1);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testDoubleArrayWrap() {
     WritableMemory mem1 = (WritableMemory) Memory.wrap(new double[8]);
     mem1.putInt(0, 1);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testByteBufferWrap() {
     WritableMemory mem1 = (WritableMemory) Memory.wrap(ByteBuffer.allocate(8));
     mem1.putInt(0, 1);
   }
 
-  //@SuppressWarnings("resource")
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = ReadOnlyException.class)
   public void testMapFile() throws Exception {
-    File tempFile = File.createTempFile("test", null);
-    tempFile.deleteOnExit();
-    try (RandomAccessFile raf = new RandomAccessFile(tempFile, "rw")) {
-      raf.setLength(8);
-      //System.out.println(UtilTest.getFileAttributes(tempFile));
-      try (MapHandle h = Memory.map(tempFile)) {
-        ((WritableMemory) h.get()).putInt(0, 1);
-      }
+    File tempFile;
+    try {
+      tempFile = File.createTempFile("test", ".tmp", null);
+      Files.write(tempFile.toPath(), "ipsum".getBytes(), StandardOpenOption.APPEND);
+      //tempFile.setReadOnly();
+    } catch (IllegalArgumentException | IOException | SecurityException e) { throw new RuntimeException(e); }
+    try (Memory mem = Memory.map(tempFile)) { //Memory is RO
+      ((WritableMemory) mem).putInt(0, 1);
+    }
+    tempFile.delete();
+  }
+
+  @Test(expectedExceptions = ReadOnlyException.class)
+  public void testWritableMapWithROFile() {
+    File tempFile;
+    try {
+      tempFile = File.createTempFile("test", ".tmp", null);
+      Files.write(tempFile.toPath(), "ipsum".getBytes(), StandardOpenOption.APPEND);
+      tempFile.setReadOnly();
+    } catch (IllegalArgumentException | IOException | SecurityException e) { throw new RuntimeException(e); }
+    try (WritableMemory mem = WritableMemory.writableMap(tempFile)) { //File is RO
+      mem.putInt(0, 1);
     }
+    tempFile.delete();
   }
 
-  @SuppressWarnings("resource")
-  @Test(expectedExceptions = AssertionError.class)
-  public void testMapFileWithOffsetsAndBO() throws Exception {
-    File tempFile = File.createTempFile("test", "test");
-    tempFile.deleteOnExit();
-    new RandomAccessFile(tempFile, "rw").setLength(8);
-    try (MapHandle h = Memory.map(tempFile, 0, 4, ByteOrder.nativeOrder())) {
-      ((WritableMemory) h.get()).putInt(0, 1);
+  @Test(expectedExceptions = ReadOnlyException.class)
+  public void testMapFileWithOffsetsAndBO() {
+    File tempFile;
+    try {
+      tempFile = File.createTempFile("test", ".tmp", null);
+      Files.write(tempFile.toPath(), "ipsum".getBytes(), StandardOpenOption.APPEND);
+      //tempFile.setReadOnly();
+    } catch (IllegalArgumentException | IOException | SecurityException e) { throw new RuntimeException(e); }
+    try (Memory mem = Memory.map(tempFile, 0, 4, ByteOrder.nativeOrder())) { //Memory is RO
+      ((WritableMemory) mem).putInt(0, 1);
     }
+    tempFile.delete();
   }
 
-  @SuppressWarnings("resource")
   @Test(expectedExceptions = IllegalArgumentException.class)
-  public void testMapFileBeyondTheFileSize() throws Exception {
-    File tempFile = File.createTempFile("test", "test");
-    tempFile.deleteOnExit();
-    new RandomAccessFile(tempFile, "rw").setLength(8);
-    try (MapHandle unused = Memory.map(tempFile, 0, 16, ByteOrder.nativeOrder())) {
-      //empty
+  public void testMapFileBeyondTheFileSize() {
+    File tempFile;
+    try {
+      tempFile = File.createTempFile("test", ".tmp", null);
+      Files.write(tempFile.toPath(), "ipsum".getBytes(), StandardOpenOption.APPEND);
+      //tempFile.setReadOnly();
+    } catch (IllegalArgumentException | IOException | SecurityException e) { throw new RuntimeException(e); }
+    try (Memory mem = Memory.map(tempFile, 0, 16, ByteOrder.nativeOrder())) {
+      //Read-only mode and requested map length is greater than current file length:
+      //  Requested Length = 16, Current File Length = 5
     }
+    tempFile.delete();
   }
 }
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 4d43e47..2867687 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
@@ -23,30 +23,29 @@
 
 package org.apache.datasketches.memory.internal;
 
-import static org.apache.datasketches.memory.internal.Util.getResourceFile;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertTrue;
 
-import java.io.File;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.util.List;
 
-import org.apache.datasketches.memory.Resource;
-import org.apache.datasketches.memory.MapHandle;
+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;
-import org.apache.datasketches.memory.WritableHandle;
 import org.apache.datasketches.memory.WritableMemory;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 import org.testng.collections.Lists;
 
 public class MemoryTest {
-  private static final String LS = System.getProperty("line.separator");
+  private static final String LS = Util.LS;
 
   @BeforeClass
   public void setReadOnly() {
@@ -56,8 +55,7 @@ public class MemoryTest {
   @Test
   public void checkDirectRoundTrip() throws Exception {
     int n = 1024; //longs
-    try (WritableHandle wh = WritableMemory.allocateDirect(n * 8)) {
-      WritableMemory mem = wh.getWritable();
+    try (WritableMemory mem = WritableMemory.allocateDirect(n * 8)) {
       for (int i = 0; i < n; i++) {
         mem.putLong(i * 8, i);
       }
@@ -319,73 +317,23 @@ public class MemoryTest {
     }
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = MemoryInvalidException.class)
   public void checkParentUseAfterFree() throws Exception {
     int bytes = 64 * 8;
-    WritableHandle wh = WritableMemory.allocateDirect(bytes);
-    WritableMemory wmem = wh.getWritable();
-    wh.close();
-    //with -ea assert: Memory not valid.
-    //with -da sometimes segfaults, sometimes passes!
+    WritableMemory wmem = WritableMemory.allocateDirect(bytes);
+    wmem.close();
     wmem.getLong(0);
   }
 
-  @Test(expectedExceptions = AssertionError.class)
+  @Test(expectedExceptions = MemoryInvalidException.class)
   public void checkRegionUseAfterFree() throws Exception {
     int bytes = 64;
-    WritableHandle wh = WritableMemory.allocateDirect(bytes);
-    Memory wmem = wh.get();
-    Memory region = wmem.region(0L, bytes);
-    wh.close();
-    //with -ea assert: Memory not valid.
-    //with -da sometimes segfaults, sometimes passes!
+    Memory mem = WritableMemory.allocateDirect(bytes);
+    Memory region = mem.region(0L, bytes);
+    mem.close();
     region.getByte(0);
   }
 
-  @Test
-  public void checkMonitorDirectStats() throws Exception {
-    int bytes = 1024;
-    long curAllocations = Resource.getCurrentDirectMemoryAllocations();
-    long curAllocated   = Resource.getCurrentDirectMemoryAllocated();
-    if (curAllocations != 0) { System.err.println(curAllocations + " should be zero!"); }
-    WritableHandle wh1 = WritableMemory.allocateDirect(bytes);
-    WritableHandle wh2 = WritableMemory.allocateDirect(bytes);
-    assertEquals(Resource.getCurrentDirectMemoryAllocations(), 2L + curAllocations);
-    assertEquals(Resource.getCurrentDirectMemoryAllocated(), 2 * bytes + curAllocated);
-
-    wh1.close();
-    assertEquals(Resource.getCurrentDirectMemoryAllocations(), 1L + curAllocations);
-    assertEquals(Resource.getCurrentDirectMemoryAllocated(), bytes + curAllocated);
-
-    wh2.close();
-    wh2.close(); //check that it doesn't go negative.
-    //even though the handles are closed, these methods are static access
-    assertEquals(Resource.getCurrentDirectMemoryAllocations(), 0L + curAllocations);
-    assertEquals(Resource.getCurrentDirectMemoryAllocated(), 0L + curAllocated);
-  }
-
-  @Test
-  public void checkMonitorDirectMapStats() throws Exception {
-    File file = getResourceFile("GettysburgAddress.txt");
-    long bytes = file.length();
-
-    MapHandle mmh1 = Memory.map(file);
-    MapHandle mmh2 = Memory.map(file);
-
-    assertEquals(Resource.getCurrentDirectMemoryMapAllocations(), 2L);
-    assertEquals(Resource.getCurrentDirectMemoryMapAllocated(), 2 * bytes);
-
-    mmh1.close();
-    assertEquals(Resource.getCurrentDirectMemoryMapAllocations(), 1L);
-    assertEquals(Resource.getCurrentDirectMemoryMapAllocated(), bytes);
-
-    mmh2.close();
-    mmh2.close(); //check that it doesn't go negative.
-    //even though the handles are closed, these methods are static access
-    assertEquals(Resource.getCurrentDirectMemoryMapAllocations(), 0L);
-    assertEquals(Resource.getCurrentDirectMemoryMapAllocated(), 0L);
-  }
-
   @Test
   public void checkMemReqSvr() throws Exception {
     WritableMemory wmem;
@@ -397,10 +345,9 @@ public class MemoryTest {
       wbuf = wmem.asWritableBuffer();
       assertNull(wbuf.getMemoryRequestServer());
       //OFF HEAP
-      try (WritableHandle wdh = WritableMemory.allocateDirect(16)) { //OFF HEAP
-        wmem = wdh.getWritable();
-        assertNull(wmem.getMemoryRequestServer());
-        wbuf = wmem.asWritableBuffer();
+      try (WritableMemory wmem2 = WritableMemory.allocateDirect(16)) { //OFF HEAP
+        assertNull(wmem2.getMemoryRequestServer());
+        wbuf = wmem2.asWritableBuffer();
         assertNull(wbuf.getMemoryRequestServer());
       }
       //ByteBuffer
@@ -409,26 +356,28 @@ public class MemoryTest {
       assertNull(wmem.getMemoryRequestServer());
       wbuf = wmem.asWritableBuffer();
       assertNull(wbuf.getMemoryRequestServer());
-    } else {
-      //ON HEAP
-      wmem = WritableMemory.writableWrap(new byte[16]);
-      assertNotNull(wmem.getMemoryRequestServer());
-      wbuf = wmem.asWritableBuffer();
-      assertNotNull(wbuf.getMemoryRequestServer());
-      //OFF HEAP
-      try (WritableHandle wdh = WritableMemory.allocateDirect(16)) {
-        WritableMemory wmem2 = wdh.getWritable();
-        assertNotNull(wmem2.getMemoryRequestServer());
-        wbuf = wmem.asWritableBuffer();
-        assertNotNull(wbuf.getMemoryRequestServer());
-      }
-      //ByteBuffer
-      ByteBuffer bb = ByteBuffer.allocate(16);
-      wmem = WritableMemory.writableWrap(bb);
-      assertNotNull(wmem.getMemoryRequestServer());
+    }
+
+    MemoryRequestServer memReqSvr = new DefaultMemoryRequestServer();
+
+    //ON HEAP
+    wmem = WritableMemory.writableWrap(new byte[16], 0, 16, Util.NATIVE_BYTE_ORDER, memReqSvr);
+    assertNotNull(wmem.getMemoryRequestServer());
+    wbuf = wmem.asWritableBuffer();
+    assertNotNull(wbuf.getMemoryRequestServer());
+    //OFF HEAP
+    try (WritableMemory wmem3 = WritableMemory.allocateDirect(16, Util.NATIVE_BYTE_ORDER, memReqSvr)) {
+      assertNotNull(wmem3.getMemoryRequestServer());
       wbuf = wmem.asWritableBuffer();
       assertNotNull(wbuf.getMemoryRequestServer());
     }
+    //ByteBuffer
+    ByteBuffer bb = ByteBuffer.allocate(16);
+    wmem = WritableMemory.writableWrap(bb, Util.NATIVE_BYTE_ORDER, memReqSvr);
+    assertNotNull(wmem.getMemoryRequestServer());
+    wbuf = wmem.asWritableBuffer();
+    assertNotNull(wbuf.getMemoryRequestServer());
+
   }
 
   @Test
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryWriteToTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryWriteToTest.java
index 78e51ab..58ba098 100644
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryWriteToTest.java
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MemoryWriteToTest.java
@@ -27,7 +27,6 @@ import java.nio.channels.Channels;
 import java.nio.channels.WritableByteChannel;
 import java.util.concurrent.ThreadLocalRandom;
 
-import org.apache.datasketches.memory.WritableHandle;
 import org.apache.datasketches.memory.Memory;
 import org.apache.datasketches.memory.WritableMemory;
 import org.testng.Assert;
@@ -57,9 +56,8 @@ public class MemoryWriteToTest {
 
   @Test
   public void testOffHeap() throws Exception {
-    try (WritableHandle handle =
+    try (WritableMemory mem =
         WritableMemory.allocateDirect((UNSAFE_COPY_THRESHOLD_BYTES * 5) + 10)) {
-      WritableMemory mem = handle.getWritable();
       testWriteTo(mem.region(0, 0));
       testOffHeap(mem, 7);
       testOffHeap(mem, 1023);
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MurmurHash3v2Test.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MurmurHash3v2Test.java
index 90f1dab..d64965c 100644
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MurmurHash3v2Test.java
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/MurmurHash3v2Test.java
@@ -25,7 +25,6 @@ import static org.testng.Assert.fail;
 
 import org.apache.datasketches.memory.Memory;
 import org.apache.datasketches.memory.MurmurHash3v2;
-import org.apache.datasketches.memory.WritableHandle;
 import org.apache.datasketches.memory.WritableMemory;
 import org.testng.Assert;
 import org.testng.annotations.Test;
@@ -254,9 +253,8 @@ public class MurmurHash3v2Test {
       Memory mem = Memory.wrap(new byte[0]);
       out = hash(mem, 0L, 4L, 1L, out);
     } catch (final IllegalArgumentException e) { }
-    try (WritableHandle wh = WritableMemory.allocateDirect(8)) {
+    try (Memory mem = WritableMemory.allocateDirect(8)) {
       long[] out = new long[2];
-      Memory mem = wh.get();
       out = hash(mem, 0L, 4L, 1L, out);
     } catch (Exception ee) { }
   }
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 8711b9d..2dc582e 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
@@ -23,17 +23,17 @@ import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
 
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 
 import org.apache.datasketches.memory.Buffer;
 import org.apache.datasketches.memory.Memory;
+import org.apache.datasketches.memory.MemoryBoundsException;
 import org.apache.datasketches.memory.ReadOnlyException;
 import org.apache.datasketches.memory.WritableBuffer;
-import org.apache.datasketches.memory.WritableHandle;
 import org.apache.datasketches.memory.WritableMemory;
-import org.testng.Assert;
 import org.testng.annotations.Test;
 
 public class NativeWritableBufferImplTest {
@@ -41,17 +41,14 @@ public class NativeWritableBufferImplTest {
   //Simple Native direct
 
   @Test
-  public void checkNativeCapacityAndClose() throws Exception {
+  public void checkNativeCapacityAndClose() {
     int memCapacity = 64;
-    WritableHandle wmh = WritableMemory.allocateDirect(memCapacity);
-    WritableMemory wmem = wmh.getWritable();
+    WritableMemory wmem = WritableMemory.allocateDirect(memCapacity);
     WritableBuffer wbuf = wmem.asWritableBuffer();
     assertEquals(wbuf.getCapacity(), memCapacity);
 
-    wmh.close(); //intentional
+    wmem.close(); //intentional
     assertFalse(wbuf.isValid());
-
-    wmh.close(); //intentional, nothing to free
   }
 
   //Simple Heap arrays
@@ -202,37 +199,36 @@ public class NativeWritableBufferImplTest {
   }
 
   @Test
-  public void checkNativeBaseBound() throws Exception {
+  public void checkNativeBaseBound() {
     int memCapacity = 64;
-    try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory wmem = wrh.getWritable();
+    try (WritableMemory wmem = WritableMemory.allocateDirect(memCapacity)) {
       WritableBuffer wbuf = wmem.asWritableBuffer();
-      wbuf.toHexString("Force Assertion Error", memCapacity, 8);
-    } catch (IllegalArgumentException e) {
+      wbuf.toHexString("Bounds Exception", memCapacity, 8); //Bounds Exception
+      fail("Should have thrown MemoryBoundsException");
+    } catch (MemoryBoundsException e) {
       //ok
     }
   }
 
   @Test
-  public void checkNativeSrcArrayBound() throws Exception {
+  public void checkNativeSrcArrayBound() {
     long memCapacity = 64;
-    try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory wmem = wrh.getWritable();
+    try (WritableMemory wmem = WritableMemory.allocateDirect(memCapacity)) {
       WritableBuffer wbuf = wmem.asWritableBuffer();
       byte[] srcArray = { 1, -2, 3, -4 };
-      wbuf.putByteArray(srcArray, 0, 5); //wrong!
-    } catch (IllegalArgumentException e) {
+      wbuf.putByteArray(srcArray, 0, 5); //should be 4!
+      fail("Should have thrown MemoryBoundsException");
+    } catch (MemoryBoundsException e) {
       //pass
     }
   }
 
-  @Test(expectedExceptions = IllegalArgumentException.class)
-  public void checkRegionBounds() throws Exception {
+  @Test(expectedExceptions = MemoryBoundsException.class)
+  public void checkRegionBounds() {
     int memCapacity = 64;
-    try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory wmem = wrh.getWritable();
+    try (WritableMemory wmem = WritableMemory.allocateDirect(memCapacity)) {
       WritableBuffer wbuf = wmem.asWritableBuffer();
-      wbuf.writableRegion(1, 64, wbuf.getByteOrder()); //wrong!
+      wbuf.writableRegion(1, 64, wbuf.getByteOrder()); //off by one
     }
   }
 
@@ -252,7 +248,7 @@ public class NativeWritableBufferImplTest {
       assertEquals(wbuf.getByte(), byteBuf.get(i));
     }
 
-    assertTrue(wbuf.hasByteBuffer());
+    assertTrue(wbuf.isByteBufferResource());
     ByteBuffer byteBuf2 = wbuf.getByteBuffer();
     assertEquals(byteBuf2, byteBuf);
     //println( mem.toHexString("HeapBB", 0, memCapacity));
@@ -340,15 +336,13 @@ public class NativeWritableBufferImplTest {
   }
 
   @Test
-  public void checkIsDirect() throws Exception {
+  public void checkIsDirect() {
     int memCapacity = 64;
     WritableBuffer mem = WritableMemory.allocate(memCapacity).asWritableBuffer();
-    assertFalse(mem.isDirect());
-    try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem2 = wrh.getWritable();
+    assertFalse(mem.isDirectResource());
+    try (WritableMemory mem2 = WritableMemory.allocateDirect(memCapacity)) {
       WritableBuffer wbuf = mem2.asWritableBuffer();
-      assertTrue(wbuf.isDirect());
-      wrh.close(); //immediate close
+      assertTrue(wbuf.isDirectResource());
     }
   }
 
@@ -369,7 +363,7 @@ public class NativeWritableBufferImplTest {
 
   @Test
   public void checkGoodBounds() {
-    UnsafeUtil.checkBounds(50, 50, 100);
+    ResourceImpl.checkBounds(50, 50, 100);
   }
 
   @Test
@@ -396,22 +390,17 @@ public class NativeWritableBufferImplTest {
   }
 
   @Test
-  public void checkCompareToDirect() throws Exception {
+  public void checkCompareToDirect() {
     byte[] arr1 = new byte[] {0, 1, 2, 3};
     byte[] arr2 = new byte[] {0, 1, 2, 4};
     byte[] arr3 = new byte[] {0, 1, 2, 3, 4};
 
-    try (WritableHandle h1 = WritableMemory.allocateDirect(4);
-        WritableHandle h2 = WritableMemory.allocateDirect(4);
-        WritableHandle h3 = WritableMemory.allocateDirect(5))
+    try (WritableMemory mem1 = WritableMemory.allocateDirect(4);
+        WritableMemory mem2 = WritableMemory.allocateDirect(4);
+        WritableMemory mem3 = WritableMemory.allocateDirect(5))
     {
-      WritableMemory mem1 = h1.getWritable();
       mem1.putByteArray(0, arr1, 0, 4);
-
-      WritableMemory mem2 = h2.getWritable();
       mem2.putByteArray(0, arr2, 0, 4);
-
-      WritableMemory mem3 = h3.getWritable();
       mem3.putByteArray(0, arr3, 0, 5);
 
       Buffer buf1 = mem1.asBuffer();
@@ -506,7 +495,7 @@ public class NativeWritableBufferImplTest {
       Buffer buf = Buffer.wrap(bb.asReadOnlyBuffer());
       wbuf = (WritableBuffer) buf;
       wmem = wbuf.asWritableMemory();
-      Assert.fail();
+      fail("Should have thrown exception");
     } catch (ReadOnlyException expected) {
       // expected
     }
@@ -524,7 +513,7 @@ public class NativeWritableBufferImplTest {
       wbuf = (WritableBuffer) buf;
       @SuppressWarnings("unused")
       WritableBuffer wdup2 = wbuf.writableDuplicate();
-      Assert.fail();
+      fail("Should have thrown exception");
     } catch (ReadOnlyException expected) {
       // ignore
     }
@@ -542,7 +531,7 @@ public class NativeWritableBufferImplTest {
       wbuf = (WritableBuffer) buf;
       @SuppressWarnings("unused")
       WritableBuffer wreg2 = wbuf.writableRegion();
-      Assert.fail();
+      fail("Should have thrown exception");
     } catch (ReadOnlyException expected) {
       // ignore
     }
@@ -560,7 +549,7 @@ public class NativeWritableBufferImplTest {
       wbuf = (WritableBuffer) buf;
       @SuppressWarnings("unused")
       WritableBuffer wreg2 = wbuf.writableRegion(0, 1, wbuf.getByteOrder());
-      Assert.fail();
+      fail("Should have thrown exception");
     } catch (ReadOnlyException expected) {
       // ignore
     }
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 737add1..57ecd23 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
@@ -29,9 +29,9 @@ import java.nio.ByteOrder;
 
 import org.apache.datasketches.memory.Buffer;
 import org.apache.datasketches.memory.Memory;
+import org.apache.datasketches.memory.MemoryBoundsException;
 import org.apache.datasketches.memory.ReadOnlyException;
 import org.apache.datasketches.memory.WritableBuffer;
-import org.apache.datasketches.memory.WritableHandle;
 import org.apache.datasketches.memory.WritableMemory;
 import org.testng.annotations.Test;
 
@@ -40,16 +40,13 @@ public class NativeWritableMemoryImplTest {
   //Simple Native direct
 
   @Test
-  public void checkNativeCapacityAndClose() throws Exception {
+  public void checkNativeCapacityAndClose() {
     int memCapacity = 64;
-    WritableHandle wmh = WritableMemory.allocateDirect(memCapacity);
-    WritableMemory mem = wmh.getWritable();
+    WritableMemory mem = WritableMemory.allocateDirect(memCapacity);
     assertEquals(memCapacity, mem.getCapacity());
 
-    wmh.close(); //intentional
+    mem.close(); //intentional
     assertFalse(mem.isValid());
-
-    wmh.close(); //intentional, nothing to free
   }
 
   //Simple Native arrays
@@ -200,24 +197,24 @@ public class NativeWritableMemoryImplTest {
   }
 
   @Test
-  public void checkNativeBaseBound() throws Exception {
+  public void checkNativeBaseBound() {
     int memCapacity = 64;
-    try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem = wrh.getWritable();
+    try (WritableMemory mem = WritableMemory.allocateDirect(memCapacity)) {
       mem.toHexString("Force Assertion Error", memCapacity, 8);
-    } catch (IllegalArgumentException e) {
+      fail("Should have thrown MemoryBoundsException");
+    } catch (MemoryBoundsException e) { //bounds exception
       //ok
     }
   }
 
   @Test
-  public void checkNativeSrcArrayBound() throws Exception {
+  public void checkNativeSrcArrayBound() {
     long memCapacity = 64;
-    try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem = wrh.getWritable();
+    try (WritableMemory mem = WritableMemory.allocateDirect(memCapacity)) {
       byte[] srcArray = { 1, -2, 3, -4 };
       mem.putByteArray(0L, srcArray, 0, 5);
-    } catch (IllegalArgumentException e) {
+      fail("Should have thrown MemoryBoundsException");
+    } catch (MemoryBoundsException e) {
       //pass
     }
   }
@@ -227,15 +224,14 @@ public class NativeWritableMemoryImplTest {
   @Test(expectedExceptions = IllegalArgumentException.class)
   public void checkDegenerateCopyTo() {
     WritableMemory wmem = WritableMemory.allocate(64);
-    wmem.copyTo(0, wmem, 0, 64);
+    wmem.copyTo(0, wmem, 0, 64); //Attempt to copy a block of memory exactly in-place, should be a bug
   }
 
   @Test
-  public void checkCopyWithinNativeSmall() throws Exception {
+  public void checkCopyWithinNativeSmall() {
     int memCapacity = 64;
     int half = memCapacity / 2;
-    try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem = wrh.getWritable();
+    try (WritableMemory mem = WritableMemory.allocateDirect(memCapacity)) {
       mem.clear();
 
       for (int i = 0; i < half; i++) { //fill first half
@@ -251,13 +247,12 @@ public class NativeWritableMemoryImplTest {
   }
 
   @Test
-  public void checkCopyWithinNativeLarge() throws Exception {
+  public void checkCopyWithinNativeLarge() {
     int memCapacity = (2 << 20) + 64;
     int memCapLongs = memCapacity / 8;
     int halfBytes = memCapacity / 2;
     int halfLongs = memCapLongs / 2;
-    try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem = wrh.getWritable();
+    try (WritableMemory mem = WritableMemory.allocateDirect(memCapacity)) {
       mem.clear();
 
       for (int i = 0; i < halfLongs; i++) {
@@ -273,41 +268,36 @@ public class NativeWritableMemoryImplTest {
   }
 
   @Test
-  public void checkCopyWithinNativeSrcBound() throws Exception {
+  public void checkCopyWithinNativeSrcBound() {
     int memCapacity = 64;
-    try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem = wrh.getWritable();
+    try (WritableMemory mem = WritableMemory.allocateDirect(memCapacity)) {
       mem.copyTo(32, mem, 32, 33);  //hit source bound check
-      fail("Did Not Catch Assertion Error: source bound");
+      fail("Should have thrown MemoryBoundsException");
     }
-    catch (IllegalArgumentException e) {
+    catch (MemoryBoundsException e) {
       //pass
     }
   }
 
   @Test
-  public void checkCopyWithinNativeDstBound() throws Exception {
+  public void checkCopyWithinNativeDstBound() {
     int memCapacity = 64;
-    try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem = wrh.getWritable();
+    try (WritableMemory mem = WritableMemory.allocateDirect(memCapacity)) {
       mem.copyTo(0, mem, 32, 33);  //hit dst bound check
-      fail("Did Not Catch Assertion Error: dst bound");
+      fail("Should have thrown MemoryBoundsException");
     }
-    catch (IllegalArgumentException e) {
+    catch (MemoryBoundsException e) {
       //pass
     }
   }
 
   @Test
-  public void checkCopyCrossNativeSmall() throws Exception {
+  public void checkCopyCrossNativeSmall() {
     int memCapacity = 64;
 
-    try (WritableHandle wrh1 = WritableMemory.allocateDirect(memCapacity);
-        WritableHandle wrh2 = WritableMemory.allocateDirect(memCapacity))
+    try (WritableMemory mem1 = WritableMemory.allocateDirect(memCapacity);
+        WritableMemory mem2 = WritableMemory.allocateDirect(memCapacity))
     {
-      WritableMemory mem1 = wrh1.getWritable();
-      WritableMemory mem2 = wrh2.getWritable();
-
       for (int i = 0; i < memCapacity; i++) {
         mem1.putByte(i, (byte) i);
       }
@@ -317,22 +307,17 @@ public class NativeWritableMemoryImplTest {
       for (int i = 0; i < memCapacity; i++) {
         assertEquals(mem2.getByte(i), (byte) i);
       }
-      wrh1.close();
-      wrh2.close();
     }
   }
 
   @Test
-  public void checkCopyCrossNativeLarge() throws Exception {
+  public void checkCopyCrossNativeLarge() {
     int memCapacity = (2 << 20) + 64;
     int memCapLongs = memCapacity / 8;
 
-    try (WritableHandle wrh1 = WritableMemory.allocateDirect(memCapacity);
-        WritableHandle wrh2 = WritableMemory.allocateDirect(memCapacity))
+    try (WritableMemory mem1 = WritableMemory.allocateDirect(memCapacity);
+        WritableMemory mem2 = WritableMemory.allocateDirect(memCapacity))
     {
-      WritableMemory mem1 = wrh1.getWritable();
-      WritableMemory mem2 = wrh2.getWritable();
-
       for (int i = 0; i < memCapLongs; i++) {
         mem1.putLong(i * 8, i);
       }
@@ -347,11 +332,9 @@ public class NativeWritableMemoryImplTest {
   }
 
   @Test
-  public void checkCopyCrossNativeAndByteArray() throws Exception {
+  public void checkCopyCrossNativeAndByteArray() {
     int memCapacity = 64;
-    try (WritableHandle wrh1 = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem1 = wrh1.getWritable();
-
+    try (WritableMemory mem1 = WritableMemory.allocateDirect(memCapacity)) {
       for (int i = 0; i < mem1.getCapacity(); i++) {
         mem1.putByte(i, (byte) i);
       }
@@ -367,11 +350,10 @@ public class NativeWritableMemoryImplTest {
   }
 
   @Test
-  public void checkCopyCrossRegionsSameNative() throws Exception {
+  public void checkCopyCrossRegionsSameNative() {
     int memCapacity = 128;
 
-    try (WritableHandle wrh1 = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem1 = wrh1.getWritable();
+    try (WritableMemory mem1 = WritableMemory.allocateDirect(memCapacity)) {
 
       for (int i = 0; i < mem1.getCapacity(); i++) {
         mem1.putByte(i, (byte) i);
@@ -394,10 +376,9 @@ public class NativeWritableMemoryImplTest {
   }
 
   @Test
-  public void checkCopyCrossNativeArrayAndHierarchicalRegions() throws Exception {
+  public void checkCopyCrossNativeArrayAndHierarchicalRegions() {
     int memCapacity = 64;
-    try (WritableHandle wrh1 = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem1 = wrh1.getWritable();
+    try (WritableMemory mem1 = WritableMemory.allocateDirect(memCapacity)) {
 
       for (int i = 0; i < mem1.getCapacity(); i++) { //fill with numbers
         mem1.putByte(i, (byte) i);
@@ -420,14 +401,12 @@ public class NativeWritableMemoryImplTest {
         assertEquals(mem2.getByte(i), j);
       }
     }
-
   }
 
-  @Test(expectedExceptions = IllegalArgumentException.class)
-  public void checkRegionBounds() throws Exception {
+  @Test(expectedExceptions = MemoryBoundsException.class)
+  public void checkRegionBounds() {
     int memCapacity = 64;
-    try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem = wrh.getWritable();
+    try (WritableMemory mem = WritableMemory.allocateDirect(memCapacity)) {
       mem.writableRegion(1, 64);
     }
   }
@@ -448,7 +427,7 @@ public class NativeWritableMemoryImplTest {
       assertEquals(wmem.getByte(i), byteBuf.get(i));
     }
 
-    assertTrue(wmem.hasByteBuffer());
+    assertTrue(wmem.isByteBufferResource());
     ByteBuffer byteBuf2 = wmem.getByteBuffer();
     assertEquals(byteBuf2, byteBuf);
     //println( mem.toHexString("HeapBB", 0, memCapacity));
@@ -534,14 +513,12 @@ public class NativeWritableMemoryImplTest {
   }
 
   @Test
-  public void checkIsDirect() throws Exception {
+  public void checkIsDirect() {
     int memCapacity = 64;
     WritableMemory mem = WritableMemory.allocate(memCapacity);
-    assertFalse(mem.isDirect());
-    try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
-      mem = wrh.getWritable();
-      assertTrue(mem.isDirect());
-      wrh.close();
+    assertFalse(mem.isDirectResource());
+    try (WritableMemory mem1 = WritableMemory.allocateDirect(memCapacity)) {
+      assertTrue(mem1.isDirectResource());
     }
   }
 
@@ -562,7 +539,7 @@ public class NativeWritableMemoryImplTest {
 
   @Test
   public void checkGoodBounds() {
-    UnsafeUtil.checkBounds(50, 50, 100);
+    ResourceImpl.checkBounds(50, 50, 100);
   }
 
   @Test
@@ -595,22 +572,17 @@ public class NativeWritableMemoryImplTest {
   }
 
   @Test
-  public void checkCompareToDirect() throws Exception {
+  public void checkCompareToDirect() {
     byte[] arr1 = new byte[] {0, 1, 2, 3};
     byte[] arr2 = new byte[] {0, 1, 2, 4};
     byte[] arr3 = new byte[] {0, 1, 2, 3, 4};
 
-    try (WritableHandle h1 = WritableMemory.allocateDirect(4);
-        WritableHandle h2 = WritableMemory.allocateDirect(4);
-        WritableHandle h3 = WritableMemory.allocateDirect(5))
+    try (WritableMemory mem1 = WritableMemory.allocateDirect(4);
+        WritableMemory mem2 = WritableMemory.allocateDirect(4);
+        WritableMemory mem3 = WritableMemory.allocateDirect(5))
     {
-      WritableMemory mem1 = h1.getWritable();
       mem1.putByteArray(0, arr1, 0, 4);
-
-      WritableMemory mem2 = h2.getWritable();
       mem2.putByteArray(0, arr2, 0, 4);
-
-      WritableMemory mem3 = h3.getWritable();
       mem3.putByteArray(0, arr3, 0, 5);
 
       int comp = mem1.compareTo(0, 3, mem2, 0, 3);
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/NonNativeWritableMemoryImplTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/NonNativeWritableMemoryImplTest.java
index ced0f4c..cf1076c 100644
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/NonNativeWritableMemoryImplTest.java
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/NonNativeWritableMemoryImplTest.java
@@ -20,10 +20,12 @@
 package org.apache.datasketches.memory.internal;
 
 import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
 
 import java.nio.ByteOrder;
 
 import org.apache.datasketches.memory.Memory;
+import org.apache.datasketches.memory.MemoryBoundsException;
 import org.apache.datasketches.memory.WritableMemory;
 import org.testng.annotations.Test;
 
@@ -172,8 +174,8 @@ public class NonNativeWritableMemoryImplTest {
     wmem.getAndAddLong(0, 1L);
     try {
       wmem.getAndAddLong(1, 1L);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
+      fail("Expected MemoryBoundsException");
+    } catch (final MemoryBoundsException expected) {
       // ignore
     }
   }
@@ -183,8 +185,8 @@ public class NonNativeWritableMemoryImplTest {
     wmem.getAndSetLong(0, 1L);
     try {
       wmem.getAndSetLong(1, 1L);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
+      fail("Expected MemoryBoundsException");
+    } catch (final MemoryBoundsException expected) {
       // ignore
     }
   }
@@ -194,8 +196,8 @@ public class NonNativeWritableMemoryImplTest {
     wmem.compareAndSwapLong(0, 0L, 1L);
     try {
       wmem.compareAndSwapLong(1, 0L, 1L);
-      throw new RuntimeException("Expected AssertionError");
-    } catch (final AssertionError expected) {
+      fail("Expected MemoryBoundsException");
+    } catch (final MemoryBoundsException expected) {
       // ignore
     }
   }
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/ResourceTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/ResourceTest.java
index 86f4246..8b0fedf 100644
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/ResourceTest.java
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/ResourceTest.java
@@ -56,9 +56,11 @@ public class ResourceTest {
 
   @Test
   public void checkNotEqualTo() {
-    byte[] arr = new byte[8];
-    Memory mem = Memory.wrap(arr);
-    assertFalse(mem.equalTo(0, arr, 0, 8));
+    byte[] arr1 = {1,2,3,4,5,6,7,8};
+    Memory mem1 = Memory.wrap(arr1);
+    byte[] arr2 = {1,2,3,4,5,6,7,9};
+    Memory mem2 = Memory.wrap(arr2);
+    assertFalse(mem1.equalTo(mem2));
   }
 
   //StepBoolean checks
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 7b3c955..db060ab 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
@@ -29,8 +29,6 @@ import java.nio.ByteOrder;
 
 import org.apache.datasketches.memory.Buffer;
 import org.apache.datasketches.memory.Memory;
-import org.apache.datasketches.memory.WritableHandle;
-import org.apache.datasketches.memory.WritableMapHandle;
 import org.apache.datasketches.memory.WritableMemory;
 import org.testng.annotations.Test;
 
@@ -67,11 +65,10 @@ public class SpecificLeafTest {
   }
 
   @Test
-  public void checkDirectLeafs() throws Exception {
+  public void checkDirectLeafs()  {
     int bytes = 128;
-    try (WritableHandle h = WritableMemory.allocateDirect(bytes)) {
-      WritableMemory wmem = h.getWritable(); //native mem
-      assertTrue(((ResourceImpl)wmem).isDirectType(((ResourceImpl)wmem).getTypeId()));
+    try (WritableMemory wmem = WritableMemory.allocateDirect(bytes)) {
+      assertTrue(((ResourceImpl)wmem).isDirectResource());
       assertFalse(wmem.isReadOnly());
       checkCrossLeafTypeIds(wmem);
       WritableMemory nnwmem = wmem.writableRegion(0, bytes, Util.NON_NATIVE_BYTE_ORDER);
@@ -120,7 +117,7 @@ public class SpecificLeafTest {
   }
 
   @Test
-  public void checkMapLeafs() throws Exception {
+  public void checkMapLeafs() throws IOException {
     File file = new File("TestFile2.bin");
     if (file.exists()) {
       try {
@@ -136,8 +133,7 @@ public class SpecificLeafTest {
 
     final long bytes = 128;
 
-    try (WritableMapHandle h = WritableMemory.writableMap(file, 0L, bytes, ByteOrder.nativeOrder())) {
-      WritableMemory mem = h.getWritable();
+    try (WritableMemory mem = WritableMemory.writableMap(file, 0L, bytes, ByteOrder.nativeOrder())) {
       assertTrue(((ResourceImpl)mem).isMapType(((ResourceImpl)mem).getTypeId()));
       assertFalse(mem.isReadOnly());
       checkCrossLeafTypeIds(mem);
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/Utf8Test.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/Utf8Test.java
index 2568e03..e59a6ac 100644
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/Utf8Test.java
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/Utf8Test.java
@@ -29,6 +29,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.datasketches.memory.Memory;
+import org.apache.datasketches.memory.MemoryBoundsException;
 import org.apache.datasketches.memory.Utf8CodingException;
 import org.apache.datasketches.memory.WritableMemory;
 import org.apache.datasketches.memory.internal.Util.RandomCodePoints;
@@ -141,7 +142,7 @@ public class Utf8Test {
     for (int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) {
       ByteString bs = ByteString.copyFrom(new byte[] {(byte) i });
       if (!bs.isValidUtf8()) { //from -128 to -1
-        assertInvalid(bs.toByteArray());
+        checkInvalidBytes(bs.toByteArray());
       } else {
         valid++; //from 0 to 127
       }
@@ -156,7 +157,7 @@ public class Utf8Test {
       for (int j = Byte.MIN_VALUE; j <= Byte.MAX_VALUE; j++) {
         ByteString bs = ByteString.copyFrom(new byte[]{(byte) i, (byte) j});
         if (!bs.isValidUtf8()) {
-          assertInvalid(bs.toByteArray());
+          checkInvalidBytes(bs.toByteArray());
         } else {
           valid++;
         }
@@ -179,7 +180,7 @@ public class Utf8Test {
             byte[] bytes = new byte[]{(byte) i, (byte) j, (byte) k};
             ByteString bs = ByteString.copyFrom(bytes);
             if (!bs.isValidUtf8()) {
-              assertInvalid(bytes);
+              checkInvalidBytes(bytes);
             } else {
               valid++;
             }
@@ -253,12 +254,12 @@ public class Utf8Test {
   @Test
   public void testInvalid_4BytesSamples() {
     // Bad trailing bytes
-    assertInvalid(0xF0, 0xA4, 0xAD, 0x7F);
-    assertInvalid(0xF0, 0xA4, 0xAD, 0xC0);
+    checkInvalidInts(0xF0, 0xA4, 0xAD, 0x7F);
+    checkInvalidInts(0xF0, 0xA4, 0xAD, 0xC0);
 
     // Special cases for byte2
-    assertInvalid(0xF0, 0x8F, 0xAD, 0xA2);
-    assertInvalid(0xF4, 0x90, 0xAD, 0xA2);
+    checkInvalidInts(0xF0, 0x8F, 0xAD, 0xA2);
+    checkInvalidInts(0xF4, 0x90, 0xAD, 0xA2);
   }
 
   @Test
@@ -324,41 +325,41 @@ public class Utf8Test {
 
   @Test
   public void testOverlong() {
-    assertInvalid(0xc0, 0xaf);
-    assertInvalid(0xe0, 0x80, 0xaf);
-    assertInvalid(0xf0, 0x80, 0x80, 0xaf);
+    checkInvalidInts(0xc0, 0xaf);
+    checkInvalidInts(0xe0, 0x80, 0xaf);
+    checkInvalidInts(0xf0, 0x80, 0x80, 0xaf);
 
     // Max overlong
-    assertInvalid(0xc1, 0xbf);
-    assertInvalid(0xe0, 0x9f, 0xbf);
-    assertInvalid(0xf0 ,0x8f, 0xbf, 0xbf);
+    checkInvalidInts(0xc1, 0xbf);
+    checkInvalidInts(0xe0, 0x9f, 0xbf);
+    checkInvalidInts(0xf0 ,0x8f, 0xbf, 0xbf);
 
     // null overlong
-    assertInvalid(0xc0, 0x80);
-    assertInvalid(0xe0, 0x80, 0x80);
-    assertInvalid(0xf0, 0x80, 0x80, 0x80);
+    checkInvalidInts(0xc0, 0x80);
+    checkInvalidInts(0xe0, 0x80, 0x80);
+    checkInvalidInts(0xf0, 0x80, 0x80, 0x80);
   }
 
   @Test
   public void testIllegalCodepoints() {
     // Single surrogate
-    assertInvalid(0xed, 0xa0, 0x80);
-    assertInvalid(0xed, 0xad, 0xbf);
-    assertInvalid(0xed, 0xae, 0x80);
-    assertInvalid(0xed, 0xaf, 0xbf);
-    assertInvalid(0xed, 0xb0, 0x80);
-    assertInvalid(0xed, 0xbe, 0x80);
-    assertInvalid(0xed, 0xbf, 0xbf);
+    checkInvalidInts(0xed, 0xa0, 0x80);
+    checkInvalidInts(0xed, 0xad, 0xbf);
+    checkInvalidInts(0xed, 0xae, 0x80);
+    checkInvalidInts(0xed, 0xaf, 0xbf);
+    checkInvalidInts(0xed, 0xb0, 0x80);
+    checkInvalidInts(0xed, 0xbe, 0x80);
+    checkInvalidInts(0xed, 0xbf, 0xbf);
 
     // Paired surrogates
-    assertInvalid(0xed, 0xa0, 0x80, 0xed, 0xb0, 0x80);
-    assertInvalid(0xed, 0xa0, 0x80, 0xed, 0xbf, 0xbf);
-    assertInvalid(0xed, 0xad, 0xbf, 0xed, 0xb0, 0x80);
-    assertInvalid(0xed, 0xad, 0xbf, 0xed, 0xbf, 0xbf);
-    assertInvalid(0xed, 0xae, 0x80, 0xed, 0xb0, 0x80);
-    assertInvalid(0xed, 0xae, 0x80, 0xed, 0xbf, 0xbf);
-    assertInvalid(0xed, 0xaf, 0xbf, 0xed, 0xb0, 0x80);
-    assertInvalid(0xed, 0xaf, 0xbf, 0xed, 0xbf, 0xbf);
+    checkInvalidInts(0xed, 0xa0, 0x80, 0xed, 0xb0, 0x80);
+    checkInvalidInts(0xed, 0xa0, 0x80, 0xed, 0xbf, 0xbf);
+    checkInvalidInts(0xed, 0xad, 0xbf, 0xed, 0xb0, 0x80);
+    checkInvalidInts(0xed, 0xad, 0xbf, 0xed, 0xbf, 0xbf);
+    checkInvalidInts(0xed, 0xae, 0x80, 0xed, 0xb0, 0x80);
+    checkInvalidInts(0xed, 0xae, 0x80, 0xed, 0xbf, 0xbf);
+    checkInvalidInts(0xed, 0xaf, 0xbf, 0xed, 0xb0, 0x80);
+    checkInvalidInts(0xed, 0xaf, 0xbf, 0xed, 0xbf, 0xbf);
   }
 
   @Test
@@ -371,21 +372,21 @@ public class Utf8Test {
   @Test
   public void testInvalidBufferSlice() { //these are pure Memory bounds violations
     byte[] bytes  = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
-    assertInvalidSlice(bytes, bytes.length - 3, 4);
-    assertInvalidSlice(bytes, bytes.length, 1);
-    assertInvalidSlice(bytes, bytes.length + 1, 0);
-    assertInvalidSlice(bytes, 0, bytes.length + 1);
+    checkInvalidSlice(bytes, bytes.length - 3, 4);
+    checkInvalidSlice(bytes, bytes.length, 1);
+    checkInvalidSlice(bytes, bytes.length + 1, 0);
+    checkInvalidSlice(bytes, 0, bytes.length + 1);
   }
 
-  private static void assertInvalid(int... bytesAsInt) { //invalid byte sequences
+  private static void checkInvalidInts(int... bytesAsInt) { //invalid byte sequences
     byte[] bytes = new byte[bytesAsInt.length];
     for (int i = 0; i < bytesAsInt.length; i++) {
       bytes[i] = (byte) bytesAsInt[i];
     }
-    assertInvalid(bytes);
+    checkInvalidBytes(bytes);
   }
 
-  private static void assertInvalid(byte[] bytes) {
+  private static void checkInvalidBytes(byte[] bytes) {
     int bytesLen = bytes.length;
     try {
       Memory.wrap(bytes).getCharsFromUtf8(0, bytesLen, new StringBuilder());
@@ -402,12 +403,12 @@ public class Utf8Test {
     }
   }
 
-  private static void assertInvalidSlice(byte[] bytes, int index, int size) {
+  private static void checkInvalidSlice(byte[] bytes, int index, int size) {
     try {
       Memory mem = Memory.wrap(bytes);
       mem.getCharsFromUtf8(index, size, new StringBuilder());
       fail();
-    } catch (IllegalArgumentException e) { //Pure bounds violation
+    } catch (MemoryBoundsException e) { //Pure bounds violation
       // Expected.
     }
   }
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/UtilTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/UtilTest.java
index 4c2d72f..14a8629 100644
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/UtilTest.java
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/UtilTest.java
@@ -42,6 +42,7 @@ import java.nio.file.attribute.PosixFileAttributeView;
 import java.nio.file.attribute.PosixFileAttributes;
 import java.nio.file.attribute.PosixFilePermissions;
 
+import org.apache.datasketches.memory.MemoryBoundsException;
 import org.apache.datasketches.memory.WritableMemory;
 import org.testng.annotations.Test;
 
@@ -63,9 +64,9 @@ public class UtilTest {
     assertEquals(idx, -1024);
   }
 
-  @Test(expectedExceptions = IllegalArgumentException.class)
+  @Test(expectedExceptions = MemoryBoundsException.class)
   public void checkBoundsTest() {
-    UnsafeUtil.checkBounds(999, 2, 1000);
+    ResourceImpl.checkBounds(999, 2, 1000);
   }
 
   @Test
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/WritableDirectCopyTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/WritableDirectCopyTest.java
index f52aa34..37519a4 100644
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/WritableDirectCopyTest.java
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/WritableDirectCopyTest.java
@@ -22,8 +22,8 @@ package org.apache.datasketches.memory.internal;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.fail;
 
-import org.apache.datasketches.memory.WritableHandle;
 import org.apache.datasketches.memory.Memory;
+import org.apache.datasketches.memory.MemoryBoundsException;
 import org.apache.datasketches.memory.WritableMemory;
 import org.testng.annotations.Test;
 
@@ -35,11 +35,10 @@ public class WritableDirectCopyTest {
 //Copy Within tests
 
   @Test
-  public void checkCopyWithinNativeSmall() throws Exception {
+  public void checkCopyWithinNativeSmall() {
     int memCapacity = 64;
     int half = memCapacity / 2;
-    try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem = wrh.getWritable();
+    try (WritableMemory mem = WritableMemory.allocateDirect(memCapacity)) {
       mem.clear();
 
       for (int i = 0; i < half; i++) { //fill first half
@@ -55,13 +54,12 @@ public class WritableDirectCopyTest {
   }
 
   @Test
-  public void checkCopyWithinNativeLarge() throws Exception {
+  public void checkCopyWithinNativeLarge() {
     int memCapacity = (2 << 20) + 64;
     int memCapLongs = memCapacity / 8;
     int halfBytes = memCapacity / 2;
     int halfLongs = memCapLongs / 2;
-    try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem = wrh.getWritable();
+    try (WritableMemory mem = WritableMemory.allocateDirect(memCapacity)) {
       mem.clear();
 
       for (int i = 0; i < halfLongs; i++) {
@@ -77,10 +75,9 @@ public class WritableDirectCopyTest {
   }
 
   @Test
-  public void checkCopyWithinNativeOverlap() throws Exception {
+  public void checkCopyWithinNativeOverlap() {
     int memCapacity = 64;
-    try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem = wrh.getWritable();
+    try (WritableMemory mem = WritableMemory.allocateDirect(memCapacity)) {
       mem.clear();
       //println(mem.toHexString("Clear 64", 0, memCapacity));
 
@@ -93,37 +90,33 @@ public class WritableDirectCopyTest {
   }
 
   @Test
-  public void checkCopyWithinNativeSrcBound() throws Exception {
+  public void checkCopyWithinNativeSrcBound() {
     int memCapacity = 64;
-    try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem = wrh.getWritable();
+    try (WritableMemory mem = WritableMemory.allocateDirect(memCapacity)) {
       mem.copyTo(32, mem, 32, 33);  //hit source bound check
       fail("Did Not Catch Assertion Error: source bound");
-    } catch (IllegalArgumentException e) {
+    } catch (MemoryBoundsException e) {
       //pass
     }
   }
 
   @Test
-  public void checkCopyWithinNativeDstBound() throws Exception {
+  public void checkCopyWithinNativeDstBound() {
     int memCapacity = 64;
-    try (WritableHandle wrh = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem = wrh.getWritable();
+    try (WritableMemory mem = WritableMemory.allocateDirect(memCapacity)) {
       mem.copyTo(0, mem, 32, 33);  //hit dst bound check
       fail("Did Not Catch Assertion Error: dst bound");
-    } catch (IllegalArgumentException e) {
+    } catch (MemoryBoundsException e) {
       //pass
     }
   }
 
   @Test
-  public void checkCopyCrossNativeSmall() throws Exception {
+  public void checkCopyCrossNativeSmall() {
     int memCapacity = 64;
 
-    try (WritableHandle wrh1 = WritableMemory.allocateDirect(memCapacity);
-         WritableHandle wrh2 = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem1 = wrh1.getWritable();
-      WritableMemory mem2 = wrh2.getWritable();
+    try (WritableMemory mem1 = WritableMemory.allocateDirect(memCapacity);
+        WritableMemory mem2 = WritableMemory.allocateDirect(memCapacity)) {
 
       for (int i = 0; i < memCapacity; i++) {
         mem1.putByte(i, (byte) i);
@@ -134,21 +127,16 @@ public class WritableDirectCopyTest {
       for (int i = 0; i < memCapacity; i++) {
         assertEquals(mem2.getByte(i), (byte) i);
       }
-      wrh1.close();
-      wrh2.close();
     }
   }
 
   @Test
-  public void checkCopyCrossNativeLarge() throws Exception {
+  public void checkCopyCrossNativeLarge() {
     int memCapacity = (2 << 20) + 64;
     int memCapLongs = memCapacity / 8;
 
-    try (WritableHandle wrh1 = WritableMemory.allocateDirect(memCapacity);
-         WritableHandle wrh2 = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem1 = wrh1.getWritable();
-      WritableMemory mem2 = wrh2.getWritable();
-
+    try (WritableMemory mem1 = WritableMemory.allocateDirect(memCapacity);
+         WritableMemory mem2 = WritableMemory.allocateDirect(memCapacity)) {
       for (int i = 0; i < memCapLongs; i++) {
         mem1.putLong(i * 8, i);
       }
@@ -163,11 +151,9 @@ public class WritableDirectCopyTest {
   }
 
   @Test
-  public void checkCopyCrossNativeAndByteArray() throws Exception {
+  public void checkCopyCrossNativeAndByteArray() {
     int memCapacity = 64;
-    try (WritableHandle wrh1 = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem1 = wrh1.getWritable();
-
+    try (WritableMemory mem1 = WritableMemory.allocateDirect(memCapacity)) {
       for (int i = 0; i < mem1.getCapacity(); i++) {
         mem1.putByte(i, (byte) i);
       }
@@ -183,12 +169,9 @@ public class WritableDirectCopyTest {
   }
 
   @Test
-  public void checkCopyCrossRegionsSameNative() throws Exception {
+  public void checkCopyCrossRegionsSameNative() {
     int memCapacity = 128;
-
-    try (WritableHandle wrh1 = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem1 = wrh1.getWritable();
-
+    try (WritableMemory mem1 = WritableMemory.allocateDirect(memCapacity)) {
       for (int i = 0; i < mem1.getCapacity(); i++) {
         mem1.putByte(i, (byte) i);
       }
@@ -210,11 +193,9 @@ public class WritableDirectCopyTest {
   }
 
   @Test
-  public void checkCopyCrossNativeArrayAndHierarchicalRegions() throws Exception {
+  public void checkCopyCrossNativeArrayAndHierarchicalRegions() {
     int memCapacity = 64;
-    try (WritableHandle wrh1 = WritableMemory.allocateDirect(memCapacity)) {
-      WritableMemory mem1 = wrh1.getWritable();
-
+    try (WritableMemory mem1 = WritableMemory.allocateDirect(memCapacity)) {
       for (int i = 0; i < mem1.getCapacity(); i++) { //fill with numbers
         mem1.putByte(i, (byte) i);
       }
diff --git a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/ZeroCapacityTest.java b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/ZeroCapacityTest.java
index 5979e37..fa500db 100644
--- a/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/ZeroCapacityTest.java
+++ b/datasketches-memory-java8/src/test/java/org/apache/datasketches/memory/internal/ZeroCapacityTest.java
@@ -24,12 +24,12 @@ import static org.testng.Assert.assertEquals;
 import java.nio.ByteBuffer;
 
 import org.apache.datasketches.memory.Memory;
-import org.apache.datasketches.memory.WritableHandle;
 import org.apache.datasketches.memory.WritableMemory;
-import org.testng.Assert;
 import org.testng.annotations.Test;
 
 /**
+ * Although allocating zero bytes may be a bug, it is tolerated in Java.
+ *
  * @author Lee Rhodes
  */
 public class ZeroCapacityTest {
@@ -43,14 +43,8 @@ public class ZeroCapacityTest {
     Memory.wrap(ByteBuffer.allocate(0));
     Memory mem3 = Memory.wrap(ByteBuffer.allocateDirect(0));
     mem3.region(0, 0);
-    WritableHandle wh = null;
-    try {
-      wh = WritableMemory.allocateDirect(0);
-      Assert.fail();
-    } catch (IllegalArgumentException ignore) {
-      if (wh != null) { wh.close(); }
-      // expected
-    }
+    WritableMemory mem = WritableMemory.allocateDirect(0);
+    mem.close();
   }
 
   @Test


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