# Calling Java Methods from Plug-ins

Calling Java methods from plug-ins is simple. You'll need to run the new JRI version of `javah` from Netscape on the class files whose methods you want to call. This will generate the header files you'll need for C and C++ to call Java.

For example, say you want to call methods from the `java.lang.String` class. All you have to do is call:

    	% javah -jri java.lang.String

(Be sure to have your classpath set properly, or use the `-classpath` option to `javah`.) This will generate the file `java_lang_String.h` with accessors macros defined for all methods and fields that are accessible.

### Accessing Fields

The JRI version of `javah` uses a naming convention to create accessor macros for all fields defined for a Java class. This convention prepends `get_` or `set_` followed by the package and class name to the field name to define a getter or setter. When the preprocessor symbol `DEBUG` is defined, these names declare functions (for better type checking) with signatures of the form:

    	ResultType
    	get_ClassName_fieldName(JRIEnv* env, ClassName* self);

    	void
    	set_ClassName_fieldName(JRIEnv* env, ClassName* self,
    	                        ResultType value);

Note that the class name itself denotes the type of the object whose field is to be accessed (the `self` parameter). The name of the struct may also be used to avoid including additional header files, e.g. `struct ClassName*`.

In C++, the type denoting the Java class becomes an actual C++ class with the same name. Fields can be accessed via inlined accessor methods of the form:

    	class ClassName : ... {
    		ResultType	// getter method
    		fieldName(JRIEnv* env) { ... }

    		void		// setter method
    		fieldName(JRIEnv* env, ResultType value) { ... }
    		...
    	}

So, for example, you can get the `count` field of the `String` class in C via:

    	jint cnt = get_java_lang_String_count(env, myString);

or in C++:

    	jint cnt = myString->count(env);

and set the `count` field in C via:

    	set_java_lang_String_count(env, myString, cnt);

or in C++:

    	myString->count(env, cnt);

The env parameter is passed to all Java methods and represents the current execution environment (the state of the Java interpreter).

#### Security Considerations

Note that the `count` field of the `String` is private although we are able to access it anyway. This is because the C and C++ interface to Java objects has unrestricted access privileges. Although we could have made you jump through more hoops to get private and protected information from Java, we didn't because you can always cast and find it anyway. However, it is not advised to access private fields or invoke private methods because other Java implementations may not provide these members (as they are not part of the contract published in the Java interface).

#### Static Fields

Static fields can be accessed in almost the same way as non-static fields. Rather than accessing them from an instance, we access them from a class object. So in Java where one might write:

    	PrintStream o = System.out;

from C you would instead write:

    	java_lang_Class* systemClass = class_java_lang_System(env);
    	java_io_PrintStream* o = java_lang_System_out(env, systemClass);

or in C++:

    	java_lang_Class* systemClass = java_lang_System::_class(env);
    	java_io_PrintStream* o = java_lang_System::out(env, systemClass);

Note that although in C++ static Java object fields are accessed by static member functions, these member functions still have to be passed the Java class object. Although the class object could be looked up by the member function, passing it in eliminates possibile multiple lookups.

### Accessing Methods

Methods can be accessed in a very similar fashion. For example, the `substring` method of the `String` class can be called as follows:

    	java_lang_String* sub = java_lang_String_substring(env, str, 5, 9);

This call gets the substring of the string `str` from characters 5 through 9 and assigns the result to the `sub` variable.

The above example also can be expressed in C++ as:

    	java_lang_String* sub = str->substring(env, 5, 9);

#### Overloaded Methods

The JRI version of `javah` attempts to deal with overloaded methods in Java in a more graceful way than fully mangling the name. Mangled names such as the way C++ member function names appear to C are not mnemonic and are difficult to deal with.

Whenever `javah` encounters more than one method with the same name, it generates symbols in C (and C++) that have an index appended to them for all but the first occurrance. For example, in the `String` class there are several methods with the name `indexOf`:

    	public int indexOf(int ch);
    	public int indexOf(int ch, int fromIndex);
    	public int indexOf(String str);
    	public int indexOf(String str, int fromIndex);

In C these are given the names (and signatures):

    	extern jint java_lang_String_indexOf(JRIEnv* env,
    			java_lang_String* self, jint a);

    	extern jint java_lang_String_indexOf_1(JRIEnv* env,
    			java_lang_String* self, jint a, jint b);

    	extern jint java_lang_String_indexOf_2(JRIEnv* env,
    			java_lang_String* self, java_lang_String *a);

    	extern jint java_lang_String_indexOf_3(JRIEnv* env,
    			java_lang_String* self, java_lang_String *a, jint b);

and in C++:

    	jint indexOf(JRIEnv* env, jint a);
    	jint indexOf_1(JRIEnv* env, jint a, jint b);
    	jint indexOf_2(JRIEnv* env, java_lang_String *a);
    	jint indexOf_3(JRIEnv* env, java_lang_String *a, jint b);

Here's a helpful hint: Put the overloaded method you want to use most from C or C++ before the other overloaded methods in the class definition. This will cause it's name to not have an index appended to it. Also, if you have a method implemented in Java and an overloaded declaration of a native method, put the native method first. It's the one you'll have to implement in your C code, and again you can avoid the appended index.

But what if I define a method called `indexOf_1`? To prevent this sort of collision, `javah` mangles method names containing underscores. All underscores get replaced by the hexidecimal value `00005f`. Other Unicode characters also get replaced in this way with their hexidecimal equivalent. This means although the second overloaded version of `indexOf` would become `indexOf_1`, a method explicitly named `indexOf_1` would become `indexOf_00005f1`. Bottom line: avoid underscores and you'll be much happier.

Note that although you can call methods which are overloaded in this way, you cannot define native methods with overloaded names. This is currently a limitation of the Java 1.0 runtime.

### Java Names for Primitive Types

What's a `jint`? A `jint` is the JRI way of expressing a 32-bit signed integer value that works across all platforms. The JRI defines similar C type names for all of Java's scalar types. The following table shows the correspondence:

Java Type | C/C++ Type | Size
boolean | jbool | 1 byte
byte | jbyte | 1 byte
char | jchar | 2 bytes
short | jshort | 2 bytes
int | jint | 4 bytes
long | jlong | 8 bytes
float | jfloat | 4 bytes
double | jdouble | 8 bytes

You should always use these JRI types when dealing with Java from C and C++ rather than standard types like `int` or `long`. This is the first step to ensuring that your code will work across multiple platforms.

These JRI types are defined in the file `jri_md.h` which is included by the main JRI header file, `jri.h`. These types are conditionally defined for each architecture and compiler by controlling numerous preprocessor symbols (including type sizes, alignment, byte ordering, whether the compiler supports `long long` values, etc.).

You must set the right preprocessor symbols for your architecture and compiler before including `jri.h`. Look at `jri_md.h` to see what you'll need. The `jri_md.h` header also defines a set of cross-platform macros for manipulating `jlong` (`long long`) values.

### What's this `env` parameter?

The `env` parameter represents the execution environment -- a `JRIEnv*` that's passed to all JRI operations (and consequently operations generated by `javah`). It's your handle on the Java interpreter. It serves two purposes:

- a dispatching mechanism to call JRI operations
- an encapsulation of the current Java thread of execution

You needn't be concerned with it for the most part except to know that you need to pass it back to all JRI calls you make, and you shouldn't allow any other threads to use it except the one it was delivered to you on.

So how do you get your hands on one of these execution environments in the first place? The Navigator Plug-in API defines a new call, `NPN_GetJavaEnv`, that delivers one to you:

    	extern JRIEnv* NPN_GetJavaEnv(void);

You can call this whenever you need to access the Java interpreter. The first time you call this, the interpreter may have to initialize itself if the browser hasn't already run a Java applet (so be patient).