Long chains created by direct Buffer::slice

Paul Sandoz paul.sandoz at oracle.com
Fri Jul 27 00:02:18 UTC 2018


+1 

I created this issue:

  https://bugs.openjdk.java.net/browse/JDK-8208362

The suggested fix requires a tweak though since an instance of a DirectBuffer interface is passed. This is required because views over direct ByteBuffers can be created.

Florian, i will push tomorrow and assign you as at the contributor.

Paul.

diff -r 448cd909c9e2 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	Thu Jul 26 11:53:59 2018 -0700
+++ b/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template	Thu Jul 26 16:46:20 2018 -0700
@@ -194,7 +194,8 @@
 #if[byte]
         cleaner = null;
 #end[byte]
-        att = db;
+        Object attachment = db.attachment();
+        att = (attachment == null ? db : attachment);
 #else[rw]
         super(db, mark, pos, lim, cap, off);
         this.isReadOnly = true;

> On Jul 20, 2018, at 11:15 AM, mark.reinhold at oracle.com wrote:
> 
> 2018/7/20 10:55:52 -0700, Florian Weimer <fw at deneb.enyo.de>:
>> ...
>> 
>> The constructor invoked:
>> 
>> |     // For duplicates and slices
>> |     //
>> |     Direct$Type$Buffer$RW$$BO$(DirectBuffer db,         // package-private
>> |                                int mark, int pos, int lim, int cap,
>> |                                int off)
>> |     {
>> | #if[rw]
>> |         super(mark, pos, lim, cap);
>> |         address = db.address() + off;
>> | #if[byte]
>> |         cleaner = null;
>> | #end[byte]
>> |         att = db;
>> | #else[rw]
>> |         super(db, mark, pos, lim, cap, off);
>> |         this.isReadOnly = true;
>> | #end[rw]
>> |     }
>> 
>> The key part is the assignment to the att member.  If I understand
>> this correctly, it is needed to keep the backing object alive during
>> the lifetime of this buffer.
> 
> Correct.
> 
>>                              However, it causes the creation of a
>> long chain of buffer objects.  With -Xmx100m or so, the following test
>> will OOM fairly quickly for this reason:
>> 
>> |   volatile ByteBuffer buffer;
>> |   …
>> |   buffer = ByteBuffer.allocateDirect(16384);
>> |   while (true) {
>> |       buffer = buffer.duplicate();
>> |   }
> 
> Well spotted!  This bug has been lurking there for sixteen years.
> 
>> 
>> I wonder if it would be possible to change the setting of the att
>> member to this instead:
>> 
>> |         if (db.att == null) {
>> |             att = db;
>> |         } else {
>> |             att = db.att;
>> |         }
>> 
>> This would only keep the object alive which actually owns the backing
>> storage, as if Buffer::slice had been invoked on it directly.
> 
> Your suggested fix looks fine.
> 
> - Mark



More information about the core-libs-dev mailing list