On 14/02/2018 10:43 PM, David Holmes wrote:
Adding in core-libs-dev as there's nothing related to hotspot directly here.


Correction, this is of course leading to a proposed change in hotspot to implement the new Unsafe methods and perform the native memory tracking. Of course we already have NMT so the obvious question is how this will fit in with NMT?

David

David

On 14/02/2018 9:32 PM, Adam Farley8 wrote:
Hi All,

Currently, diagnostic core files generated from OpenJDK seem to lump all
of the
native memory usages together, making it near-impossible for someone to
figure
out *what* is using all that memory in the event of a memory leak.

The OpenJ9 VM has a feature which allows it to track the allocation of
native
memory for Direct Byte Buffers (DBBs), and to supply that information into
the
cores when they are generated. This makes it a *lot* easier to find out
what is using
all that native memory, making memory leak resolution less like some dark
art, and
more like logical debugging.

To use this feature, there is a native method referenced in Unsafe.java.
To open
up this feature so that any VM can make use of it, the java code below
sets the
stage for it. This change starts letting people call DBB-specific methods
when
allocating native memory, and getting into the habit of using it.

Thoughts?

Best Regards

Adam Farley

P.S. Code:

diff --git
a/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template
b/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template
--- a/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template
+++ b/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template
@@ -85,7 +85,7 @@
                  // Paranoia
                  return;
              }
-            UNSAFE.freeMemory(address);
+            UNSAFE.freeDBBMemory(address);
              address = 0;
              Bits.unreserveMemory(size, capacity);
          }
@@ -118,7 +118,7 @@
          long base = 0;
          try {
-            base = UNSAFE.allocateMemory(size);
+            base = UNSAFE.allocateDBBMemory(size);
          } catch (OutOfMemoryError x) {
              Bits.unreserveMemory(size, cap);
              throw x;
diff --git a/src/java.base/share/classes/jdk/internal/misc/Unsafe.java
b/src/java.base/share/classes/jdk/internal/misc/Unsafe.java
--- a/src/java.base/share/classes/jdk/internal/misc/Unsafe.java
+++ b/src/java.base/share/classes/jdk/internal/misc/Unsafe.java
@@ -632,6 +632,26 @@
      }
      /**
+     * Allocates a new block of native memory for DirectByteBuffers, of
the
+     * given size in bytes.  The contents of the memory are
uninitialized;
+     * they will generally be garbage.  The resulting native pointer will
+     * never be zero, and will be aligned for all value types.  Dispose
of
+     * this memory by calling {@link #freeDBBMemory} or resize it with
+     * {@link #reallocateDBBMemory}.
+     *
+     * @throws RuntimeException if the size is negative or too large
+     *                          for the native size_t type
+     *
+     * @throws OutOfMemoryError if the allocation is refused by the
system
+     *
+     * @see #getByte(long)
+     * @see #putByte(long, byte)
+     */
+    public long allocateDBBMemory(long bytes) {
+        return allocateMemory(bytes);
+    }
+
+    /**
       * Resizes a new block of native memory, to the given size in bytes.
The
       * contents of the new block past the size of the old block are
       * uninitialized; they will generally be garbage.  The resulting
native
@@ -687,6 +707,27 @@
      }
      /**
+     * Resizes a new block of native memory for DirectByteBuffers, to the
+     * given size in bytes.  The contents of the new block past the size
of
+     * the old block are uninitialized; they will generally be garbage.
The
+     * resulting native pointer will be zero if and only if the requested
size
+     * is zero.  The resulting native pointer will be aligned for all
value
+     * types.  Dispose of this memory by calling {@link #freeDBBMemory},
or
+     * resize it with {@link #reallocateDBBMemory}.  The address passed
to
+     * this method may be null, in which case an allocation will be
performed.
+     *
+     * @throws RuntimeException if the size is negative or too large
+     *                          for the native size_t type
+     *
+     * @throws OutOfMemoryError if the allocation is refused by the
system
+     *
+     * @see #allocateDBBMemory
+     */
+    public long reallocateDBBMemory(long address, long bytes) {
+        return reallocateMemory(address, bytes);
+    }
+
+    /**
       * Sets all bytes in a given block of memory to a fixed value
       * (usually zero).
       *
@@ -918,6 +959,17 @@
          checkPointer(null, address);
      }
+    /**
+     * Disposes of a block of native memory, as obtained from {@link
+     * #allocateDBBMemory} or {@link #reallocateDBBMemory}.  The address
passed
+     * to this method may be null, in which case no action is taken.
+     *
+     * @see #allocateDBBMemory
+     */
+    public void freeDBBMemory(long address) {
+        freeMemory(address);
+    }
+
      /// random queries
      /**

Unless stated otherwise above:
IBM United Kingdom Limited - Registered in England and Wales with number
741598.
Registered office: PO Box 41, North Harbour, Portsmouth, Hampshire PO6 3AU

Reply via email to