Wednesday 9 November 2016

Delving deeper with Java Native Access

The world of Java programming has always been exciting. Java won over the hearts and minds of programmers owing to its portability, ruggedness and, of course, object-oriented programming features.

However, many would argue that Java has played second fiddle to its more distinguished brethren - C and C++. That has been due to the fact that it does not offer seamless integration with dynamic linked library files (DLLs on Windows, and shared objects (SO files) on Linux). The path to integration has been through complex and often time-consuming process of Java Native Interface programming.

The Java Native Access library - which this post attempts to introduce - was developed and rolled out almost nine years ago, to mitigate the problems associated with linked library files integration. More specifically, this library allowed less of clutter and frees the developer to think and focus more on the problem, rather than get mired in complexities involving Java Native Interface. 

In the course of the years in which I have produced software using Java, I have always come across issues that required attention to certain programming aspects that went way beyond what could be achieved efficiently using Java. In most cases, I found the need to dig deeper into operating system internals in order to make certain features come alive. 

The Java Native Access Library has been around longer than the time I ever first came into contact with it. Indeed my first search yielded several blogs in prominent online Java journals. However, most were either abstruse or esoteric for me to understand. Even now, after several projects' worth of experience, most of the programs produced in such blogs, fine though that they are, throw up errors when put in practice. 

The Java Native Access Library itself depends upon a small dynamic link library to perform its intended functions. The very excellent Getting Started with JNA page provides all necessary details to get up and running in almost no time at all. What follows next, however, is an implementation of how a Java program can be built with the help of Java Native Access library.

We shall cut through the obvious and perhaps basic steps of setting up an IDE, Java SDK, and importing the required jna library. In the following example, I use jna-4.2.2.jar file.

We begin by creating a package within a newly created Java project, of course. We create an interface and write it thus:
package jna01;

import com.sun.jna.*;
import com.sun.jna.win32.StdCallLibrary;
import java.util.Arrays;
import java.util.List;

/**
 *
 * @author satadru
 */
public interface Kernel32 extends StdCallLibrary {

    public static class SYSTEMTIME extends Structure {

        public short wYear;
        public short wMonth;
        public short wDayOfWeek;
        public short wDay;
        public short wHour;
        public short wMinute;
        public short wSecond;
        public short wMilliSecond;

        @Override
        protected List getFieldOrder() {
            return Arrays.asList(new String[]{"wYear", "wMonth", "wDayOfWeek", "wDay", "wHour", "wMinute", "wSecond", "wMilliSecond"});
        }
    }

    void GetLocalTime(SYSTEMTIME result);

}


At this point, I would like to present a frank admission. The interface, and the class file that follows hereafter, is a copy from the very excellent article written by Jeff Friesen for Java World

However, there is something about this interface that sets it apart from the one that Mr. Friesen had composed over eight years ago. But before, we begin discussing the difference, the accompanying class file is presented for the impatient.


package jna01;

import com.sun.jna.*;

/**
 *
 * @author satadru
 */
public class LocalTime {

    public static void main(String[] ar) {
        Kernel32 lib = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);

        Kernel32.SYSTEMTIME tine = new Kernel32.SYSTEMTIME();

        lib.GetLocalTime(tine);

        System.out.println("Year is " + tine.wYear);
        System.out.println("Month is " + tine.wMonth);
        System.out.println("Day of Week is " + tine.wDayOfWeek);
        System.out.println("Day is " + tine.wDay);
        System.out.println("Hour is " + tine.wHour);
        System.out.println("Minute is " + tine.wMinute);
        System.out.println("Second is " + tine.wSecond);
        System.out.println("Milliseconds are " + tine.wMilliSecond);
    }

}

The instance tine has been purposely spelled that way to obviate the possibility of confusing the same with java.time.

As would be evident upon compiling and running of the project (I prefer Netbeans IDE), the results are on the expected lines. A sample output is produced below:

Year is 2016
Month is 11
Day of Week is 3
Day is 9
Hour is 17
Minute is 40
Second is 18
Milliseconds are 343

It is the interface that is most interesting part in the whole program. Mr. Friesen has produced a lucid explanation on how this functions. I would not even presume to elaborate on this, simply because there could be little value added to what he has already written. What, however, is interesting is that the interface that he wrote over eight years ago, throws up errors if produced verbatim. 

It appears that the static class [SYSTEMTIME] inside the interface needs to override the getFieldMethod() which resides in the abstract class com.sun.jna.Structure that the static class extends!

In short, the solution is to insert the overriding method:

        @Override
        protected List getFieldOrder() {
            return Arrays.asList(new String[]{"wYear", "wMonth", "wDayOfWeek", "wDay", "wHour", "wMinute", "wSecond", "wMilliSecond"});
        }

The purpose of the above method is to obtain the list of field names in the order these actually appear in the SYSTEMTIME structure of Kernel32.dll.

In fine, programming with Java Native Access is interesting. It invokes host of opportunities that are not easily replicated through pure Java coding. Through this blog post, I intended to share my initial experiences unraveling the complexities associated with native codes.












Resetting password of Amazon Kindle Paperwhite (7th Generation)

What to do to in case one forgets the password of an Amazon Kindle Paperwhite (7th Generation)? The answer is to type in  111222777  and...