You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Arkadiy Belousov <ab...@micromuse.com> on 2001/06/13 00:16:32 UTC

JNI from servlets in Tomcat (some answers)

Hello all!

I needed to access native methods from inside a servlet, and I ran into
UnsatisfiedLinkError when my native methods were called, even though I
did call loadLibrary before instantiating the classes.

After a lot of investigation, I think I solved the problem. Although
this list contains some hints that were extremely useful, it does not
spell out a solution the way I would wanted to find it on the web.
Hence, this note.

Let's assume that you have 2 files: myapi.jar and libmyapi.so . You need

to use them from a servlet. Here is what seems to be the winning
combination:

-copy myapi.jar to $TOMCAT_HOME/lib (or add it to CLASSPATH before
calling "tomcat start"). When Tomcat spits its classpath on startup, it
should contain ":$TOMCAT_HOME/lib/myapi.jar:" as an element
-copy libmyapi.so to a place where it is accessible through
LD_LIBRARY_PATH
-create and compile the following class:

public class MyApiLoader
{
  public VisionaryApiLoader() {
    System.loadLibrary("myapi");
    try {
      getClass().getClassLoader().loadClass("MyClass1");
      getClass().getClassLoader().loadClass("MyClass2");
      getClass().getClassLoader().loadClass("MyClass3");
    } catch (java.lang.ClassNotFoundException e) {
      System.out.println("Could not load a class: " + e.getMessage());
    }
  }
}

That class needs to be placed in CLASSPATH or in $TOMCAT_HOME/lib as
well. I placed it outside of myapi.jar, but it can be inside too.

-We are almost there. In one of the classes that come from
$TOMCAT_HOME/webapps/myapp/WEB-INFO/classes you place a static
initializer:
static {new MyApiLoader();}
This will load the .so and make the classes available.


Now, here is what I think happens and why we need to jump through those
hoops. Tomcat implements its own class loader to load classes from
$TOMCAT_HOME/webapps/myapp/WEB-INFO/classes  . This way, classes written

for one context will not be loaded from another.  However, that loader
does not handle loadLibrary() call for native libraries. It uses its
parent loader to handle that call instead.
If a class that can be loaded by Tomcat's own loader issues
loadLibrary() call, the library is loaded into Sun's class loader
instead. In order to use it, the native classes need to be loaded by
Sun's loader as well. That is accomplished through having that little
loader class.

I realize this explanation is somewhat holey... Can someone with more
knowlege improve it? Also, would it be a good item for FAQ?