Comments
Richard Davies wrote: The UK has a good crop of technology pioneers in cloud computing - for example ElasticHosts, FlexiScale, Flexiant, OnApp - and also some strong government initiatives such as G-Cloud. We will have to see whether this kind of technical leadership converts into swift mass-market adoption or not.
Cloud Expo on Google News


2008 West
DIAMOND SPONSOR:
Data Direct
SOA, WOA and Cloud Computing: The New Frontier for Data Services
PLATINUM SPONSORS:
Red Hat
The Opening of Virtualization
GOLD SPONSORS:
Appsense
User Environment Management – The Third Layer of the Desktop
Cordys
Cloud Computing for Business Agility
EMC
CMIS: A Multi-Vendor Proposal for a Service-Based Content Management Interoperability Standard
Freedom OSS
Practical SOA” Max Yankelevich
Intel
Architecting an Enterprise Service Router (ESR) – A Cost-Effective Way to Scale SOA Across the Enterprise
Sensedia
Return on Assests: Bringing Visibility to your SOA Strategy
Symantec
Managing Hybrid Endpoint Environments
VMWare
Game-Changing Technology for Enterprise Clouds and Applications
Click For 2008 West
Event Webcasts

2008 West
PLATINUM SPONSORS:
Appcelerator
Get ‘Rich’ Quick: Rapid Prototyping for RIA with ZERO Server Code
Keynote Systems
Designing for and Managing Performance in the New Frontier of Rich Internet Applications
GOLD SPONSORS:
ICEsoft
How Can AJAX Improve Homeland Security?
Isomorphic
Beyond Widgets: What a RIA Platform Should Offer
Oracle
REAs: Rich Enterprise Applications
Click For 2008 Event Webcasts
SYS-CON.TV
Top Links You Must Click On


Understanding the Native Java Interface
Understanding the Native Java Interface

The evolution of Java has been truly mind-boggling, and quite unlike anything we have ever seen before in the computing domain. Seldom does a day go by without yet another software vendor pledging allegiance to the Java paradigm. Today, few among us will question the power and flexibility of Java. Still, one may ask, "Can Java, by itself, meet all our needs?" The answer to that question was given indirectly by the designers of the language itself when they made allowances for extending the reach of Java through a standard interface utilizing native methods.

So, what exactly are native methods, you ask? Simply put, they are methods which are implemented not in Java itself, but in a different language like C or C++. The methods are compiled into either a DLL or a shared library, depending on the target platform.

Prior to JDK 1.1, the native method interface itself varied quite a bit, depending on the vendor implementing it. Here, the standard native method interface offered by Sun's JDK was replaced by proprietary interfaces like Microsoft's Raw Native Interface (RNI) and Netscape's Java Runtime Interface (JRI) within their respective JVM implementations. For a while, it almost seemed as if Sun's "Write Once, Run Anywhere" clarion call did not apply to Java applications using native methods!

But as with everything else related to Java, the native method interface itself has come a long way since those rough and tumble days. The Java development community (at least those visionary enough to recognize the futility of having to "customize" Java programs for every vendor's JVM) heaved a collective sigh of relief when Sun announced a unifying native method interface called the Java Native Interface (JNI). The JNI, available as an integral part of JDK 1.1, was developed following extensive consultations between JavaSoft and other Java licensees. Although it borrows heavily from Netscape's JRI, JNI holds the promise of making the native method implementation truly independent of the underlying JVM. It should be noted, however, that so far Microsoft has been a holdout on adopting the JNI standard, and has announced that it would support native methods via the RNI and Java/COM interfaces instead.

Why Use Native Methods?
The ability to invoke functionality implemented in C or C++ may be the only way to solve certain types of problems, while still working within the Java paradigm. What if you wanted to write a Java application that needed to directly access a modem or a sound card? Or perhaps your Java servers needed to source data from a data repository that came with its own non-Java API? In short, if your Java application ever needed to access functionality that was not made available via the JDK or third party Java class libraries, or it needed to take advantage of easily available C'-based APIs, taking the native method route is quite possibly the only way out.

Even if you do not have any need for accessing peripheral devices, native methods can facilitate the integration of tried and tested legacy code without causing extensive rewrite.

Some developers have even rationalized that the lack of speed in Java applications is yet another reason to implement core functionality within native methods. While it is true that a C or C++ native method would be much faster than its pure Java counterpart, implementing something as native solely for the sake of speed is a short-sighted move at best! This is especially true considering that Java execution speeds have shown significant improvements over the past few months with the emergence of highly efficient Java Virtual Machines and Just-In-Time (JIT) compilers.

The Flip Side
Before you bring out your trusty old C or C++ compiler, be sure to understand some of the shortcomings in using native methods. It certainly raises the bar a couple of notches in that now the developer not only has to be a competent Java programmer, but also must be proficient in whichever language they may choose for the native method implementation. Furthermore, the portability of your Java application is also substantially curbed since now you need to re-implement your shared library or DLL for each and every platform your application needs to run under. This may not be a particularly easy task, especially considering that a platform's proprietary features may be utilized in implementing the native method functionality.

It is important to note that native methods can be used only as part of Java applications, and not within applets. The security manager implementations in both Netscape's Navigator and Microsoft's Internet Explorer browsers currently disallow the loading of applets that link to shared libraries over the network. However, there is a possibility that future implementations may allow the user to modify the default browser settings. Then, applets containing native methods can at least be run in an Intranet mode, behind a corporate firewall if need be.

Six Steps to Native Method Success!
All native methods written to the JNI standard have the following six steps in common:
1. Develop the Java code
2. Compile the Java code to a class file
3. Generate the header file
4. Implement the native method
5. Create the shared library or DLL
6. Run the Java program

Now, let us delve into the details with a simple example. Our example program, NativeQuote.java, invokes the native method quote which in turn displays a popular quote as output. Please note that our example programs show a strong bias towards Sun's Solaris operating environment and uses C' to implement the native method functionality.

Develop the Java Code
Consider

public native void quote();

The presence of the keyword native within the declaration of the method quote indicates that the method is implemented outside of Java, in a different programming language. Also note that the native methods are always just merely declared within the class and are never implemented, unlike regular Java methods.

The static block

static {
System.loadLibrary("nativequote");
}

tells Java to load the shared library within which it can find the native method implementation. Since we are assuming a Solaris platform for this example, the shared library libnativequote.so is dynamically loaded at run time. If we were to implement the shared library under Windows 95 or NT, then Java would try to load nativequote.dll instead. It is important that the path of the shared library is present within the Java environment variable LD_LIBRARY_PATH.

The main method creates an instance of the class NativeQuote and invokes the native method quote.

Compile the Java Code to a Class File
Nothing new here. Compile the Java source file as usual to obtain the class file.

javac NativeQuote.java &127;

Generate the Header File
The javah utility given to you as part of the JDK is applied on the Java class file to generate the JNI header file. JNI, unlike the native method specification under JDK 1.02, does not make use of stub files.

javah -jni NativeQuote.java

The generated header file is always named after the Java class file, which contains the native method declaration. In this case, the header file NativeQuote.h is generated by javah.

Implement the Native Method
We can obtain the native function prototype from the generated header file, NativeQuote.h, shown in Listing 2.

The stdio.h header file is needed in our implementation, marvinQuote.c (Listing 3), since we make use of the printf function.

Create the Shared Library or DLL.
This step is platform-dependent and your library can be implemented either as a shared object under Solaris, or as a DLL under Windows 95 or NT. Under Solaris, the shared object can be created by using the following compiler options:

cc -G marvinQuote.c -I$JAVAHOME/include
-I$JAVAHOME/include/solaris -o libnativequote.so

For Windows NT/Windows 95 use:

cl marvinQuote.c -I$JAVAHOME\include -I$JAVAHOME\
include\win32 -Fenativequote1.dll -MD -LD -nologo
$JAVAHOME\lib\javai.lib

Run the Java Program
Assuming that the environment variable, LD_LIBRARY_PATH, contains the path of the shared library, when the application is run as:

java NativeQuote

we should see Marvin the Martian's famous quote as the output:

"Where's the kaboom? There was supposed to be an earth-shattering kaboom!" -- Marvin the Martian

Invoking Java Methods From Native Methods
JNI supports the seamless invocation of Java methods from within native methods. We will see how the recursive Java method factorial, which is a part of the Factorial.java shown in Listing 4, can be invoked from within the native method computeFact shown in Listing 5. The example also shows us how we can pass data to and from native methods.

On running the Java program as

java Factorial

we get the output:

Factorial(5) = 120

We create the shared library fact containing the native implementation, as explained earlier. Also, the function prototype for computeFact is obtained from the header file, Factorial.h, that is generated by applying javah on the compiled class file.

Java methods can be invoked from within native methods by following the following five-step approach:

Step 1: Obtain the class type to which the Java object belongs using the GetObjectClass accessor function

Step 2: Get the Java method ID, by passing the method name and its signature to the function GetMethodID.

The general form of a method signature is

"(argument-types)return-type"

In our example, the Java method factorial takes in an int and returns a double. From Table 1, we can deduce its method signature as (I)D.

Step 3: Initialize the parameters to the Java method, if any. In the above example, we initialize the integer parameter x to 5.

Step 4: Use the appropriate CallMethod accessor function to invoke the Java method. For our example, since the Java method factorial returns a double we make use of the CallDoubleMethod accessor function.

Table 2 shows the various CallMethod functions available, based on the return type from the Java method invocation.

Step 5: Convert any returned Java object to its native method equivalent. For our example, since we have an equivalent native method type (jdouble) for the Java primitive type double, no conversion is necessary.

A highlight of JNI methods is that they are source-portable across platforms as long as the target platform is JNI-compatible and the native method does not make use of any system-dependent functionality. Table 3 shows the equivalent native types for Java data types.

Accessing Java Fields From Native Methods
JNI provides you with numerous accessor functions to seamlessly access and set Java fields from within native methods. Listing 6 is an example Java program whose data is accessed and changed by the native method implementation shown in Listing 7.

We see from Listing 7 how easy it is to access any Java field from within a native method. After first obtaining the class to which the parent object belongs, we obtain the field id of the target field. It is important to provide the correct field name and signature at this stage. After this, accessing or changing the value of the field is just a matter of calling the appropriate GetField() or SetField() accessor function. Tables 4 and 5 show the available functions for accessing or modifying Java fields.Throwing Exceptions
Any number of things could potentially go wrong within a native method. In such an eventuality, it is imperative for us to pass along the exception so that it can be properly handled within regular Java methods. The JNI provides functionality for exactly such an eventuality via the Throw, ThrowNew and FatalError accessor functions.

Throw and ThrowNew are used to trigger exceptions from within the native method implementation. For example, consider the following code segments:

(*env)->Throw(env, new java/lang/IllegalArgumentException);

and

(*env)->ThrowNew(env, java/lang/IllegalArgumentException, "Some diagnostic message");

Both of the above enable IllegalArgumentException to be passed over to the parent Java object. JNI also provides for more catastrophic situations by providing the FatalError accessor function.

These types of errors are unrecoverable and typically result in the JVM exiting. The following code snippet is a good example of the usage of FatalError:

(*env)->FatalError(env, "Out of memory! Exiting!");

Using Native Methods in a Multithreaded Environment
Native methods can certainly be accessed by more than one thread concurrently within Java. For example:

public synchronized native void someNativeMethod();

indicates that someNativeMethod can be used in a multithreaded environment.

JNI also provides for data-locking, permitting thread-safe operations within native methods via a monitor-based mechanism. The MonitorEnter() and MonitorExit() accessor functions are instrumental in setting up a critical region for shared data, so that they can be accessed by concurrent threads of execution.

Conclusion
The native methods interface has been totally revamped under JDK 1.1. The new standard - JNI - offers greater power and flexibility to advanced Java developers who need to extend Java's reach into legacy systems, peripheral devices, etc. JNI also promises to make your native method implementations portable across all JVM's adopting this new standard.

Native methods come at a price, however. Currently, they cannot be used within downloadable applets and, consequently, are practical only within stand-alone applications. Native method development itself is not a trivial task, and needs developer expertise not only in Java but also the native implementation language.

About Govind Seshadri
Govind Seshadri is a Lead Systems Analyst for a leading financial services company and heads a major Java client/server initiative.

In order to post a comment you need to be registered and logged in.

Register | Sign-in

Reader Feedback: Page 1 of 1

Enterprise Open Source Magazine Latest Stories . . .
Apache Deltacloud, the Red Hat-contributed ReSTful API that abstracts differences between clouds so services on any cloud can be managed – provided of course there’s a driver – has graduated from the Apache Foundation’s incubator and is now a full-fledged Top-Level Project (TLP). The...
With Cloud Expo 2012 New York (10th Cloud Expo) just four months away, what better time to start introducing you in greater detail to the distinguished individuals in our incredible Speaker Faculty for the technical and strategy sessions at the conference... We have technical and st...
AMD said late Tuesday that its chief sales officer Emilio Ghilardi had left the company and that CEO and president Rory Read is going to do his job while a replacement is sought. AMD didn’t say why Ghilardi left but it’s assumed Read wants his own people. Read is relatively new to th...
During the lifespan of M3 (Monitis Monitor Manager) there has always been something lacking – timers. M3 execution procedure was outlined in this previous article. The execution mentioned in the latter was a one-time-execution, whereas server monitoring requires periodic invocati...
Red Hat is putting its bought-in Gluster scale-out NAS storage technology, acquired in October, on the Amazon cloud. It’s styled Red Hat Virtual Storage Appliance for Amazon Web Services and other clouds are supposed to follow in short order.
A new episode of the screencast series is now available at the OpenNebula YouTube Channel. This screencast demonstrates the new easily-customizable self-service portal for cloud consumers. Its aim is to offer a simplified access to shared infrastructure for non-IT end users. The scree...
Subscribe to the World's Most Powerful Newsletters
Subscribe to Our Rss Feeds & Get Your SYS-CON News Live!
Click to Add our RSS Feeds to the Service of Your Choice:
Google Reader or Homepage Add to My Yahoo! Subscribe with Bloglines Subscribe in NewsGator Online
myFeedster Add to My AOL Subscribe in Rojo Add 'Hugg' to Newsburst from CNET News.com Kinja Digest View Additional SYS-CON Feeds
Publish Your Article! Please send it to editorial(at)sys-con.com!

Advertise on this site! Contact advertising(at)sys-con.com! 201 802-3021


SYS-CON Featured Whitepapers
ADS BY GOOGLE