tags:

views:

51

answers:

2

What is the common way (or best practice) to optionally use JNI?

E.g. I have a Java class and this class is 100% pure Java, so it can run on all platforms. However, on some platforms I'd like to speed up some heavy calculations using JNI - which works fine. Unfortunately I cannot support any existing Java platform in the world. So I guess it is fine to initially only support the big three: Linux, Windows, Mac OS X.

So what I'd like to do is to use JNI on those three platforms and use the 100% pure Java version on all other platforms. Now I can think of various ways how to do that (loading class dynamically for example and either loading the JNI class or the pure Java one), but thinking that this is a common issue that thousands of projects had to solve in the past for sure, I'm really surprised to not find any documentation or references to the question how to solve this most elegantly or effectively.

+1  A: 

Your platform dependant code should be in a platform dependant class ;-)

Suppose you have a main "Algorithm" class (or better, interface). This interface is implemented by a WindowsAlgorithm using JNI and a HaikuAlgorithm not doing so (it's only for the sake of example). The only thing you have to do now is to load the right one depending upon your client OS, which I think is rather mundane to do.

Riduidel
So this would be dynamic class loading, right? I fire up the JVM without having any class loaded at all, check for the system and then dynamically load either one of the native classes or the 100% pure Java one. However, doing it like that means I also have to "dynamically call" the methods of this class or I have to use an interface, as you suggested, dynamically decide which object to instantiate (so only the constructor call is dynamically dispatched at runtime) and then use this class only through its interface. Correct?
Mecki
Exactly. For an example, take a look at Daff's reply
Riduidel
+1  A: 

If it really makes sense to supply two different versions you could do the following:

  • Create an interface for the class
  • Implement the interface in a class in pure Java
  • Implement the interface in a class that uses JNI

Then you can write a factory method that instantiates the correct class:

public static SomeInterface getInterface()
{               
    SomeInterface res = new JavaSomeInterfaceImpl();

    if (System.getProperty("os.name").matches(".*Windows.*"))
    {
        File library = new File("mylibrary.dll");
        System.load(library.getAbsolutePath());
        res = new NativeSomeInterfaceImpl();
    }

    return res; 
}
Daff
Makes sense - but is that really **the way** to go? Or is it just **a way** to go? Is this what Sun is doing for example or have you seen code like this being used in actual projects?
Mecki
I don't think there is *THE* way to go. What don't you like about that approach? I used that in actual projects, but it couldn't hurt to take a look at the source of the Sun projects that use things like that as well.
Daff
I have not said that I don't like it. I'm just waiting for possibly other suggestions. So far this would be the accepted answer, unless somebody else can come up with a brilliant idea that seems to have advantages over this one.
Mecki