twall/jna — Issue #44: Incorrect behavior loading multi librarys
Author: panga
Created: 2011-12-21 21:46:37+00:00
State: open

I have a problem with the simultaneous use of two libraries in the JVM on Linux using JNA (3.4.0).

The problem occurs when two third-party libraries (not mine) have global variables with the same name.

When calling functions that manipulate global variables, I have a BIG problem.

I found that the problem only occurs on Linux and probably other platforms using the "dlopen" for Windows works properly.

In revision 771 (svn repo) was added "set RTLD_GLOBAL flag" to dlopen function call.

This flag set all subsequent casll to dlopen to share same namespace for C global variables (shared), not only external vars.

File: dispatch.c
Line 67: #define LOAD_LIBRARY(NAME) dlopen(NAME, RTLD_LAZY|RTLD_GLOBAL)

The fix is remove flag RTLD_GLOBAL for dlopen call or create a option (Map options).

I made a workaround to resolve the problem immediately loading the libraries before using the JNA.

Example
-

Wrong output:
-
```java
[root@jbosscluster bin]# java -jar Main.jar
Foo count: 1
Func number: 2
Current foo count: 2
Current func number: 2
Foo count: 3
Func number: 4
Current foo count: 4
Current func number: 4
[root@jbosscluster bin]#
```
Correct output:
-
```java
[root@jbosscluster bin]# java -jar Main.jar
Foo count: 1
Func number: 1
Current foo count: 1
Current func number: 1
Foo count: 2
Func number: 2
Current foo count: 2
Current func number: 2
[root@jbosscluster bin]#
```

Main.java
-
```java
public interface Foo extends Library {
void addCount();
int getCount();
}

public interface Func extends Library {
void addNumber();
int getNumber();
}

public interface DL extends Library {
public static final int
RTLD_LOCAL = 0x00000,
RTLD_LAZY = 0x00001,
RTLD_NOW = 0x00002,
RTLD_BINDING_MASK = 0x3,
RTLD_NOLOAD = 0x00004,
RTLD_DEEPBIND = 0x00008,
RTLD_GLOBAL = 0x00100,
RTLD_NODELETE = 0x01000;

public Pointer dlopen(String file, int mode);
public int dlclose(Pointer handle);
}

public class Main {
public static void main(String args[]) throws Exception {
/*
* Workarround for RTLD_GLOBAL flag in function dlopen called by JNA
*/
if (Platform.isLinux()) {
DL dl = (DL)Native.loadLibrary("dl", DL.class);
dl.dlopen("libFoo.so", dl.RTLD_LAZY);
dl.dlopen("libFunc.so", dl.RTLD_LAZY);
}

Foo foo = (Foo)Native.loadLibrary("Foo", Foo.class);
Func func = (Func)Native.loadLibrary("Func", Func.class);

foo.addCount();
func.addNumber();

System.out.println("Current foo count: "+foo.getCount());
System.out.println("Current func number: "+func.getNumber());

foo.addCount();
func.addNumber();

System.out.println("Current foo count: "+foo.getCount());
System.out.println("Current func number: "+func.getNumber());
}
}
```

func.c
-
```c++
#include
#include
#include "func.h"

int count = 0;

void addNumber()
{
count++;
printf("Func number: %d\n",count);
}

int getNumber() {
return count;
}
```

foo.c
-
```c++
#include
#include
#include "foo.h"

int count = 0;

void addCount()
{
count++;
printf("Foo count: %d\n",count);
}

int getCount() {
return count;
}
```

func.h
-
```c++
extern "C"
{
void addNumber();
int getNumber();
}
```

foo.h
-
```c++
extern "C"
{
void addCount();
int getCount();
}
```