# Calling Plug-in Native Methods from Java

Not only can you call Java methods from a plug-in, but you can also define native methods that Java (and JavaScript) programs can call. "Native methods" are the name given to Java methods written in C code rather than in the Java language.

Why would you want to write native methods? Primarily to export lower-level functionality that could not otherwise be written directly in Java (such as functionality implemented by a plug-in). Native methods can also be used when greater performance is required.

To Java programs, plugins appear as instances of the class `netscape.plugin.Plugin`. The `Plugin` class is described in the Netscape Packages documentation.

Actually, there are three choices a plugin designer can make with respect to supplying a Java class for a plugin:

- Don't supply a Java class -- This will cause the plug-in to be invisible to other java applets. The plug-in can still call into Java, but will have no object in the Java space that represents it.

- Supply the default class, `Plugin` -- This should be done when the plugin must have a Java object associated with it, but otherwise doesn't define any additional methods (either Java methods or native methods).

- Supply a subclass of `Plugin` -- This should be done when the plugin wishes to export additional functionality (usually native methods). We'll see how to do that in the next section.

### Defining a Plug-in Class

Plugins that wish to export additional functionality must do so by subclassing the class `netscape.plugin.Plugin`. Let's walk through a simple example where a plugin defines a new native method, `playMovie`.

We'll begin by creating a MoviePlugin.java file:

    	import netscape.plugin.Plugin;

    	class MoviePlugin extends Plugin {
    		public native void playMovie(int from, int to);
    	}

That's it! All you have to do is define the subclass and declare the new native method.

Next you'll need to compile the class with the Java compiler, `javac`, and then generate both headers and stubs with the new `javah` stub compiler. We've already seen how to create the header files in the previous section. To create the stubs you run `javah` once again with the `-stubs` option:

    	% javah -jri MoviePlugin
    	% javah -jri -stubs MoviePlugin

Be sure to set up your `CLASSPATH` environment variable to include the directory that the MoviePlugin.class file resides in (or use the `-classpath` option).

The call to `javah -jri` will produce a `.h` file containing macros for accessing the public fields and methods of the class. (When the `DEBUG` flag is defined, these are functions instead of macros for easier debugging.) Include the `.h` files of any classes that you intend to use in your plugin. And if you intend to implement any native methods that require protected or private access to fields and methods of a class, first define the `IMPLEMENT_ClassName` symbol before including the header:

    	#include "java_lang_String.h"
    	#define IMPLEMENT_MoviePlugin
    	#include "MoviePlugin.h"

The call to `javah -jri -stubs` will produce a `.c` file with a special routine that sets up the class for use from native code (`use_ClassName`). It is essential that you call this routine before using your class. The "`use`" routine performs the linkage that allows you to access fields of objects of that class, and registers your native method implementations so that Java can call them.

You need to call the "`use`" routine for all classes whose methods will be invoked or fields will be accessed -- not just your `Plugin` subclass that defines native methods.

For the MoviePlugin example, the file "MoviePlugin.c" will be generated containing the "`use`" routine `use_MoviePlugin`:

    	extern java_lang_Class* use_MoviePlugin(JRIEnv* env);	/* C */
    	java_lang_Class* MoviePlugin::_use(JRIEnv* env);	/* C++ */

If the `MoviePlugin` class had been declared to be in a Java package, the package name would also become part of the class name, separated by underscores.

Warning: Don't generate "`use`" routines for system classes in order to access their fields. Most of these are private and may change in the future. Call the public accessor routines instead.

When you're done using a particular class, you can call the corresponding "`unuse`" routine:

    	extern void unuse_MoviePlugin(JRIEnv* env);	/* C */
    	void MoviePlugin::_unuse(JRIEnv* env);		/* C++ */

### Associating a Class with your Plug-in

With Navigator Plug-ins version 0.8, you'll need to add another entry-point to your plug-in that tells the Navigator the Java class of your plug-in. This entry point is `NPP_GetJavaClass`:

    	extern java_lang_Class* NPP_GetJavaClass(void);

For the MoviePlugin example, we can write:

    	java_lang_Class* NPP_GetJavaClass() {
    		return use_MoviePlugin(NPN_GetJavaEnv());
    	}

As mentioned previously, you may also choose to not associate a Java class with your plug-in. This can be done by simply returning `NULL` from the `NPP_GetJavaClass` callback.

If you have any other classes that you'll be using from your plugin, you may need to call their "`use`" routine too. Do this if you have native methods that you're implementing for that class (calling the "`use`" will register them with the Java runtime). Just call all the "`use`" routines in your `NPP_GetJavaClass` routine, returning the one that is the class of your plug-in.

Also remember to call the corresponding "`unuse`" routine so that your classes can be unloaded when the plug-in shuts down:

    	NPError
    	NPP_Shutdown() {
    		JRIEnv* env = NPN_GetJavaEnv();
    		unuse_MoviePlugin(env);
    	}

You'll need to compile and link the stub file (e.g. "`MoviePlugin.c`") into your application to include the "`use`" and "`unuse`" routines. You'll also need to compile and link the stub file if you're compiling with the `DEBUG` preprocessor symbol defined. This causes functions to be used for field access and method invocation instead of macros which gives better type checking, and makes debugging a little easier.

### Implementing Native Methods

The remaining task is to implement the body of the native method that we defined in the `MoviePlugin` example. The "`use`" generated by the `javah` stub compiler expects you to implement C functions with a name that corresponds to the class and method name, and a signature that corresponds to the signature of the declared native method. The function name is again the concatenation of the package and class name with the method name, separated by underscores and prefixed by the word `native_`:

    	ResultType
    	native_ClassName_methodName(
    		JRIEnv* env,
    		ClassName* self, other args...);

The `env` parameter is the current execution environment. It is passed to the native method by the runtime when it is called. The `self` parameter is the object on which the method is being invoked. For static methods, this will be the class on which the the method is invoked, rather than an instance. Any remaining arguments (according to the signature of the method defined in Java) follow. So for the movie plug-in, we'll define:

    	void
    	native_MoviePlugin_playMovie(JRIEnv* env, MoviePlugin* self,
    	                             jint from, jint to)
    	{
    		...bla, bla, bla...
    	}

When you define native methods in a DLL, it's important that you remember to compile the `.c` file for your class with the `IMPLEMENT_ClassName` preprocessor symbol defined. This will cause the native method stub routines to be linked into your DLL. Without this you'll see "Unsatsified link error" messages from Java when your Java code tries to call a native method. Typically we define a dummy `stub.c` file that defines this symbol to prevent it from being defined globally:

    	/* stub.c: Compile this instead of MoviePlugin.c to get
    	   the java stub routines pulled in. */
    	#define IMPLEMENT_MoviePlugin	/* define symbol for stub routines */
    	#include "_stubs/MoviePlugin.c" /* and pull in the .c file */

#### Associating the Native Instance and Java Object

Most likely, you'll need to access the native plugin instance (the `NPP` object) from the Java `Plugin` object. You can do this by fetching the `peer` field of the `Plugin` object:

    	NPP npp = (NPP)netscape_plugin_Plugin_getPeer(env, self);

or in C++:

    	NPP npp = (NPP)self->getPeer(env);

Be sure to include `netscape_plugin_Plugin.h` to have access to this accessor (you'll need to generate it by running `javah -jri netscape.plugin.Plugin`). Don't forget to also generate, compile and link the stub file (by running `javah -jri -stubs netscape.plugin.Plugin`) to get the "`use`" method and any accessor functions in `DEBUG` mode.

You can also access the Java object associated with your plugin at any time by calling the `NPN_GetJavaPeer` routine:

    	extern netscape_plugin_Plugin* NPN_GetJavaPeer(NPP instance);

The Java instance is actually not created until this call is made the first time (thereby avoiding starting up the interpreter if you never need an instance). Note however that JavaScript will also call this routine if it needs to talk to a plug-in on the page.

When your Java `Plugin` instance gets created, its `init` method will be called. You can specialize this method to perform special initialization work after the instance is created. Also, right before the native plugin instance (the `NPP`) is destroyed, the Java Java `Plugin` instance will get its `destroy` method called. You can specialize this method to perform special cleanup work before the native instance is destroyed. At any time you can test if the native instance is still active (not destroyed) by calling `isActive`:

    	public void init();
    	public void destroy();
    	public boolean isActive();

To access JavaScript from a plugin, you can call the `getWindow` method:

    	public JSObject getWindow();

The `getWindow` method returns a `JSObject` (a JavaScript object reflected into Java) representing the window on which your plugin is running. From the window you can access other plugin instances, and JavaScript operations. You can also access the window object from native plugin code via:

    	netscape_javascript_JSObject* window =
    		netscape_plugin_Plugin_getWindow(env,
    			NPN_GetJavaPeer(instance));

See the section Calling JavaScript from Java Methods or the Netscape Packages documentation for more details.

### Garbage Collection Considerations

You may have noticed that you never have to free a Java object. That's because they get garbage collected, i.e. freed by the system when it can determine that the objects are no longer needed. However, with this privilege come a few caveats when dealing with Java objects from less fortunate languages like C and C++.

First, pointers to Java objects are dangerous. This includes `jref`, the primary type of pointers to Java objects (also referred to as references to Java objects), and pointers to types and structs fabricated by `javah` (for instance, `java_lang_String*` or `struct java_lang_String*`). Pointers to these types and structures are `jref`s which have been cast.

Basically, the lifetime of Java references is the same as the stack frame in which they're used. You can think of them as automatic variables in C (pointers to structures that are allocated on the stack). Consequently you must never store a `jref` in the heap, or in a global variable. You can put them in local variables, pass them as parameters and return them as results, but don't use them anywhere else.

### But what about globals?

Storing references to Java objects in global variables or in the heap is sometimes an essential part of life, so we've invented a way of for you to work with the garbage collector when you need them. The `JRIGlobalRef` data type is just for this purpose. `JRIGlobalRef`s can be used just like malloc'd data in C and C++ -- you explicitly obtain one, and you have to explicitly free them. Once you have one, you can store it anywhere.

To create a global reference, use the `JRI_NewGlobalRef` JRI call:

    	extern JRIGlobalRef JRI_NewGlobalRef(JRIEnv* env, jref initialValue);

This call takes a `jref` with which to initialize the value of the new global reference. Global references must be disposed of by calling `JRI_DisposeGlobalRef`:

    	extern void JRI_DisposeGlobalRef(JRIEnv* env, JRIGlobalRef globalRef);

To get or set a global reference, use the following calls:

    	extern jref JRI_GetGlobalRef(JRIEnv* env, JRIGlobalRef globalRef);
    	extern void JRI_SetGlobalRef(JRIEnv* env, JRIGlobalRef globalRef,
    	                             jref newValue);

Global references are scoped to the execution environment which is passed as the first argument to all the global reference calls. This means that different execution envionments cannot access each other's globals (although `jref`s may be freely exchanged between different execution environments). It also means that if the execution environment is destroyed, all the globals will be automatically disposed.

The Navigator assigns a unique execution environment to each class of plug-in. This means that if multiple instances of the same plug-in class (i.e. the same library) are currently active, they will share the same execution environment and consequently the same global references. Plug-ins of a different class will have their own globals references. When a plug-in library gets unloaded, the global references will be automatically disposed. [Warning: This is not implemented in Atlas Release beta4, so be sure to explicitly dispose any globals when your plug-in is unloaded.]

For more information, consult the Java Runtime Interface (JRI) specification, particularly the overview, the native method API description and enhancements to javah.