nio

Java Nio HeapByteBuffer Example

Photo of JJJJJune 29th, 2017Last Updated: March 12th, 2019
0 1,292 4 minutes read

This example demonstrates the usage of the Java NioHeapByteBuffer. The Java NioHeapByteBuffer is an odd class, one you will never reference directly and for good reason, it’s package private. Although it’s use is almost guaranteed when working withByteBuffers unless you opt for aDirectByteBuffer (off heap). By virtue of extendingByteBuffer, it also happens to extend Buffer and implement Comparable.
 
 
 
 
 
 

1. Introduction

A Java NioHeapByteBuffer is created via calling the following methods on theByteBuffer class:

  • allocate(int)
  • wrap(byte[], int, int)
  • wrap(byte[])

All of theget(...)andput(...)methods defined on the super abstract classByteBuffer return the current implementation owing to the fluent API design. If the actual implementation have been aHeapByteBuffer then this will surely be returned.

HeapByteBuffer further specializes intoHeapByteBufferR which is a read only implementation for aHeapByteBuffer disallowing mutations and ensuring that “views” of this type ofByteBuffer only return an instance ofHeapByteBufferR and not the superclass, thus protecting the invariant. AHeapByteBufferR instance is created by callingasReadOnlyBuffer()on an instance ofHeapByteBuffer.

2. Technologies used

The example code in this article was built and run using:

  • Java 1.8.101 (1.8.x will do fine)
  • Maven 3.3.9 (3.3.x will do fine)
  • Spring source tool suite 4.6.3 (Any Java IDE would work)
  • Ubuntu 16.04 (Windows, Mac or Linux will do fine)

3. Overview

This article builds upon a previousarticle onByteBuffers in general and I would recommend to read that article first before continuing with this one.HeapByteBuffers are simply the default implementation provided when creating aByteBuffer via the 3 methods listed in the introduction.

One way to ensure you are working with a aHeapByteBuffer implementation is to call theisDirect()method which will returnfalse forHeapByteBuffer andHeapByteBufferR implementations.

HeapByteBuffer instances are, barring escape analysis, always allocated on the Java heap and thus are wonderfully managed by the GC.DirectByteBuffers are not and thus are not easily quantifiable in terms of space.

The reasons for the differentiation stem from the fact that the Operating system can optimize IO operations onDirectByteBuffers because the bytes are guaranteed to be physically contiguous, whereas heap memory is at the whim of the GC and thus means thatHeapByteBuffer bytes may not necessarily be contiguous.

4. Test cases

Testing a HeapByteBuffer identity

public class HeapByteBufferIdentityTest {    @Test    public void isHeapBuffer() {        final ByteBuffer heapBuffer = ByteBuffer.allocate(5 * 10000);        final ByteBuffer directBuffer = ByteBuffer.allocateDirect(5 * 10000);        assertTrue("Must be direct", directBuffer.isDirect());        assertTrue("Must not be direct", !heapBuffer.isDirect());    }    @Test    public void persistenIdentityChecker() {        final ByteBuffer buffer = ByteBuffer.allocate(5 * 10000);        check(buffer, (a) -> !a.duplicate().isDirect());        check(buffer, (a) -> !a.slice().isDirect());        check(buffer, (a) -> !a.put("I am going to trick this buffer".getBytes()).isDirect());        check(buffer, (a) -> !a.asIntBuffer().isDirect());        check(buffer, (a) -> !a.asCharBuffer().isDirect());        check(buffer, (a) -> !a.asFloatBuffer().isDirect());    }    private void check(final ByteBuffer buffer, final Predicate<? super ByteBuffer> action) {        assertTrue(action.test(buffer));    }}
  • line 24-26: we accept a predicate which asserts the fact that theHeapByteBuffer stays aHeapByteBuffer regardless of the operation we performed on it.

Testing a HeapByteBuffer memory vs DirectByteBuffer

public class HeapByteBufferMemoryTest {    private static final Runtime RUNTIME = Runtime.getRuntime();    private ByteBuffer heapBuffer;    private ByteBuffer directBuffer;    private long startFreeMemory;    @Before    public void setUp() {        this.startFreeMemory = RUNTIME.freeMemory();    }    @Test    public void memoryUsage() {        this.heapBuffer = ByteBuffer.allocate(5 * 100000);        long afterHeapAllocation = RUNTIME.freeMemory();        assertTrue("Heap memory did not increase", afterHeapAllocation > this.startFreeMemory);        this.directBuffer = ByteBuffer.allocateDirect(5 * 100000);        assertTrue("Heap memory must not increase", RUNTIME.freeMemory() >= afterHeapAllocation);    }}
  • In this test case we attempt to prove that allocating aHeapByteBuffer will have an impact on heap memory usage whereas the allocation of aDirectByteBuffer will not.

Testing the read only properties of a HeapByteBuffer

public class HeapByteBufferReadOnlyTest {    private ByteBuffer buffer;    @Before    public void setUp() {        this.buffer = ByteBuffer.allocate(5 * 10000);    }    @Test(expected = ReadOnlyBufferException.class)    public void readOnly() {        this.buffer = this.buffer.asReadOnlyBuffer();        assertTrue("Must be readOnly", this.buffer.isReadOnly());        this.buffer.putChar('b');    }    @Test(expected = ReadOnlyBufferException.class)    public void readOnlyWithManners() {        this.buffer = this.buffer.asReadOnlyBuffer();        assertTrue("Must be readOnly", this.buffer.isReadOnly());        this.buffer.put("Please put this in the buffer".getBytes());    }    @Test    public void persistenReadOnlyChecker() {        this.buffer = buffer.asReadOnlyBuffer();        check(this.buffer, (a) -> a.duplicate().put("I am going to trick this buffer".getBytes()));        check(this.buffer, (a) -> a.slice().put("I am going to trick this buffer".getBytes()));        check(this.buffer, (a) -> a.put("I am going to trick this buffer".getBytes()));        check(this.buffer, (a) -> a.asIntBuffer().put(1));        check(this.buffer, (a) -> a.asCharBuffer().put('c'));        check(this.buffer, (a) -> a.asFloatBuffer().put(1f));    }    private void check(final ByteBuffer buffer, final Consumer>? super ByteBuffer< action) {        try {            action.accept(buffer);            fail("Must throw exception");        } catch (ReadOnlyBufferException e) {        }    }}
  • lines 35-41: we invoke a function that should throw aReadOnlyBufferException proving the property of read only despite creating a different view of theHeapByteBuffer through it’s api. Various methods are called ranging fromput(...)toduplicate(),sice() etc. to try and break this property

Cloning a HeapByteBuffer into a DirectByteBuffer

Want to be a Java NIO Master ?
Subscribe to our newsletter and download the JDBCUltimateGuideright now!
In order to help you master Java NIO Library, we have compiled a kick-ass guide with all the major Java NIO features and use cases! Besides studying them online you may download the eBook in PDF format!

Thank you!

We will contact you soon.

public class HeapByteBufferIdentityCrisisTest {    @Test    public void shapeShift() {        final ByteBuffer buffer = ByteBuffer.wrap("Hello world!".getBytes());        assertTrue("Not a heap buffer", !buffer.isDirect());                final ByteBuffer shapeShifter = ByteBuffer.allocateDirect(buffer.capacity()).put(getBytes(buffer));        assertTrue("Not a direct buffer", shapeShifter.isDirect());                shapeShifter.flip();        byte [] contents = new byte[shapeShifter.capacity()];        shapeShifter.get(contents);                assertEquals("Invalid text", "Hello world!", new String(contents).trim());    }        private byte [] getBytes(final ByteBuffer buffer) {        byte [] dest = new byte[buffer.remaining()];        buffer.get(dest);        return dest;    }}
  • lines 18-22 we copy the bytes (remaining) betweenpositionandlimitinto a destinationbyte []. This is to ensure that the content of the originalHeapByteBuffer are exumed and made ready for insertion into a comingDirectByteBuffer
  • I did not concern myself with encoding and decoding explicitness in this test. I refer you to a previousarticle in this series which does those test cases explicit in theCharset usage during encoding and decoding.

5. Summary

This example demonstrated the creation and usage of aHeapByteBuffer implementation of aByteBuffer. It proved properties of the API and attempted to demonstrate the core difference in implementation between this and aDirectByteBuffer in terms of memory allocation.

6. Download the source code

This was a Java Nio HeapByteBuffer example.

Download
You can download the full source code of this example here:Java Nio HeapByteBuffer example
Do you want to know how to develop your skillset to become aJava Rockstar?
Subscribe to our newsletter to start Rockingright now!
To get you started we give you our best selling eBooks forFREE!
1. JPA Mini Book
2. JVM Troubleshooting Guide
3. JUnit Tutorial for Unit Testing
4. Java Annotations Tutorial
5. Java Interview Questions
6. Spring Interview Questions
7. Android UI Design
and many more ....
I agree to theTerms andPrivacy Policy

Thank you!

We will contact you soon.

Tags
Photo of JJJJJune 29th, 2017Last Updated: March 12th, 2019
0 1,292 4 minutes read
Photo of JJ

JJ

Jean-Jay Vester graduated from the Cape Peninsula University of Technology, Cape Town, in 2001 and has spent most of his career developing Java backend systems for small to large sized companies both sides of the equator.He has an abundance of experience and knowledge in many varied Java frameworks and has also acquired some systems knowledge along the way.Recently he has started developing his JavaScript skill set specifically targeting Angularjs and also bridged that skill to the backend with Nodejs.
Subscribe
Notify of
guest
I agree to theTerms andPrivacy Policy
The comment form collects your name, email and content to allow us keep track of the comments placed on the website. Please read and accept our website Terms and Privacy Policy to post a comment.

I agree to theTerms andPrivacy Policy
The comment form collects your name, email and content to allow us keep track of the comments placed on the website. Please read and accept our website Terms and Privacy Policy to post a comment.