2016-07-27 7 views
5

Ich versuche, eine native, nicht Thread-sichere Fortran-Bibliothek gleichzeitig mit JNA zu betreiben. Da die Bibliothek nicht Thread-sicher ist, versuche ich, verschiedene Kopien derselben Bibliothek zu instanziieren, aber scheinbar teilen sie sich Speicheradressen. Wenn ich eine Variable in einer Bibliothek ändere, wird die Variable in der anderen Bibliothek geändert. Dieses Verhalten macht es unmöglich, sie in separaten Threads auszuführen.Speicherprobleme beim Laden von zwei nativen Bibliotheken mit denselben Symbolen

Das folgende Codebeispiel zeigt, was ich meine:

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 

Diese Datei kompiliert und kopiert wie folgt:

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

Dann Zugriff über diese beiden I 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()); 

    } 

Die Ausgabe des obigen Codes ist 9, was bedeutet, dass die beiden Bibliotheken ihren Speicher teilen.

Gibt es eine Möglichkeit, sie vollkommen unabhängig zu machen? Ich habe das gleiche mit Intel Fortran Compiler versucht, das gleiche Ergebnis.

Antwort

2

JNA verwendet RTLD_LAZY | RTLD_GLOBAL beim Öffnen einer Bibliothek über dlopen, weshalb wahrscheinlich die Symbole geteilt werden. Sie können diese Flags wie folgt überschreiben:

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

Wie kann ich rtld_local herausfinden? Ich benutze CentOS 7 –

+0

Ich bekomme das erwartete Verhalten mit der Einstellung 'RTLD_LOCAL = 1', obwohl ich denke,' RTLD_LOCAL' hat den Wert 0 (GLIBC2.4). Wenn ich 'RTLD_LOCAL = 0 'festlege, beschwert sich' Native.loadLibrary', dass die Bibliothek (d. H. Die So-Datei) nicht gefunden werden kann. PS: Es gibt keine solche Methode 'Native.loadLibrary' mit einer Signatur wie in Ihrer Antwort fehlt Ihnen die Interface-Klasse. –

+0

Eventuell müssen Sie 'RTLD_LAZY' einbeziehen (das unter OSX einen Wert von" 1 "hat, kann Linux ATM nicht überprüfen). Definiere 'RTLD_LOCAL' nicht als" 1 ", das ist falsch. Es ist nichts falsch daran, einfach 'OPTIONS = 1' zu definieren und es dabei zu belassen; Es gibt keine Notwendigkeit, die Konstanten zu definieren, wenn niemand sonst diesen Teil des Codes wiederverwenden wird. – technomage

Verwandte Themen