Home » Core Java » nio » ByteBuffer » Java Direct ByteBuffer Example

About Prasad Saya

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

This example shows the usage of direct ByteBuffer.

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.

2. The Code

DirectByteBufferExample.java

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.Path;
import java.util.Date;

public class DirectByteBufferExample {

    public static void main (String [] args)
            throws Exception {

        long startTime = new Date().getTime();

        Path path = Paths.get("testfile");
        FileChannel fileChannel = FileChannel.open(path);
	
        ByteBuffer buffer = ByteBuffer.allocateDirect(1024 * 10);
	
        System.out.println("Is a direct buffer: " + buffer.isDirect());
        System.out.println("Buffer has a backing array: " + buffer.hasArray());
        System.out.println("Reading file... ");
	
        int noOfBytesRead = fileChannel.read(buffer);

        for (int i = 0; i < 25; i++) {

            while (noOfBytesRead != -1) {

                buffer.clear();
                noOfBytesRead = fileChannel.read(buffer);
            }
		
            buffer.clear();
            fileChannel.position(0);
            noOfBytesRead = fileChannel.read(buffer);
        }

        fileChannel.close();

        long endTime = new Date().getTime();
        System.out.println("");
        System.out.println("Time taken (millis): " + (endTime - startTime));
    }
}

The above program reads a file using a direct byte buffer. To run the program with a non-direct byte buffer, replace the code on line 18 with the following:

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

NOTE: For usage of file channels with byte buffers see: java.nio.channels.FileChannel Example

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.

4. Download Java Source Code

This was an example of Java Direct ByteBuffer

Download
You can download the full source code of this example here: DirectByteBufferExample.zip
(No Ratings Yet)
Start the discussion Views Tweet it!

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you our best selling eBooks for FREE!

 

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 ....

 

Receive Java & Developer job alerts in your Area

 

Leave a Reply

avatar
  Subscribe  
Notify of