About Prasad Saya

Prasad Saya is a software engineer with over ten years’ experience in application development, maintenance, testing and
consulting on various platforms. He is a certified Java and Java EE developer. At present his interest is in developing Java applications. He also has experience working with databases and ERP applications.

Java Direct ByteBuffer Example

ByteBuffer is an abstract class, extends Buffer and implements Comparable<ByteBuffer>. This class is defined in the java.nio package.

A buffer is a container for a fixed amount of data of a specific primitive type. There is a buffer class for each non-boolean primitive type. A ByteBuffer is a sub class of Buffer of byte primitive type.

Byte Buffer

Byte buffers are distinguished in that they can be used as the sources and targets of I/O operations. They also support several features not found in the other buffer classes:

A byte buffer can be allocated as a direct buffer.

A byte buffer can be created by mapping a region of a file directly into memory.

A byte buffer provides access to its content as either a heterogeneous or homogeneous sequence of binary data of any non-boolean primitive type, in either big-endian or little-endian byte order.

Direct and Non-direct Byte Buffers

For a direct byte buffer, the Java virtual machine will make a best effort to perform native I/O operations directly upon it. That is, it will attempt to avoid copying the buffer’s content to (or from) an intermediate buffer before (or after) each invocation of one of the underlying operating system’s native I/O operations.

A direct byte buffer may be created by invoking the allocateDirect() factory method of this class.

The buffers returned by allocateDirect() method typically have somewhat higher allocation and deallocation costs than non-direct buffers.

The contents of direct buffers may reside outside of the normal garbage-collected heap, and so their impact upon the memory footprint of an application might not be obvious. It is therefore recommended that direct buffers be allocated primarily for large, long-lived buffers that are subject to the underlying system’s native I/O operations.

A direct byte buffer may also be created by mapping a region of a file directly into memory. See MappedByteBuffer for details.

Whether a byte buffer is direct or non-direct may be determined by invoking its isDirect() method.

1. An Example

This example shows usage of a direct ByteBuffer class.

First, the example program reads a file using a direct buffer, and then with a non-direct buffer. The times taken to complete the read operation are compared. The program reads a binary file (for example a video file of type .wmv) of about 1.2 GB size. The program reads the file multiple times.

The following describes the example program code:

1.1. Create a direct byte buffer

ByteBuffer buffer = ByteBuffer.allocateDirect(1024 * 10);

1.2. Verify if buffer is direct

buffer.isDirect();

The isDirect() method returns true for a direct byte buffer and false for an non-direct buffer.

1.3. Check if buffer has a backing array

buffer.hasArray();

The hasArray() method returns false for a direct buffer and true for a non-direct buffer.

The array() method of byte buffer class returns a byte array (byte []) of the buffer’s contents. This is only valid for non-direct buffers. When used with direct buffers this method throws an exception: UnsupportedOperationException

1.4. Read the file

The input file is read using a FileChannel into a direct byte buffer. The file is read multiple times (25). Each read is from the beginning to the end of file. The total time taken to complete all the reads is recorded and printed.

Next, the program is modified to use a non-direct byte buffer. Only, the following line of the program code is changed:

From:

ByteBuffer buffer = ByteBuffer.allocateDirect(1024 * 10);

To:

ByteBuffer buffer = ByteBuffer.allocate(1024 * 10);

The program is run again and the total time taken to complete all the reads is recorded and printed – this time using a non-direct byte buffer.

3. The Program Run

Run the program with direct buffer and then with the non-direct buffer. The following are the respective outputs. Note that the program was tested on Windows 7 OS and using Java SE 7 API.

3.1. The output

3.1.1. The direct buffer program output

Is a direct buffer: true
Buffer has a backing array: false
Reading file...
Time taken (millis): 17062

3.1.2. The non-direct buffer output

Is a direct buffer: false
Buffer has a backing array: true
Reading file...
Time taken (millis): 26395

From the two outputs note that there is a time improvement in reading the file using direct byte buffer. The time taken figures were consistent over multiple program runs of both direct and non-direct buffer usage.

Newsletter

Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

Email address:

Receive Java & Developer job alerts in your Area

Leave this field empty if you're human:

Join Us

With 1,240,600 monthly unique visitors and over 500 authors we are placed among the top Java related sites around. Constantly being on the lookout for partners; we encourage you to join us. So If you have a blog with unique and interesting content then you should check out our JCG partners program. You can also be a guest writer for Java Code Geeks and hone your writing skills!

Disclaimer

All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners. Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries. Examples Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.