Академический Документы
Профессиональный Документы
Культура Документы
Native methods within a Java class are very simple. Any Java method can be transformed into a
native method-simply delete the method body, add a semicolon at the end, and prefix the native
keyword. The following Java method
static
{
System.loadLibrary("myMethodLibrary");
}
Static code blocks are executed once by the system when the class is first introduced. Any
operations may be specified, but library loading is the most common use. If the static block fails,
the class will not be loaded. This ensures that no native methods are executed without the
underlying libraries.
That's all there is to Java-side native methods. All the complexity is hidden within the native
library. A native method appears to Java like all other real Java methods. In fact, all the Java
modifiers (public, private, and so forth) apply to native methods as well.
The Java runtime was implemented in the C programming language, so currently the only native
language supported is C. The entry points into a C library that can be called from Java are called
stubs. When you execute a native method call, a stub is entered. Java tries to ease the transition
into native code by supplying a tool to generate a C header file and stub module.
Note
Any language that can link with and be called by C can be used to implement a
native method. The C language is needed only to provide the actual interface with
Java. Any additional, non-Java processing could be done in another language, such
as Pascal.
Using Javah
Javah is the tool used to generate C files for Java classes; here's how you use it:
javah [options] class
The following table briefly lists the options available. By default, javah will create a C header (.h)
file in the current directory for each class listed on the command line. Class names are specified
without the trailing .class. Therefore, to generate the header for SomeName.class, use the
following command:
javah SomeName
Javah options
Option Description
-verbose Causes progress strings to be sent to stdout
-version Prints the version of javah
-o outputfile Overrides default file creation;uses only this file
-d directory Overrides placement of output in current directory
-td tempdirectory Overrides default temp directory use
-stubs Creates C code module instead of header module
-classpath path Overrides default classpath
Note
If the class you want is within a package, then the package name must be specified
along with the class name: javah java.net.Socket. In addition, javah will prefix the
package name to the output filename: java_net_Socket.h.
The following code is a simple class with native methods. The class was chosen because it uses
most of the Java types. Compile this class and pass it to javah.
static
{
System.loadLibrary("Demonstration");
}
}
#ifndef _Included_Demonstration
#define _Included_Demonstration
struct Hjava_lang_String;
#ifdef __cplusplus
extern "C" {
#endif
__declspec(dllexport) void Demonstration_method1(struct HDemonstration *);
__declspec(dllexport) long Demonstration_method2(struct HDemonstration
*,/*boolean*/ long,
char,unicode,short);
__declspec(dllexport) HArrayOfByte *Demonstration_method3(struct HDemonstration
*,
HArrayOfByte *,HArrayOfInt *);
__declspec(dllexport) HArrayOfString *Demonstration_method4(struct HDemonstration
*,long,
int64_t,float,double);
#ifdef __cplusplus
}
#endif
#endif
The class has been transformed into a C structure. Each class member is represented, except for
static fields. Representation in a structure has an interesting side effect. Native methods have
access to all non-static fields, including private class members. You are free to read and alter any
member of the class.
Now focus your attention on the four native method prototypes. Each method has been renamed
by prefixing the class name to the method name. Had this class been contained in a package, the
package name also would have been added. Each method has an additional argument. All native
methods have a this pointer that allows the function to access the variables of its associated
class. This argument is often referred to as an "automatic" parameter. Java will add this
parameter to your methods automatically.
The final piece to the puzzle is the HandleTo() macro. Every object in Java is represented in a
structure called a JHandle. The format of this structure for the Demonstration class is as follows:
struct HDemonstration
{
ClassDemonstration *obj;
methodtable *methods;
}
The HandleTo() macro names the JHandle by adding an H to the passed name. To access any
member of a JHandle class, you must dereference it with the unhand() macro. This macro has
the opposite effect of HandleTo(). The following line retrieves a string member from the
Demonstration class:
Structure member obj is obviously the class structure, but what of the other structure member?
Typically, structure member methods will contain a pointer to an internal Java runtime structure
that represents all the information on a class. This includes the Java byte codes, the exception
table, any defined constants, and the parent class. There are times, however, when the variable
is not a pointer at all. Java has reserved the lower 5 bits of the pointer for flags. If all 5 bits are
zero, then the value is a pointer. If the lower 5 bits are non-zero, then the methods field becomes
a typecode. You will encounter typecodes whenever you handle arrays.
The other interesting feature of the stub module is the SYMBOL comment at the top of each
method. Java uses a system of method "signatures" to identify functions. The signature contains
the method arguments and the return type; the symbols are explained below.
Signatures are important because they enable you to make calls back into the Java system. If
you know the class, name, and signature of a method, then these elements can be used to
invoke the Java method from within a C library. The format of a signature is as follows
:
"package_name/class_name/method_name(args*)return_type"
Arguments can be any combination of the characters shown above. Class name arguments are
written like this:
Lclass_name;
The semicolon signals the end of the class name, just as the right (closing) parenthesis signals
the end of an argument list. Arrays are followed by the array type: