Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JNA can't load several libraries with same method name #716

Closed
ldulout opened this issue Oct 11, 2016 · 5 comments
Closed

JNA can't load several libraries with same method name #716

ldulout opened this issue Oct 11, 2016 · 5 comments

Comments

@ldulout
Copy link

ldulout commented Oct 11, 2016

It seems that my native shared libraries (.so) can't declare a method with the same name.

An example is worth a thousand words...
I have a native1.c:

#include <stdio.h>
int anotherMethod() {
    return 100;
}
int method() {
     return 1 + anotherMethod();
}

And a native2.c:

#include <stdio.h>
int anotherMethod() {
    return 200;
}
int method() {
    return 2 + anotherMethod();
}

Each are compiled in a shared library (libnative1.so and libnative2.so).

$ gcc -m64 -shared -fPIC -o linux-x86-64/libnative1.so native1.c
$ gcc -m64 -shared -fPIC -o linux-x86-64/libnative2.so native2.c

(I am on a 64bit linux)

So invoking method() should return :

  • 101 in native1
  • 202 in native2

I will try it in a small Java Main :

public static void main(String[] args) {
    Native1 native1 = (Native1) Native.loadLibrary("native1", Native1.class);
    Native2 native2 = (Native2) Native.loadLibrary("native2", Native2.class);
    System.out.println(native1.method());
    System.out.println(native2.method());
}

The libraries interfaces are minimalists:

public interface Native1 extends Library {
    int method();
}

And

public interface Native2 extends Library {
    int method();
}

I obtain :

101 // OK

102 // Should be 202 !

It means the good method() is invoked, but when my native code calls anotherMethod(), only the one from native1 is invoked.

I think Native.loadLibrary() loads my shared libraries and flatten it so only the first "anotherMethod" symbol exists.

In my real world case, the C code isn't under my responsibility, it is provided by another editor, so the less I have to edit it is the best

Could JNA provide a system to isolate each loaded library as they are different objects in my Java code ?

@matthiasblaesing
Copy link
Member

My reading:

  • JNA resolves the correct methods (the last digit in your test indicates the first method in the call chain)
  • the library linker then links the resolves the symbol "anotherMethod" incorrectly (from your POV)

I gave google a spin and the issue is the same in plain C! A q'n'd solution could be to spawn two process that each load one of the libraries and invoke the methods via in RPC bridge.

@matthiasblaesing
Copy link
Member

Oh - and maybe a good approach: Talk to the vendors of the libraries and make them use separate namespaces.... or let them explain how they think that problem should be resolved.

@ldulout
Copy link
Author

ldulout commented Oct 13, 2016

Sadly I can't edit the code and in fact, the vendor give us a new version of their lib, and our software has to use old versions for old files...

When in plain C, I can use dlopen() with RTLD_LOCAL option to solve it... Could I use something similar in JNA ?

@matthiasblaesing
Copy link
Member

I never before looked at this code, but check:

Native#getInstance(String, Map<String,?>)

This method allows loading a libraries with a set of options. And one of these options is:

Library.OPTION_OPEN_FLAGS

the value of the open flags is directly passed to native and passed into dl_open. So this could do the trick (untested!):

   Map<String,?> options = new HashMap<>();
   options.put(Library.OPTION_OPEN_FLAGS, 0); // if I read the headers correctly 0 is the value of RTLD_LOCAL
    Native1 native1 = (Native1) Native.loadLibrary("native1", Native1.class, options);
    Native2 native2 = (Native2) Native.loadLibrary("native2", Native2.class, options);
    System.out.println(native1.method());
    System.out.println(native2.method());

@matthiasblaesing
Copy link
Member

Closing - I'll asume this is fully answered.

mstyura pushed a commit to mstyura/jna that referenced this issue Sep 9, 2024
Motivation:

Quiche had some changes related to when it will detect / handle reset
frames. We should pull these in.

Modifications:

Update quiche sha to a9b3954090488e940b673c18e1660d66b3ccf565.

Result:

Have fixes for reset frames
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants