簡體   English   中英

從Java啟動的JRuby腳本加載JNI庫失敗

[英]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中的庫

http://jira.codehaus.org/browse/JRUBY-4620

在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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM