2016-07-27 10 views
5

Próbuję korzystać z natywnej biblioteki Fortran, która nie jest wątkowo bezpieczna, jednocześnie używając JNA. Ponieważ biblioteka nie jest bezpieczna dla wątków, próbuję utworzyć różne kopie tej samej biblioteki, ale najwyraźniej wydają się one współużytkować adresy pamięci. Jeśli zmodyfikuję jedną zmienną w jednej bibliotece, zmienna w drugiej bibliotece zostanie zmieniona na. Takie zachowanie uniemożliwia uruchamianie ich jednocześnie w osobnych wątkach.Problemy z pamięcią podczas ładowania dwóch rodzimych bibliotek zawierających te same symbole.

Poniższy przykład pokazuje kod co mam na myśli:

code.f:

subroutine set(var) 
    implicit none 
    integer var,n 
    common/conc/n 
    n=var 
    end subroutine 

    subroutine get(var) 
    implicit none 
    integer var,n 
    common/conc/n 
    var=n 
    end subroutine 

Plik ten jest kompilowany i kopiowane w sposób następujący:

gfortran -shared -O2 code.f -o mylib.so -fPIC 
cp mylib.so mylib_copy.so 

Potem dostęp przy użyciu tych dwóch JNA:

import com.sun.jna.Library; 
import com.sun.jna.Native; 
import com.sun.jna.ptr.IntByReference; 

public class JNA { 
    public interface MyLib extends Library { 
     public void set_(IntByReference var); 
     public void get_(IntByReference var); 
    } 

    public static void main(String[] args) { 
     System.setProperty("jna.library.path", "."); 
     MyLib lib = (MyLib) Native.loadLibrary("mylib.so", MyLib.class); 
     MyLib lib_copy = (MyLib) Native.loadLibrary("mylib_copy.so", MyLib.class); 

     # set a common variable in mylib 
     lib.set_(new IntByReference(9)); 

     # access the variable in mylib_copy 
     IntByReference result = new IntByReference(); 
     lib_copy.get_(result); 
     System.out.println(result.getValue()); 

    } 

Dane wyjściowe powyższego kodu to 9, co oznacza, że ​​dwie biblioteki wydają się udostępniać swoją pamięć.

Czy istnieje sposób, aby były całkowicie niezależne? Próbowałem tego samego przy użyciu kompilatora Intel Fortran, ten sam wynik.

Odpowiedz

2

JNA używa RTLD_LAZY | RTLD_GLOBAL podczas otwierania biblioteki przez dlopen, prawdopodobnie dlatego symbole są udostępniane. Można zastąpić te flagi w następujący sposób:

int RTLD_LOCAL = ??; // look this up on your system 
Map options = new HashMap(); 
options.put(Library.OPTION_OPEN_FLAGS, RTLD_LOCAL); 
MyLib mylib = Native.loadLibrary("mylib", MyLib.class, options); 
MyLib mylib2 = Native.loadLibrary("mylib2", MyLib.class, options); 
+0

Jak mogę się dowiedzieć, rtld_local? Używam CentOS 7 –

+0

Otrzymuję oczekiwane zachowanie z ustawieniem 'RTLD_LOCAL = 1', chociaż myślę, że' RTLD_LOCAL' ma wartość 0 (GLIBC2.4). Jeśli ustawię 'RTLD_LOCAL = 0', to' Native.loadLibrary' narzeka, że ​​nie można znaleźć biblioteki (tj. Tak-pliku). PS: Nie ma takiej metody 'Native.loadLibrary' z podpisem jak w twojej odpowiedzi, brakuje ci klasy interfejsu. –

+0

Być może będziesz musiał dołączyć 'RTLD_LAZY' (który ma wartość" 1 "na OSX, nie może sprawdzić linuksowego ATM). Nie definiuj 'RTLD_LOCAL' jako" 1 ", to jest niepoprawne. Nic złego w tym, że po prostu definiujesz 'OPCJE = 1' i pozostawiasz to; nie ma potrzeby definiowania stałych, jeśli nikt inny nie użyje ponownie tej części kodu. – technomage

Powiązane problemy