Forum Stats

  • 3,853,777 Users
  • 2,264,267 Discussions
  • 7,905,444 Comments

Discussions

Loading more than one library per native call

843829
843829 Member Posts: 49,201
edited Sep 20, 2010 2:08PM in Java Native Interface (JNI)
Hi all,

I never really used forums before, but now I am really stuck... Ok I have a java application that needs to load several c++ libraries.

The C++ libraries are supposed to do the following
libA.so prints Hello A.
libB.so prints Hello B.

Java Classes
abstract class Master
{
public abstract void testeMyFunction(String name);
}


class A extends Master
{
A(String lib)
{
System.load(lib);
}

public native void testeMyFunction(String name);
}

public class Main
{
public static void main(String[] args) throws Exception
{
A a =new A("/home/filipe/workspace/TESTES/myTeste/Debug/libA.so");
a.testeMyFunction("Lib");

A b = new A("/home/filipe/workspace/TESTES/myTeste2/Debug/libB.so");
b.testeMyFunction("Lib");
}
}

The expected output should be:
Hello A
Hello B

However the result is Hello A Hello A :(

I believe its because it is binding the native call to the first System.load (in this case libA.so) and therefore its not loading the second library properly... Is there anyway you guys can recommend to have the desired output?

Thanks a million,
Filipe

Edited by: TonyCarreira on Sep 17, 2010 8:24 AM

Comments

  • jschellSomeoneStoleMyAlias
    jschellSomeoneStoleMyAlias Member Posts: 24,877 Gold Badge
    Use code tags when you post code.

    Your problem cannot be solved as stated in Java, nor any programming language nor even logically.

    You have a value X (your java method) and you wish to map it to two values (C methods) and then call each without differentiating them.
    That is not possible.

    And it is obvious if you suppose that you now create a new instance called c from A - so which C library is it supposed to call?

    The first step is that you MUST differentitate the two calls. For example pass a boolean. Or some other id.
    Then your JNI code uses that passed in value to decide with C method to call.
  • 843829
    843829 Member Posts: 49,201
    Thanks for the reply mate.

    I found a way of doing it, but it involves having to "unload" the library. The way I did it, involved calling the finalize method of the classLoader (which is a big cock-up and really unsafe) Are you aware of any other way to unload the library?
  • EJP
    EJP Member Posts: 32,920 Gold Crown
    edited Sep 18, 2010 4:29AM
    Why not have two native classes, one per native library? Have them both implement the same interface? A bit of OO design, in fact?

    In fact, why have two native libraries at all?
  • 843829
    843829 Member Posts: 49,201
    Well mate its obvious that if I wanted to use one native method per library I would have, if I didnt its because I have requirements to do the way I did.

    Basically we are building a Java application that loads dynamic libraries (therefore you dont know when or what the library will be about) the same native method is supposed to be used by multiple libraries hence we have two possible solutions:
    1 - unload the previous library (which is quite hard to do safelly)
    2 - use a different classloader.

    My question now is, is there any way (safe) to unload a loaded Dll or SO library?
  • EJP
    EJP Member Posts: 32,920 Gold Crown
    edited Sep 19, 2010 8:04AM
    Surely it is clear that this architecture is the problem? Not the solution.
  • 800381
    800381 Member Posts: 486
    TonyCarreira wrote:
    Well mate its obvious that if I wanted to use one native method per library I would have, if I didnt its because I have requirements to do the way I did.

    Basically we are building a Java application that loads dynamic libraries (therefore you dont know when or what the library will be about) the same native method is supposed to be used by multiple libraries hence we have two possible solutions:
    1 - unload the previous library (which is quite hard to do safelly)
    2 - use a different classloader.

    My question now is, is there any way (safe) to unload a loaded Dll or SO library?
    I seriously doubt your requirements specify a solution that ignores how dynamic linking works. And if they DO, you need to find people to write requirements to solve a problem, and not requirements that specify an impossible solution.

    And no, there's no way to safely unload a shared library when you can't control its usage. Since you have no control over when any finalize() method that would unload the library would be called, you can't do anything to ensure one library is unloaded before the next one is loaded.

    Never mind the fact that swapping libraries like you're proposing is inherently unsafe in a multithreaded environment - which a JVM is.
  • jschellSomeoneStoleMyAlias
    jschellSomeoneStoleMyAlias Member Posts: 24,877 Gold Badge
    TonyCarreira wrote:
    Thanks for the reply mate.

    I found a way of doing it, but it involves having to "unload" the library. The way I did it, involved calling the finalize method of the classLoader (which is a big cock-up and really unsafe) Are you aware of any other way to unload the library?
    That would not solve the original question that you posted.

    If your real question is that you want to replace a JNI library with a newer version then the solution (with the Sun VM) is as follows.
    1. Use a class loader
    2. Use appropriate proxies to insure control of the class references
    3. During the class loader reload sequence call System.gc() twice.

    If you mess up 2 then step 3 will not work.
This discussion has been closed.