参考までに、これを行うために実装した次のクラスを共有したかっただけです。指定されたライブラリとインターフェースを受け取り、n
コピーを作成し、JNA プロキシされたインターフェースを各コピーにマップします。次に、スレッドセーフ ロックを実装する別のプロキシされたインターフェースを返し、再入可能でプロセッサ数 1 まで実行できるバージョンを作成します。もっている。
public class LibraryReplicator<C> {
final BlockingQueue<C> libQueue;
final Class<C> interfaceClass;
final C proxiedInterface;
@SuppressWarnings("unchecked")
public LibraryReplicator(URL libraryResource, Class<C> interfaceClass, int copies) throws IOException {
if (!interfaceClass.isInterface())
throw new RuntimeException(interfaceClass + "is not a valid interface to map to the library.");
libQueue = new LinkedBlockingQueue<C>(copies);
this.interfaceClass = interfaceClass;
// Create copies of the file and map them to interfaces
String orig = libraryResource.getFile();
File origFile = new File(orig);
for( int i = 0; i < copies; i++ ) {
File copy = new File(orig + "." + i);
Files.copy(origFile, copy);
C libCopy = (C) Native.loadLibrary(copy.getPath(), interfaceClass);
libQueue.offer(libCopy); // This should never fail
}
proxiedInterface = (C) Proxy.newProxyInstance(
interfaceClass.getClassLoader(),
new Class[] { interfaceClass },
new BlockingInvocationHandler());
}
public LibraryReplicator(URL libraryResource, Class<C> interfaceClass) throws IOException {
this(libraryResource, interfaceClass, Runtime.getRuntime().availableProcessors());
}
public C getProxiedInterface() {
return proxiedInterface;
}
/*
* Invocation handler that uses the queue to grab locks and maintain thread safety.
*/
private class BlockingInvocationHandler implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Exception {
C instance = null;
// Grab a copy of the library out of the queue
do {
try { instance = libQueue.take(); }
catch(InterruptedException e) {}
} while(instance == null);
// Invoke the method
Object result = method.invoke(instance, args);
// Return the library to the queue
while(true) {
try { libQueue.put(instance); break; }
catch( InterruptedException e ) {}
}
return result;
}
}
}
使用例は、静的初期化子の一部として次のようなものです。
MvnPackGenz lib = new LibraryReplicator<MvnPackGenz>(
MvnPackGenz.class.getClassLoader().getResource("mvnpack.so"),
MvnPackGenz.class).getProxiedInterface();
これにより、ライブラリのコピーの束 (私の場合は 12) が作成され、そのlib
上に再入可能に「見える」変数が作成され、複数のスレッドで安全に実行できます。
-rw-r--r-- 1 mao mao 50525 Sep 26 13:55 mvnpack.so
-rw-r--r-- 1 mao mao 50525 Sep 26 18:21 mvnpack.so.0
-rw-r--r-- 1 mao mao 50525 Sep 26 18:21 mvnpack.so.1
-rw-r--r-- 1 mao mao 50525 Sep 26 18:21 mvnpack.so.10
-rw-r--r-- 1 mao mao 50525 Sep 26 18:21 mvnpack.so.11
-rw-r--r-- 1 mao mao 50525 Sep 26 18:21 mvnpack.so.2
-rw-r--r-- 1 mao mao 50525 Sep 26 18:21 mvnpack.so.3
-rw-r--r-- 1 mao mao 50525 Sep 26 18:21 mvnpack.so.4
-rw-r--r-- 1 mao mao 50525 Sep 26 18:21 mvnpack.so.5
-rw-r--r-- 1 mao mao 50525 Sep 26 18:21 mvnpack.so.6
-rw-r--r-- 1 mao mao 50525 Sep 26 18:21 mvnpack.so.7
-rw-r--r-- 1 mao mao 50525 Sep 26 18:21 mvnpack.so.8
-rw-r--r-- 1 mao mao 50525 Sep 26 18:21 mvnpack.so.9
更新されたバージョンは、次の場所で確認できます。
https://github.com/mizzao/libmao/blob/master/src/main/java/net/andrewmao/misc/LibraryReplicator.java