Native

  • November 2019
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View Native as PDF for free.

More details

  • Words: 1,553
  • Pages: 6
Native Methods from the Java Side 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

public int myMethod(byte[] data) { ... } becomes

public native int myMethod(byte[] data); Where does the method body get implemented? In a Java-called native library that gets loaded into Java at runtime. The class of the above method would have to cause the library to be loaded. The best way to accomplish the load is to add a static initializer to the class:

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. Writing Native Methods 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

-verbose -version -o outputfile -d directory -td tempdirectory -stubs -classpath path

Description Causes progress strings to be sent to stdout Prints the version of javah Overrides default file creation;uses only this file Overrides placement of output in current directory Overrides default temp directory use Creates C code module instead of header module 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. A simple class using native methods

public class Demonstration { public String publicName; private String privateName; public static String publicStaticName; private static String privateStatucName; public native void method1(); public native int method2(boolean b, byte by, char c, short s); public native byte[] method3(byte data[], boolean b[]); public native String[] method4(int num, long l, float f, double d); static { System.loadLibrary("Demonstration"); } } The javah output of the above class is below.

Javah output header of Demonstration class /* DO NOT EDIT THIS FILE - it is machine generated */ #include /* Header for class Demonstration */ #ifndef _Included_Demonstration #define _Included_Demonstration struct Hjava_lang_String; typedef struct ClassDemonstration { struct Hjava_lang_String *publicName; struct Hjava_lang_String *privateName; /* Inaccessible static: publicStaticName */ /* Inaccessible static: privateStatucName */ } ClassDemonstration; HandleTo(Demonstration); #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:

Hjava_lang_String str = unhand(demoPtr)->publicName; The code for the unhand() macro shows the conversion:

#define unhand(o) ((o)->obj) 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 Stubs Code Run the following command on the Demonstration class:

javah -stubs Demonstration The output will be a C file in the current directory. The following shows the result. The output of javah

-stubs Demonstration

/* DO NOT EDIT THIS FILE - it is machine generated */ #include <StubPreamble.h> /* Stubs for class Demonstration */ /* SYMBOL: "Demonstration/method1()V", Java_Demonstration_method1_stub */ declspec(dllexport) stack_item * Java_Demonstration_method1_stub(stack_item *_P_,struct execenv *_EE_) { extern void Demonstration_method1(void *); (void) Demonstration_method1(_P_[0].p); return _P_; } /* SYMBOL: "Demonstration/method2(ZBCS)I", Java_Demonstration_method2_stub */

declspec(dllexport) stack_item * Java_Demonstration_method2_stub(stack_item *_P_,struct execenv *_EE_) { extern long Demonstration_method2(void *,long,long,long,long); _P_[0].i = Demonstration_method2(_P_[0].p,((_P_[1].i)), &nbs p; ((_P_[2].i)),((_P_[3].i)), &nbs p; ((_P_[4].i))); return _P_ + 1; } /* SYMBOL: "Demonstration/method3([B[Z)[B", Java_Demonstration_method3_stub */ declspec(dllexport) stack_item * Java_Demonstration_method3_stub(stack_item *_P_,struct execenv *_EE_) { extern long Demonstration_method3(void *,void *,void *); _P_[0].i = Demonstration_method3(_P_[0].p,((_P_[1].p)),((_P_[2].p))); return _P_ + 1; } /* SYMBOL: "Demonstration/method4(IJFD)[Ljava/lang/String;", Java_Demonstration_method4_stub */ declspec(dllexport) stack_item * Java_Demonstration_method4_stub(stack_item *_P_,struct execenv *_EE_) { Java8 _t2; Java8 _t4; extern long Demonstration_method4(void *,long,int64_t,float,double); _P_[0].i = Demonstration_method4(_P_[0].p, &nbs p; ((_P_[1].i)), &nbs p; GET_INT64(_t2, _P_+2), &nbs p; ((_P_[4].f)), &nbs p; GET_DOUBLE(_t5, _P_+5)); return _P_ + 1; } This file contains the stub functions for each of the four native methods. It is the stub's job to translate Java data structures into a C format. Once this is done, the stub will then enter your C function. Sometimes the stub will have to do a little extra work to make the transition. For example, take a look at method4's stub. The Java stack is made up of 32-bit words. Java data types long and double each command 64 bits of storage. The stub code calls "helper" functions to extract the data from the Java stack. The stubs will perform all the work necessary, no matter how complex, to interface the Java stack to C. 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. Method signature symbols Type

byte char class

Signature Character B C L

end of class float double function end of function int long short void boolean

; F D ( ) I J S V Z

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:

[B for an array of bytes [Ljava/langString; for an array of objects (in this case, Strings) The Demonstration class is not actually going to be used; it's merely a convenient tool to demonstrate the C features of Java's runtime environment.

Related Documents

Native
November 2019 35
Native Americans
November 2019 39
Native Plants
June 2020 12
Native Chili
November 2019 35
Native Deserts
November 2019 61
Native Music
June 2020 0