2016-07-27 6 views
5

JNAを使用して、スレッドセーフでないネイティブのFortranライブラリを同時に操作しようとしています。ライブラリはスレッドセーフではないので、私は同じライブラリの異なるコピーをインスタンス化しようとしますが、明らかにメモリアドレスを共有しているようです。 1つのライブラリ内の1つの変数を変更すると、他のライブラリの変数は次のように変更されます。この動作により、別々のスレッドでconcurentlyで実行することができなくなります。同じシンボルを含む2つのネイティブライブラリをロードする際にメモリの問題が発生する

次のコード例は、私が何を意味するかを示しています。

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 

このファイルがコンパイルされ、次のようにコピーされます。

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

それから私は使用して、これら2にアクセス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()); 

    } 

上記のコードの出力は9です。つまり、2つのライブラリがメモリを共有しているようです。

完全に独立させる方法はありますか?私は同じ結果をインテルFortranコンパイラを使って同じものを試しました。

答えて

2

dlopenでライブラリを開くときに、JNAはRTLD_LAZY | RTLD_GLOBALを使用します。これはおそらくシンボルが共有されているためです。これらのフラグは次のように上書きできます。

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

rtld_localをどのように見つけることができますか?私はCentOS 7を使用しています –

+0

'RTLD_LOCAL'は値0(GLIBC2.4)を持っているとは思いますが、予想される動作は' RTLD_LOCAL = 1'で設定します。 'RTLD_LOCAL = 0'を設定した場合、' Native.loadLibrary'はライブラリ(つまりsoファイル)が見つからないと告げる。 PS:あなたの答えのような署名を持つメソッドNative.loadLibraryはありません。あなたはインターフェイスクラスがありません。 –

+0

'RTLD_LAZY'(OSXでは" 1 "の値を持ち、LinuxのATMはチェックできません)を含める必要があるかもしれません。 'RTLD_LOCAL'を" 1 "と定義しないでください。それは間違っています。 'OPTIONS = 1'を定義してそれを残しておけば何も問題ありません。誰もコードのその部分を再利用することがない場合は、定数を定義する必要はありません。 – technomage

関連する問題