我想加载Apple的mDNS库以用于JRuby应用程序。 JRuby应用程序作为Java进程启动,然后评估Ruby脚本。
这是一个最小的repro案例的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)
似乎JRuby从Java包装器调用时,看不到mDNS库的JNI部分。
有人可以帮忙吗?很高兴回应评论&amp;根据需要提供额外信息。
好的,所以这是实际由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参数时。
答案 0 :(得分:0)
从bootclasspath加载的类只能链接到库中 $ JAVA_HOME / bin中
答案 1 :(得分:0)
来自Twitter上的对话:&#34; JRuby启动器放置。在classpath中类似于java命令,但是你的java cmd指定了一个类路径,所以没有pwd。&#34;
添加。到类路径修复此:
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