Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Enhance your Java application with Java Native Interface (JNI)

How to compete with native applications without sacrificing cross-platform benefits

  • Print
  • Feedback

Page 4 of 7

/**
* Loads the JNI library, if available.
*
* * Must be called before images are loaded and instances are created. **/ public static boolean initialize() { // Load JNI library try { System.loadLibrary( "DesktopIndicator" ); } catch( UnsatisfiedLinkError x ) { return false; } return true; }


Note that we are catching unsatisfied link exceptions because we want to deal gracefully with platforms that do not support this feature.

As for images, it makes sense to load them internally. Operating systems usually have internal structures for handling image lists that are far more efficient than loading them from a file. If we want to have a lot of blinking and icon changes, we will want the images loaded and cached before use. To make things simpler, we'll have one global image list for all instances, so this, too, will be a static method:

/**
* Loads an image file to memory.
*
* * The image is loaded from the filename parameter, while the tool tip is * supplied in the tool tip parameter. The image file must be in a format * recognized by the native platform (for example, a ICO file for Win32). *
* * A return value of -1 indicates failure. Otherwise, it is the handle of * the image to be used for desktop indicators. **/ public static int loadImage( String filename ) { try { return nativeLoadImage( filename ); } catch( UnsatisfiedLinkError x ) { return -1; } }


This method is a wrapper for a private native method that adds graceful handling of exceptions. A good convention for this kind of situation is to give the native version a native prefix, because otherwise these methods are identical:

private synchronized static native int nativeLoadImage( String filename ) throws UnsatisfiedLinkError;


Note that we are synchronizing the native method, rather than doing our own internal synchronization in the native code. The latter procedure is potentially tricky, since native synchronization services do not necessarily have anything to do with those of a JVM; a JVM implements its own threads. We'll go further into threads when we get into the native code.

The other methods are quite obvious. They handle the showing and hiding of the indicator, and the updating of the image and tool tip. We will add one special private field:

private int handler = 0;


This field is not used by the Java code at all, and is meant as a placeholder for the native code to keep a link to an equivalent underlying native class, called DesktopIndicatorHandler.

We now have our wrapper, and the design seems generic enough to be ported to other platforms. Let's go native!

Walking the walk

Our native methods must somehow be converted to native code entry points. Javah, an integral tool of the JDK, generates a standard C/C++ header file from our Java source. Let's run Javah on our wrapper class:

> javah DesktopIndicator


Our C/C++ header starts with this:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include < jni.h >
/* Header for class DesktopIndicator */
#ifndef _Included_DesktopIndicator
#define _Included_DesktopIndicator
#ifdef __cplusplus


The header file includes jni.h, so it must be used in conjunction with the other C header files in the JDK that define various types and classes used.

  • Print
  • Feedback

Resources
  • JNI resources in JavaWorld: