Friday 15 May 2015

Extending Your Programs with Native Methods in Java

 The Java Virtual Machine provides sophisticated capabilities for creating user interfaces, performing Internet and WWW accesses, and for general-purpose programming. Unfortunately, the Java Virtual Machine has some (deliberate) limitations. First and foremost, the JVM only supports functionality that applies to many platforms. That means that unaided Java applications cannot take full advantage of their host platforms. The Java development team also introduced some artificial limitations in the interest of security. For the most part, these restrictions are not onerous. In fact, users can have a relatively high degree of confidence that Java applications and applets are not malicious. Without such assurances, the World Wide Web community would surely have revolted at the notion of self-downloading, self-executing code in a Web page. Just imagine the prospect of a cross-platform virus that attaches itself to Web pages! In some cases, however, these benevolent restrictions prevent applications from making the most of Java.
Consider these situations:
  • You have a large, specialized library of C or C++ functions that you would like to use from Java applications.
  • Your application must use a non-standard (that is, non-JDBC) database access library.
  • An existing application that communicates through an operating system-specific channel (such as Windows DDE or UNIX shared memory) must be integrated with a new Java application.
  • Your application needs to automatically determine operating system-specific information, such as the user's Netware ID.
Native methods can solve all of these problems. A Java class can declare a native method to indicate that the actual code for the method is provided in another language. (At present, native methods must be implemented in C. Support for other languages is in the works.) That code is compiled to the native machine code of your particular platform, hence the name "native method." Before it can be used by the Java Virtual Machine, the compiled code must be linked into a dynamically loadable library suitable for use on the target platform. Finally, the DLLor .so file must be installed on the target computer.
There are two parts to every native method, the Java declaration and the "native" implementation. As you do with all other methods, you declare a native method inside a Java class. Native methods can be final, static, or synchronized. They can throw exceptions and be inherited (unless they are final, of course). Because the implementation is compiled for the target platform, it can take full advantage of the capabilities of that platform. Native methods provide a powerful means of extending the Java Virtual Machine.
You have probably guessed by now that native methods are not cross-platform by nature. Your native methods will be as portable as the C code in which you write them and the APIs they call. Because the most common reason for creating native methods is to use a platform-specific API, native methods tend not to be very portable.
Because the dynamically loadable library must be installed on the target machine prior to execution of the Java classes that need it, you will have to face all the issues of software distribution and configuration management. On the other hand, native methods can only be called from Java applications, which have to be distributed and installed themselves. So, the added difficulty of distributing multiple native-method libraries should not pose too great a hurdle.


When Not to Use Native Methods
Here are some questions to ask yourself before you decide to use native methods:
  • Are you writing a full-blown application instead of an applet? Some Web browsers will prevent applets from calling native methods not distributed in the base classes. In some cases, the browser allows the user to enable native method calls from applets. Bear in mind that many users will be reluctant to deliberately short-circuit security features.
  • Can you manage the platform-specific code? Because the native methods are compiled for each platform, you will encounter significant configuration management hassles. More than likely, you will also have to cope with multiple versions of the native methods, one for each platform. This is particularly true when you are dealing with operating system features. (I know, C is supposed to be a portable language, but isn't that why you are using Java?)
  • Is it acceptable to mix object-oriented and procedural code? Keep in mind that the native methods will be written in an object-oriented style of C. You will be working with regular C structures instead of classes. These structures do not provide full information hiding. (No protected or private specifiers.) Ultimately, you will be working in C, with no encapsulation, no inheritance, and no polymorphism. It will require great discipline to maintain good object semantics in C. Most native methods are self-contained, so these should not be serious limitations, but you should be aware of the difficulties ahead.
If you answered "yes" to all of these questions, then feel free to proceed. If any of the questions trouble you, then you should probably think twice before implementing that class with native methods. The Java packages contain hundreds of classes, and the method you are looking for just might be there already, buried within an obscure class.

No comments:

Post a Comment