Friday, 15 May 2015

Creating Threads in Java

 Threads aren't much use if you don't know how to create them. Fortunately, you have two options for creating and using threads in your own programs, which have already been alluded to when discussing the thread classes:
  • Derive your class from the Threadclass and override its runmethod.
  • Implement the Runnableinterface in your class and provide an implementation for the run method.
Both of these approaches revolve around providing a runmethod, which is where all the actual processing takes place. After a thread has been created and initialized, its runmethod is called and given the opportunity to perform whatever processing the thread is designed to provide. Because it provides all the processing power, the runmethod is the heart of a thread. It's not uncommon for the runmethod to consist of an infinite loop that performs some repetitive action like updating the frames of an animation. But enough about run for now; go ahead and create some threads!

Deriving from the ThreadClass

If your class isn't derived from a specific class, you can easily make it threaded by deriving it from the Threadclass. The following source code shows how to add thread functionality to a class by deriving from the Threadclass:
public class ThreadMe extends Thread {
  public run() {
    // do some busy work
  }
}
It's as easy as that! To use this class in a real program and set the thread in motion, you simply create a ThreadMeobject and call the startmethod inherited from Thread, like this:
ThreadMe me = new ThreadMe();
me.start();
The start method automatically calls run and gets the thread busy performing its processing. The thread will then run until the run method exits or the thread is stopped, suspended, or killed. If for some reason you want to stop the thread's execution, just call the stopmethod, like this:
me.stop();
If stopping the thread entirely is a little too abrupt, you can also temporarily pause it by calling the suspendmethod, like this:
me.suspend();
The suspend method puts the thread in a wait state, very similar to the state a thread enters when you call the wait method. When you decide the thread has waited long enough, just call resumeto get things rolling again, like this:
me.resume();

Implementing the RunnableInterface

If your class needs to derive from a class other than Thread, you are forced to implement the Runnableinterface to make it threaded. A very common situation where you have to do this is when an applet class needs to be threaded. Because applet classes must be derived from the Appletclass, and Java doesn't provide a mechanism for multiple inheritance, you have no other option but to implement the Runnableinterface to add threading support. You implement the Runnableinterface in a class like this:
public class ThreadYou implements Runnable {
   public run() {
     // do some busy work
   }
 }
As you can see, the only syntactic difference in this approach is that you use the implementskeyword instead of extends. However, notice that you can still use the extendskeyword to derive from another class, like this:
public class ThreadedApp extends Applet implements Runnable {
   public run() {
     // do some busy work
   }
 }
This is a very practical scenario involving an applet class with a run method that performs some type of threaded processing. Even though the definition of a class implementing the Runnableinterface is little different than directly deriving from Thread, there is a big difference when it comes to creating the thread and getting it running. Creating and running a threaded class implementing the Runnableinterface is a three-part process, as the following code shows:
ThreadYou you = new ThreadYou();
Thread t = new Thread(you);
t.start();
Unlike the previous approach involving creating a thread object and calling its start method, this approach requires you to create both an instance of your class and a separate instance of the Threadclass. You pass your object into the Threadclass's constructor, which gives it access to your runmethod. You then set the thread running by calling the thread object's start method. The thread in turn executes your object's runmethod. The thread knows your class has a runmethod because it implements the Runnableinterface.
If you have no need to access the thread after you get it started, the creation and starting of the thread can be combined into one statement, like this:
ThreadYou you = new ThreadYou();
new Thread(you).start();

This approach eliminates the creation of the local variable t, which makes the code a little more efficient. Of course, you may think the original code is easier to understand, in which case you should by all means stick with the clearer technique. 

The Thread Classes in Java

 The Java programming language provides support for threads through a single interface and a handful of classes. The Java interface and classes that include thread functionality follow:
  • Thread
  • Runnable
  • ThreadDeath
  • ThreadGroup
  • Object

Thread

The Thread class is the primary class responsible for providing thread functionality to other classes. To add thread functionality to a class, you simply derive the class from Thread and override the run method. The run method is where the processing for a thread takes place, and it is often referred to as the thread body. The Threadclass also defines startand stop methods that allow you to start and stop the execution of the thread, along with a host of other useful methods.

Runnable

Java does not directly support multiple inheritance, which involves deriving a class from
multiple parent classes. This brings up a pretty big question in regard to adding thread functionality to a class: how can you derive from the Thread class if you are already deriving from another class? The answer is: you can't! This is where the Runnableinterface comes into play.
The Runnable interface provides the overhead for adding thread functionality to a class simply by implementing the interface, rather than deriving from Thread. Classes that implement the Runnableinterface simply provide a runmethod that is executed by an associated thread object that is created separately. This is a very useful feature and is often the only outlet you have to incorporating multithreading into existing classes.

ThreadDeath

The ThreadDeath error class provides a mechanism for allowing you to clean up after a thread is asynchronously terminated. I'm calling the ThreadDeathan error class because it is derived from the Errorclass, which provides a means of handling and reporting errors. When the stop method is called on a thread, an instance of ThreadDeathis thrown by the dying thread as an error. You should only catch the ThreadDeath object if you need to perform cleanup specific to the asynchronous termination, which is a pretty rare situation. If you do catch the object, you must rethrow it so the thread will actually die.

ThreadGroup

The ThreadGroup class is used to manage a group of threads as a single unit. This provides you with a means to finely control thread execution for a series of threads. For example, the ThreadGroupclass provides stop, suspend, and resume methods for controlling the execution of all the threads in the group. Thread groups can also contain other thread groups, allowing for a nested hierarchy of threads. Individual threads have access to their immediate thread group, but not to the parent of the thread group.

Object

Although not strictly a thread support class, the Objectclass does provide a few methods that are crucial to the Java thread architecture. These methods are wait, notify, and notifyAll. The wait method causes a thread to wait in a sleep state until it is notified to continue. Likewise, the notify method informs a waiting thread to continue along with its processing. The notifyAll method is similar to notify except it applies to all waiting threads. These three methods can only be called from a synchronized method; don't worry, you'll learn more about synchronized methods a little later in this chapter.

Typically, these methods are used with multiple threads, where one method waits for another to finish some processing before it can continue. The first thread waits for the other thread to notify it so it can continue. Just in case you're in the dark here, the Object class rests at the top of the Java class hierarchy, meaning that it is the parent of all classes. In other words, every Java class inherits the functionality provided by Object, including the wait, notify, and notifyAll methods.

Thread Basics in Java

 The multithreading support in Java revolves around the concept of a thread. The question is, what is a thread? Put simply, a thread is a single stream of execution within a process. OK, maybe that wasn't so simple. It might be better to start off by exploring exactly what a process is.

A process is a program executing within its own address space. Java is a multiprocessing system, meaning that it supports many processes running concurrently in their own address spaces. You may be more familiar with the term multitasking, which describes a scenario very similar to multiprocessing. As an example, consider the variety of applications typically running at once in a graphical environment. As I write this, I am running Microsoft Word along with Internet Explorer, Windows Explorer, Inbox, CD Player, and Volume Control. These applications are all processes executing within the Windows 95 environment. In this way, you can think of processes as being analogous to applications, or stand-alone programs; each process in a system is given its own room to execute.

A thread is a sequence of code executing within the context of a process. As a matter of fact, threads cannot execute on their own; they require the overhead of a parent process to run. Within each of the processes I mentioned running on my machine, there are no doubt a variety of threads executing. For example, Word may have a thread in the background automatically checking the spelling of what I'm writing, while another thread may be automatically saving changes to the document I'm working on. Like Word, each application (process) can be running many threads that are performing any number of tasks. The significance here is that threads are always associated with a particular process.



Note
Threads are sometimes referred to as lightweight processes, implying that they are a limited form of a process. A thread is in fact very similar to a full-blown process, with the major difference being that a thread always runs within the context of another program. Unlike processes, which maintain their own address space and operating environment, threads rely on a parent program for execution resources.

I've described threads and processes using Windows 95 as an example, so you've probably guessed that Java isn't the first system to employ the use of threads. That's true, but Java is the first major programming language to incorporate threads at the heart of the language itself. Typically, threads are implemented at the system level, requiring a platform-specific programming interface separate from the core programming language. This is the case with C/C++ Windows programming, because you have to use the Win32 programming interface to develop multithreaded Windows applications.

Java is presented as both a language and a runtime system, so the Sun architects were able to integrate threads into both. The end result is that you are able to make use of Java threads in a standard, cross-platform fashion. Trust me, this is no small feat, especially considering the fact that some systems, like Windows 3.1, don't have any native support for threads! 

Multithreading and Native Methods in Java

 Even though the native methods are written in C, they still execute within the context of the Java environment, including multithreading. Native methods will sometimes have sections of code that modify global (class or application) data, which modify important state variables, or which must call non-re-entrant functions. (Some platform-specific APIs fall into this category.) These sections are called critical sections, because it is critical that no more than one thread executes the section of code at a time. Critical sections are not unique to native methods: the same issues exist when dealing with multithreading in pure Java code.
In order to ensure that the native methods maintain the application in a consistent state, these native methods will have to be synchronized with other threads. The simplest way to accomplish this is to declare the native methods as synchronized in the Java code. Sometimes, however, this will be insufficient, either for performance reasons (for example, a method that does a long computation, but only changes the condition variable infrequently), or because a multithreaded application needs to use an existing object that does not have synchronized methods (most do not).
In these cases, your native code can perform the synchronization directly. In Java code, you could put the critical section inside a synchronized block. The native method analogue to a synchronized block directly uses a monitor.
Monitors prevent two threads from simultaneously executing a section of code. Monitors were first introduced in C.A.R. Hoare's seminal paper "Communicating Sequential Processes" (Communications of the ACM, Vol. 21, No. 8, August 1978). Typically, each condition variable has a monitor associated with it. The monitor acts as a lock on that data. Unless a thread holds the monitor, it cannot modify or inspect that data. Obviously, a thread should hold the monitor as briefly as possible.

Note
In Java, critical sections are usually methods. You can synchronize blocks of code smaller than methods. However, this leads to complex code, with many failure modes. Deadlock prevention at the method level is fairly straightforward, but it becomes rapidly more difficult when dealing with many small blocks of synchronized code.
Even when dealing with native methods, it is best to use synchronization at the method level.
Monitors provide the Java runtime system support for thread synchronization. Every object instance has a unique monitor attached to it. In this case, the entire object is considered a condition variable. Through a trio of functions, native methods can also use monitors.
void MonitorWait(unsigned int, int); 
void MonitorNotify(unsigned int);
void MonitorNotifyAll(unsigned int);
These functions are analogous to the wait(), notify(), and notifyAll()functions in Java:

monitorWaitThis function blocks the executing thread until the monitor is notified. If you encounter a deadlock, the first place to start is to check each occurrence of monitorWait().
monitorNotifyThis function awakens no more than one waiting thread. It signals that the monitor is now available. It must only be called from the thread that holds the monitor. If an unhandled exception occurs while a thread holds the monitor, any threads waiting on the monitor will be blocked indefinitely.
monitorNotifyAllThis function awakens all threads waiting on the monitor. It signals that the monitor is now available.

Tip
Monitors are re-entrant, which means that a thread that already holds a monitor will not deadlock if it calls monitorWait again.
Monitor operations are atomic. They are not subject to race conditions (although the code that calls them is).
The Java implementation of monitors has a nice feature that helps to prevent deadlock. Consider this scenario: a synchronized native method calls monitorWait, to wait for another synchronized method (native or not) to notify the monitor. Because the first method is synchronized, it already holds the monitor when monitorWaitis called. How is the second method ever supposed to execute? The implementation of monitorWaitmakes this possible by releasing the monitor on entry. This allows the second method to execute and notify the monitor. Once the monitor is notified, the first thread awakens. On exit from monitorWait, the first thread acquires the monitor again.
All three of the monitor functions are declared as receiving an unsigned integer. To get the monitor for an object, use the obj_monitormacro on the object's handle.
Here is an example of a synchronized string. This is an example of a producer/consumer problem. (Most synchronization problems can be reduced to one of two classic examples, producer/consumer and the colorfully named "dining philosophers problem." In a producer/consumer problem, one thread produces data items while another consumes them. Both operations must be synchronized so that the consumer gets each item exactly once. Listing 19.9 contains the Java definition of the synchronized string class, SyncString. Listing 19.10 shows the native method implementations of the SyncString.Setand SyncString.Get methods. Note once again that this could easily have been accomplished without the use of native methods. You will find that native methods are only useful in a very small set of circumstances.

Listing 19.9. Java class for SyncString.
class SyncString {
    String str;
    int bAvail;

    public native synchronized void Set(String s);
    public native synchronized String Get(); 

    static {
       try {
           System.loadLibrary("SyncString"); 
       } catch (UnsatisfiedLinkError e) {
           System.err.println("Cannot find library SyncString.");
           System.exit(-1); 
       }
    }
}


Listing 19.10. Native language implementation for SyncString.
#include <StubPreamble.h>
#include "SyncString.h"


void SyncString_Set(struct HSyncString *this,
                    struct Hjava_lang_String *str)
{
    while(unhand(this)->bAvail == TRUE) 
        monitorNotify(obj_monitor(this)); 

    unhand(this)->bAvail = TRUE;
    unhand(this)->str = str;

    monitorNotify(obj_monitor(this));
}

struct Hjava_lang_String *SyncString_Get(struct HSyncString *this) 
{
    Hjava_lang_String *hstrTemp;

    while(unhand(this)->bAvail == FALSE) 
        monitorWait(obj_monitor(this)); 

    unhand(this)->bAvail = FALSE;
        hstrTemp = unhand(this)->str; 

    monitorNotify(obj_monitor(this));

    return hstrTemp;
}



Note
There are other functions that allow native code to construct new monitors not associated with an object. Use of these functions is strongly discouraged, due to the increasing difficulty of deadlock prevention in the face of many monitors.

Native Methods and Exceptions in Java

 Native methods can throw exceptions just like a regular Java method. As with any other method that throws an exception, the native method in the Java class must declare the exceptions that it can throw. This looks exactly like the throwsclause for any other method.
Your native code throws the actual exception using the SignalErrorfunction:
void SignalError(ExecEnv *ee, char *Exception, char *SourceHint);
The first argument is the exception environment to use for the exception. Generally, you will pass a NULLhere to indicate the current environment.
The second argument is the fully specified exception name. This name includes the package in which the exception is defined. It should also be specified as a path, replacing the usual period separators with forward slashes (that is, UNIX-style path separators).
The third argument is a source code hint. You can pass a string that describes the error or provides some useful details. This string will appear on the walkback if the exception is not handled. It is safe to pass a NULLhere. 

Using Java Strings from Native Methods in Java

 Because there is an "impedance mismatch" between Java strings and C strings, there are several convenience functions that allow C code to use the Java strings. Java strings offer several advantages over C strings, including reference counting, automatic memory management, and Unicode support. On the other hand, no C runtime library function or API function will expect a Java string. The utility functions provide a bridge between Java and C strings.
These functions are defined in javaString.h, which will be included automatically if you include StubPreamble.h:
  • The following function will print a Java string on stdout: 
    void javaStringPrint(Hjava_lang_String *)
  • The following function returns the length of the Java string, in characters:
    int javaStringLength(Hjava_lang_String *)
  • The following function will construct a new Java string from a given C string. The second argument indicates the length of the buffer passed in the first argument:
    Hjava_lang_String *makeJavaString(char *, int)
  • The following interesting function allocates some temporary memory for a C string initialized from the given Java string. Once all references to this storage are eliminated, the memory is automatically deallocated. In other words, as long as you keep this pointer in a variable, the memory is valid:
    char *makeCString(Hjava_lang_String *)
  • The following function uses "malloc" to allocate some memory for a C string initialized from the given Java string: 
    char *mallocCString(Hjava_lang_String *)
  • The following function will convert the characters of the given Java string into a unicode string. It assumes that the buffer passed in as the second argument already exists. The third argument specifies the buffer length. The function returns the unicode string's address:
    unicode *javaString2unicode(Hjava_lang_String *, unicode*, int)
  • The following function will convert the characters of the given Java string into a C string. It assumes that the buffer passed in as the second argument already exists. The third argument specifies the buffer length. The function returns the C string's address:
    char *javaString2Cstring(Hjava_lang_String *, char *, int)

Using Java Objects from Native Methods

 In native methods, all objects appear as handles. Handles are at the heart of the Java object model, but you will be shielded from directly manipulating handles. A group of C macros and functions permit you to deal with handles largely as an abstract type. So what can you do with a handle?

Accessing Instance Variables from Native Methods

For starters, you can access all of an object's instance variables-all those that are visible to your code, at least. In order for your native method to access the data members of your object, you dereference the handle with the macro unhand(). Unhand() is defined in the header file interpreter.h, which is included by StubPreamble.h. Listing 19.8 shows an example of accessing an object's instance variables from a native method.

Listing 19.8. Using unhand()to access instance variables.

typedef struct ClassUserInformation { 
   long iUserID;
} ClassUserInformation;
HandleTo(UserInformation);
...
void UserInformation_SetUserID(struct HUserInformation *hUI,
    long newValue)
{
   unhand(hUI)->iUserID = newValue;
}


What Are Handles, Anyway?
In the Java implementation, a handle is used to maintain references to objects. Handles allow the use of native languages to truly be "two-way." That is, the native methods can access instance variables and call other methods, just as pure Java methods can. Handles are at the very heart of the Java object model. In code, a handle is a small structure with two pointers, which together form an object instance. One points to the instance variables, the other to the method table (the vtable in C++ parlance). Handles for your classes are created automatically when you create the header file. (See the sidebar "Where Did HUserInformation Come From?")
By using pointers to handles to pass objects around, Java attains great efficiency. Because object manipulations work through handles, there is a single item of interest to the garbage collector, and a natural mechanism for marking objects in use or discarded.
The unhand() macro returns a pointer to an ordinary C structure. (For handles to objects of your class, it returns a pointer to the structure defined in your header file.) In all cases, the members of the C structure have the same names as the members of the Java class. The types may be different, however. Check Table 19.1 for the type mapping. You can read and write to the members of the structure. In fact, you can even pass pointers to them as arguments to other functions. They behave in all ways as members of ordinary C structures, because that is exactly what they are. When you use unhand()on a handle, you are actually looking at the fundamental Java implementation of an object. The structures you see using the handle are the real structures; there is no behind-the-scenes marshalling before the call.

Accessing Class Variables from Native Methods

Class variables (static variables) do not appear in the instance variable structure generated by javah. This is because they are not stored with each instance of a class, but rather with the class structure itself. The Java runtime provides a function that you can use to get a pointer to the class variable getclassvariable.
long *getclassvariable(struct ClassClass *cb, char *fname);
Notice that this function, like many other Java runtime functions, requires a pointer to the class structure. Fortunately, every object instance carries this pointer around. The obj_classblockmacro from interpreter.htakes an object handle as an argument and returns a pointer to the class structure.
Why does getclassvariablereturn a pointer to a long? It returns a pointer because the native language code should be able to modify the class variables, as well as see them. The return type is long, but in C, all pointers to data are the same size. So, it is safe to cast the returned pointer to a pointer to whatever type the class variable really is.
Be warned that unless your native methods are synchronized, modifying class variables can be problematic. Always remember that, even though this method is in C, it really is being called from a multithreaded environment. There may be other threads executing Java methods or native methods. They may be doing any number of things, including accessing the class variable at exactly the same time as the native method. Any time global data is involved, whether it is class-wide or truly global, synchronization is an issue. See "Multithreading and Native Methods" for more details.
Wouldn't it be nice if your native language code could also call Java code? Yes, it really would. Fortunately, we can do exactly that. It all starts with the object handle. (Where else?) You have to use a slightly more complicated mechanism than you might think at first. Calling another C function from a function pointer in a structure is something familiar to all of us, something like:
hUserInformation->Username();                 // DO NOT DO THIS!
Although this would have the net effect of transferring execution to the other function, it is not sufficient. Here's why: When calling a C function, a stack frame is created with the return address and some arguments. (Implementations vary somewhat; this is necessarily a very general description.) In Java, there is much more context provided for a function call. In addition to the processor stack, the JVM maintains a great deal of stack information on its own, internal stack. (Presumably, combining this stack with the processor stack, both in hardware, is one of the benefits of a "Java chip.")
In order to make the method call, we really have to ask the JVM to do the call for us. Here are the three functions declared in interpreter.h that will make these calls:
HObject *execute_java_constructor(ExecEnv *, char *classname,
   ClassClass *cb, char *signature, ...);
long execute_java_dynamic_method(ExecEnv *, HObject *obj,
   char *method_name, char *signature, ...);
long execute_java_static_method(ExecEnv *, ClassClass *cb,
   char *method_name, char *signature, ...);
Each function serves a specific purpose and is described separately in the following section.

Calling a Java Constructor

Native language code can construct an instance of any Java class that is currently loaded. Here again, the native code is hooking directly into the implementation of Java. Therefore, the new object will behave exactly as it would if you had constructed it in Java code. The general form of a native language constructor is this:
hNewObject = (HClassName *)execute_java_constructor(NULL, 
    "ClassName", NULL, "ConstructorSignature", ...);
The first parameter here is the ExecEnvor exception environment that applies to the constructor call. You can safely pass a NULLhere, and the constructor will operate with the default exception environment. If you are using sophisticated exception handling in your native code, please see the section "Native Methods and Exceptions."
The interesting pieces of this call are shown in italics. First of all, in order for the native method to use the object that gets constructed, it must know the object's class. Usually, this comes from including a header file for that class. Only a few classes have headers distributed with the JDK: ClassLoader, String, Thread, and ThreadGroup. However, by using javah, you can create header files for whatever classes you need. (See Chapter 14 for details.) If you do not need to access the object's methods or instance variables, you can cast the return value from execute_java_constructorto an HObject pointer. HObjectis the handle to the base class Object.

Loading Java Classes from Native Language Code
If you need to load a class directly from native code, you can call the function:
int LoadFile(char *filename, char *directory, char *SourceHint);
It is safe to pass NULL for SourceHint. This function will cause the ClassLoader to find the file and load it into memory. Once the class is loaded, its static block is executed. Be aware that the static block can throw an exception.
The ClassLoader also provides native code for the DoImport function.
int DoImport(char *name, char *SourceHint);
This will behave exactly as if the Java code had contained an "import name;" line.
The next item of interest in this call is the class name. This is a text string that specifies what class is to be instantiated. This class must already be loaded, or reside on the class path. When you pass a class name, the Java runtime must perform a lookup on the class itself. However, if you have a pointer to the class itself, you can leave the class name argument NULLand pass the ClassClass pointer in the third argument. For example, if you wanted to clone an existing object of any class, you might use code like this:
struct HObject *Cloner_Clone(struct HCloner *hCloner,
                             struct HObject *hObj)
{
   HObject *hNewInst;
   hNewInst = execute_java_constructor(NULL, NULL, 
                 obj_classblock(hObject), "(A)", hObj);
   return hNewInst;
}
This native method can clone any object that has a copy constructor. The macro obj_classblockis another of the handle convenience macros. For any object, it will return a pointer to the class structure for that object. Many of the built-in functions of the Java runtime require a pointer to the class structure "ClassClass".
The constructor signature is used to select which constructor to invoke. It is a character string that specifies the number and type of arguments to follow. Table 19.2 shows the possible characters and their meanings.
Table 19.2. Signature characters and their meanings.

Character
Meaning
A
Any (object)
[
Array (object)
B
Byte
C
Char
L
Class
;
End class
E
Enumeration
F
Float
D
Double
(
Function argument list start
)
Function argument list end
I
Int
J
Long
S
Short
V
Void
Z
Boolean
By concatenating characters from this set, you specify what arguments are to follow. Two characters have special significance: the parentheses indicate the beginning and end of the argument list. For a constructor, parentheses should enclose the entire argument list. For other methods, the signature will also indicate the return type of the method. In the preceding example, the signature is "(A)", which means the constructor must simply take one argument-an object instance. This implies that our constructor could receive objects of other classes as arguments. If we knew the class name, say Foo, for example, we could write the signature as "(LFoo;)", which means the constructor must take an instance of class Fooor its subclasses, as an argument. Here is a revised version of the Clone method, which takes into account the class name of the argument passed in:
struct HObject *Cloner_Clone(struct HCloner *hCloner,
                             struct HObject *hObj)
{
   HObject *hNewInst;
   char     signature[80]; 

   sprintf(signature, "(L%s;)", classname(obj_classblock(hObj))); 
   hNewInst = execute_java_constructor(NULL, NULL, 
                 obj_classblock(hObject), signature, hObj);
   return hNewInst;
}
Notice that, although "name" is a simple member of struct ClassClass, we use the classname macro (from oobj.h) instead of a direct access. In general, you should never access a structure member directly. Instead, use one of the macros provided in oobj.hor interpreter.h (both included by StubPreamble.h). The macros shield you from future changes to the structures. What if there is no macro to access a particular member? Then you probably are not meant to use that member in the first place!
After the constructor signature, you can place a variable length argument list. These are the arguments that will be passed to your constructor. You should be careful to make sure that the type, number, and order of your arguments match the signature. Otherwise, your constructor may be called with garbage for arguments.
If there is an error while calling the constructor, execute_java_constructorwill return NULL.

Calling a Java Method

Now for the really good part. You can call any Java method from native code. It all works through the handle to the object instance. If the method to be called is static, see the next section. For dynamic methods-including final and native methods-use the execute_java_dynamic_methodfunction:
long execute_java_dynamic_method(ExecEnv *, HObject *obj,
    char *method_name, char *signature, ...);
The first parameter is the same as the first argument to execute_java_constructor-an exception environment. Again, it is safe to pass a NULLfor this parameter. If you require more sophisticated exception handling for the native code, see "Native Methods and Exceptions."
The second parameter is the object instance itself. This can be any valid object handle, whether it was passed from Java code as an argument or constructed in the native method itself.
The next parameter is the name of the method to be invoked. If this method does not exist in the object passed, execute_java_dynamic_methodwill throw an exception.
Finally, the fourth argument is the signature of the instance method. Again, the signature indicates the type and number of arguments to be passed to the instance method being called. This must be the same number and type of remaining arguments in the call to execute_java_dynamic_method.
The signature for a method differs slightly from the signature for a constructor. A method signature needs to indicate the expected return type. The signature can show this with an extra character after the closing parenthesis. For example, consider a method that takes arguments of two classes and a float and returns a byte:
public byte[] FunkyMethod(Object fc, SecondClass sc,
                          float difference);
This method would have the signature "(ALSecondClass;F)B". The call to execute_java_dynamic_methodwould then have three arguments after the signature: a generic object, an instance of SecondClass, and a float.
The return value from execute_java_dynamic_methoddepends on the method being invoked. It is declared as long, however, so you will need to cast it to the appropriate type. (Because long is wide enough to hold any primitive type or a handle, it is safe to cast it to whatever the method really returns.) Be careful, though. Because you are calling the method by a function, not directly, the compiler cannot possibly notify you of any changes in the method definition.

Calling a Static Java Method

Calling a class method from native code is similar to calling a dynamic method. Use the execute_java_static_methodfunction:
long execute_java_static_method(ExecEnv *, ClassClass *cb,
   char *method_name, char *signature, ...);
This is entirely analogous to the execute_java_dynamic_methodfunction, with one crucial difference. Instead of taking an object instance as a parameter, execute_java_static_methodrequires a class structure. This class structure can come from an object instance, using the obj_classblockmacro, or it can be retrieved using the FindClassfunction:
ClassClass* FindClass(ExecEnv *ee, char *classname, bool_t resolve);
FindClass will return a pointer to the class structure for any class name you pass in. This function may cause several things to happen. First, the named class may be loaded, which will in turn cause the named class's static block to execute. Exceptions may be thrown by FindClassitself, if it cannot find the class, or by the static block of the named class, when it is loaded.

Like the other runtime functions that can throw exceptions, FindClasscan take an exception environment as an argument. As usual, it is safe to pass a NULL here, in which case FindClass will use the current exception environment.