Long chains created by direct Buffer::slice

Florian Weimer fw at deneb.enyo.de
Fri Jul 20 17:55:52 UTC 2018


src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template
contains this, unfortunately without further comments:

|     public $Type$Buffer slice() {
|         int pos = this.position();
|         int lim = this.limit();
|         assert (pos <= lim);
|         int rem = (pos <= lim ? lim - pos : 0);
|         int off = (pos << $LG_BYTES_PER_VALUE$);
|         assert (off >= 0);
|         return new Direct$Type$Buffer$RW$$BO$(this, -1, 0, rem, rem, off);
|     }

ByteBuffer::duplicate and ByteBuffer::asReadOnlyBuffer have similar
code.

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.  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();
|   }

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.


More information about the core-libs-dev mailing list