[英]Loading JNI libraries from JRuby script started from Java fails
我想加載Apple的mDNS庫以用於JRuby應用程序。 JRuby應用程序作為Java進程啟動,然后評估Ruby腳本。
這是最小限度再現情況下的Java代碼,它僅獲取Ruby腳本並對其進行評估:
package mdnsscratch;
import com.apple.dnssd.*;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import org.jruby.Ruby;
import org.jruby.RubyInstanceConfig;
import org.jruby.RubyRuntimeAdapter;
import org.jruby.javasupport.JavaEmbedUtils;
import org.jruby.runtime.builtin.IRubyObject;
public final class Main {
public static void main(final String[] args) throws DNSSDException, IOException {
final Main m = new Main();
final byte[] buffy = Files.readAllBytes(Paths.get(args[0]));
m.run(new String(buffy));
}
private void run(final String cmd) {
//System.out.println("About to eval: "+ cmd);
// Get a ruby runtime
final RubyInstanceConfig rubyConfig = new RubyInstanceConfig();
rubyConfig.setExternalEncoding("UTF-8");
rubyConfig.setInternalEncoding("UTF-8");
final Ruby runtime = JavaEmbedUtils.initialize(new ArrayList(), rubyConfig);
final RubyRuntimeAdapter rubyEvaluater = JavaEmbedUtils.newRuntimeAdapter();
final IRubyObject iro = rubyEvaluater.eval(runtime, cmd);
System.out.println(iro.toString());
}
}
這是一個最小的Ruby腳本來再現該問題:
require 'java'
require 'lib/dns_sd.jar'
# Listener
class RegistrarListener
def recordRegistered(record, flags)
end
def operationFailed(service, errorCode)
puts "WARNING: mDNS operation failed"
end
end
# Registrar
puts "About to register"
DNSSD = Java::ComAppleDnssd::DNSSD
@@registrar = DNSSD.createRecordRegistrar(RegistrarListener.new)
puts "Done registering"
mDNS庫具有很多本機代碼,因此我在lib /中有dns_sd.jar和.dylib(我在Mac上)。 使用JRuby的直接評估效果很好:
$ jruby -J-Djava.library.path=lib test_mdns.rb
About to register
Done registering
但是使用Java包裝器會失敗:
$ java -Djava.library.path=lib -cp target/classes:lib/dns_sd.jar:/opt/jruby/lib/jruby.jar mdnsscratch.Main test_mdns.rb
Exception in thread "main" org.jruby.exceptions.RaiseException: (LoadError) no such file to load -- lib/dns_sd
at org.jruby.RubyKernel.require(org/jruby/RubyKernel.java:1071)
at RUBY.(root)(<script>:4)
從Java包裝程序調用JRuby時,似乎似乎看不到mDNS庫的JNI部分。
有人可以幫忙嗎? 很高興回應評論並根據需要提供其他信息。
好的,這是實際上由JRuby運行的Java命令:
/Library/Java/JavaVirtualMachines/java8/Contents/Home/bin/java -Xmx500m
-Xss2048k -Djffi.boot.library.path=/opt/jruby-1.7.17/lib/jni
-Djava.library.path=lib -Dfile.encoding=UTF-8
-Xbootclasspath/a:/opt/jruby-1.7.17/lib/jruby.jar
-classpath : -Djruby.home=/opt/jruby-1.7.17
-Djruby.lib=/opt/jruby-1.7.17/lib -Djruby.script=jruby
-Djruby.shell=/bin/sh org.jruby.Main test_mdns.rb
此等效命令行:
/Library/Java/JavaVirtualMachines/java8/Contents/Home/bin/java -Xmx500m
-Xss2048k -Djffi.boot.library.path=/opt/jruby-1.7.17/lib/jni
-Djava.library.path=lib -Dfile.encoding=UTF-8
-Xbootclasspath/a:/opt/jruby-1.7.17/lib/jruby.jar
-classpath target/classes:lib/dns_sd.jar
-Djruby.home=/opt/jruby-1.7.17 -Djruby.lib=/opt/jruby-1.7.17/lib
-Djruby.script=jruby -Djruby.shell=/bin/sh mdnsscratch.Main test_mdns.rb
仍然給出錯誤。 當前正在研究JRuby源代碼,我看到提到了一個特殊的線程本地類加載器,這很有趣,特別是因為JRuby調用包含一個空的classpath參數。
從bootclasspath加載的類只能鏈接到$ JAVA_HOME / bin中的庫
在Twitter上的對話中:“ JRuby啟動器將。放在類路徑中,類似於java命令,但是您的java cmd指定了類路徑,所以沒有pwd。”
新增。 classpath可以解決此問題:
java -Djava.library.path=lib -cp target/classes:lib/dns_sd.jar:/opt/jruby/lib/jruby.jar:. mdnsscratch.Main test_mdns.rb
About to register
Done registering
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.