Dev : Extensions : Example Code : Calling Java from Javascript

From MozillaZine Knowledge Base
Jump to navigationJump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

This page is currently notes of what I had to do to call Java from Javascript from Thunderbird.

Here's an example from a blog: http://mozilla-firefox-extension-dev.blogspot.com/2004/11/calling-java-code-in-custom-jars-from.html

   var cl = new Packages.java.net.URLClassLoader(
       [
           new Packages.java.net.URL(
               'http://foo.net/bar.jar')
       ]
   );

   var aClass = Packages.java.lang.Class.forName("HelloWorld", true, cl);
   var aStaticMethod = aClass.getMethod("getGreeting", []);
   var greeting = aStaticMethod.invoke(null, []);
   alert(greeting);


In order to write to the file system, I had to add this to the javascript code: java.lang.System.setSecurityManager(null); I could read a jar from the filesystem without a problem.

Calling showJavaConsole is very useful for debugging:

        var jvm = Components.classes["@mozilla.org/oji/jvm-mgr;1"].getService(Components.interfaces.nsIJVMManager);
	jvm.showJavaConsole();

Here's the code I use to log exceptions. JSUtil.getStackTrace doesn't always work. I haven't figured out why, so I do it last, wrap it in a try catch, and print out my own "rough" stack trace first. (The rough list has no line numbers.) Wrap all java calls in a try catch and log the exception. Mozilla doesn't always report them and when it does it doesn't give the stack trace, and it's usually wrapped in a meaningless exception. I think the java console logs all exceptions though, so maybe this isn't necessary if you use that.

function logExc(e) {
    try {
        while(e != null) {
            debug(e);
            e = e.getCause();
        }
        debug(netscape.javascript.JSUtil.getStackTrace(e));
    } catch(exp) {
        debug("exception while logging exception");
        debug(exp);
        debug("exception being logged");
        debug(e);
    }
}


I'm still trying to figure out how to get my classes in the regular classpath so I can access them with "Packages" and not use reflection. I tried setting the classpath and it doesn't work. If you use the URLClassLoader to create an instance of a class, you can call methods on it normally. So you can say "var myclass = class.newInstance()" and then call instance methods on my class. That way you don't have to use reflection for everything.


Sometimes Javascript objects get passed to Java as JSObjects. I think it's doing that for me because of the reflection, since the URL[] works in the classloader example. JSObject is defined in $JAVA_HOME/jre/lib/plugins.jar. It's documented here: http://java.sun.com/products/plugin/1.3/docs/index.docs.html


To get the Java plugin working in Thunderbird, I had to make a ".plugins" directory in ~/.mozilla (not ~/.thunderbird), and symlink libjavaplugin_oji.so in that directory. Make sure you use one compiled with the same gcc as the thunderbird compile. It also seemed to care that it was a symlink and not a copy of the lib.so file; a copy didn't work for me until I symlinked it.