Enhance your Java application with Java Native Interface (JNI)
Tutorial Details:
Enhance your Java application with Java Native Interface (JNI)
Enhance your Java application with Java Native Interface (JNI)
By: By Tal Liron
How to compete with native applications without sacrificing cross-platform benefits
o, you're going to develop a great new application. Java's cross-platform promises bring a twinkle to the eyes of your marketing people, but after a test run on a group of innocent users, you're not so sure Java can deliver the goods.
The main deficiency Java applications seem to have is that they do not look and feel like native applications. The reasons behind this are obvious: 100% Pure Java must support the lowest common denominator, but there are many platform-specific features and quirks that the users of specific platforms expect, and your application will seem to be lacking without them.
In today's competitive application arena, these features may be critically necessary to your application's marketplace success. A competitor's native application can use these features to beat your Java application every time, producing a product that's faster, looks and feels right, and works with the operating system and other native applications as expected.
The solution, of course, is to use Java Native Interface (JNI) extensions. But what will this mean for Java's cross-platform capabilities? If your application is only 60% Pure Java, it won't run on other platforms -- so why use Java at all? Admittedly, Java has other benefits: the language is easy to learn and use, the code is simple to maintain and debug, and by using it you leave open the possibility of migrating to other platforms in the future -- if you design your application with such migration in mind.
So, is JNI a compromise? It doesn't have to be. You can have a 100% Pure Java application in which JNI features are added benefits that appear only on specific platforms. There will be no loss for those who use the platforms not supported by your JNI features, and you will compete with native applications on equal terms where needed. The trick is to design an application that can take advantage of JNI features, but is still fully operational without them.
(Although Microsoft's virtual machine does not support JNI, it has many Windows-specific packages of features that give the same result: powerful native support. Unlike JNI extensions, however, you cannot replace these features with an alternate JNI library for an additional platform. If you use these Windows-specific features, you're committed to Windows and Microsoft's VM.)
Bonus features
Start out with a 100% Pure Java application design. Think of the application as being contained entirely within the virtual machine, which is otherwise platform neutral. All your features must be based on whatever the Java platform has to offer. When you're finished, congratulate yourself! Your design will work on any Java Virtual Machine (JVM) running on any platform.
Next, look at your Java application from a user's point of view. It's probably not the only application running in his or her environment. What features is your application lacking that its native neighbors have? Run a few native applications together with yours, and ask yourself some questions about the differences:
Do the native apps have special widgets that your application lacks? Tool tips are common, and so are context menus, but what about collapsing/expanding, minimizing/maximizing, and showing/hiding? Some GUIs have special popup messages and automatic behaviors. There's really no limit to what some people think users want.
Do both types of app handle special mouse and key combinations in the same way? Java makes no special assumptions about the number of mouse buttons, but many platforms do. Keyboards are largely standardized, but there are exceptions; some keyboards (and some platforms) have more specialized keys than others. Native applications may exhibit special operating system behavior for special key combinations.
Can your application interoperate with the natives? Can you drag and drop between them? What types of objects does each accept? Dragging files is common, but are other objects commonly dragged in or pasted?
How does your application interact with the desktop? Some platforms have very cluttered desktops, supporting taskbars, flashing messages, context menus, and even Web content. Do the native applications use these features? (This article will handle the taskbar icon feature in Windows, with which you can add application-defined icons to the desktop taskbar that indicate status without requiring an open window.)
How does your application interact with the operating system, as compared to the native applications? Do they handle special OS events, such as hibernation and input methods, in similar ways? Do they converse with system databases or registries? Do they write to a system event log?
Look at your list of missing features, and don't underestimate its importance. You may not like these features, finding them weird and difficult to understand, but that's just because you're not used to that platform. The average user knows them, uses them, and will expect to find them in your application. Unless your application provides functionality that is not available elsewhere, or is extremely cheap, users will always prefer native options.
But don't go overboard. Some features are so obscure or unpopular that their absence won't be noticed. Filter such features out, and list only the essentials. Try to think of these as features you want and not just obstacles to overcome. Thinking positively always helps.
The most important thing is to treat these features as an added benefit (or an annoying redundancy, if you prefer) for users of a specific platform, but never as features essential to the functioning of the application. Your app should be entirely and fully usable on either the Standard or Micro edition of the Java platform. This is the only way to protect the application's cross-platform portability -- and considering that portability was probably why you chose Java as a platform in the first place, it makes sense to protect it.
Talking the talk
In our exercise above, you probably came up with a list of features your application lacked when compared to native applications running in the same environment. You may be surprised by how many you can implement purely in standard Java:
The Java 2 platform has an improved Abstract Windowing Toolkit (AWT), and contains the Java Foundation Classes (JFC); the latter has a large set of lightweight, pure Java components capable of mimicking native platforms. The Pluggable Look and Feel (PLAF) architecture even lets you mimic an alternate look-and-feel architecture on any platform (within licensing limits) and customize your own. It is important to remember that the simulacrum is never the same as the original, and that there may be small quirks that the simulated PLAFs do not cover. As of JDK 1.2.2, Swing (JFC's GUI component set) is not very stable, but has a very flexible design and a bright future. JDK 1.3 (code-named Kestrel, and now available in beta) promises to be more stable and even more feature rich.
JFC also supports the dragging and dropping of objects between JVMs, and between JVMs and native applications. Again, there are various quirks that need attention. Don't claim it works until you've tested it on every platform.
The Java 2 platform also introduces standard extensions to the platform that may cover your needs. The Java Sound API and the Java 3D API are implemented with JNI. It is always best to use standard extensions, which are guaranteed to be widely supported on many platforms.
If you do decide to use JNI for your solution, don't immediately go native; keep the Java platform-neutral aloofness in mind. Consider each feature as if it were part of your virtual machine. Give it a name that is as generic as possible. Design the classes to be similar to those in the Java platform packages. Such aloofness is useful because there may be ways to simulate this feature on other platforms; when the time comes to do so, using platform-specific names and behavior models may seem out of place.
In this article, we will call our feature a desktop indicator, and will treat it with all the common Java courtesies, such as decorating it with listener classes. It's actually a fairly portable feature, and is available in some form or another on most desktop platforms.
Designing the wrapper
We'll start by designing our Java wrapper from a non-native perspective. Under Win32, the taskbar icon works by sending messages to windows; this is necessary because of Win32's reliance on messaging to handle events. In Java, we prefer to use listener classes. Part of our implementation challenge will be to provide a native invisible window that receives the events and dispatches them to listeners. This design is much more flexible than one based on the Win32 model. In taking this route, we have overcome the temptation to send events to AWT windows, and enabled our feature to work without any AWT involvement.
Let's start with the listener:
public interface DesktopIndicatorListener
{
/**
* Called when a desktop indicator is clicked.
**/
void onDesktopIndicatorClicked( DesktopIndicator source );
}
That's pretty straightforward.
As for our class, we will associate each instance with exactly one taskbar icon. We will need one static method to ensure that the library is loaded, and to indicate that the feature is supported on this VM:
/**
* 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 n
Read
Tutorial at: Click here to view the tutorial
Rate Tutorial: Enhance your Java application with Java Native Interface (JNI)
View Tutorial: Enhance your Java application with Java Native Interface (JNI)
Related
Tutorials:
|