私は Java の世界は初めてですが、Ruby には精通しています。サードパーティの jar ファイルと対話するプログラムを作成しようとしています。
ライブラリは、Java から呼び出された場合は正常に動作するように見えますが、JRuby で呼び出すと正しく動作しません。私は本当にJRubyを使いたいので、これは問題です。たとえば、以下の 2 つのプログラムはまったく同じことをしようとしますが、異なる出力を生成します。
この Java プログラムは正しく動作します。
以下の Java プログラムを Netbeans で開発し、F6 (メイン プロジェクトの実行) を押して実行しました。プロジェクトの Libraries フォルダは、「C:\Program Files (x86)\Microchip\MPLABX\mplab_ide\lib\nblibraries.properties」に設定されています。実行すると、「pins: 17」と出力されます。
package pinbug1;
import com.microchip.mplab.mdbcore.assemblies.Assembly;
import com.microchip.mplab.mdbcore.assemblies.AssemblyFactory;
import com.microchip.mplab.mdbcore.simulator.PinSet;
import com.microchip.mplab.mdbcore.simulator.Simulator;
import org.openide.util.Lookup;
public class PinBug1
{
public static void main(String[] args)
{
AssemblyFactory assemblyFactory = Lookup.getDefault().lookup(AssemblyFactory.class);
Assembly assembly = assemblyFactory.Create("PIC18F14K50");
Simulator simulator = assembly.getLookup().lookup(Simulator.class);
int num = simulator.getDataStore().getProcessor().getPinSet().getNumPins();
System.out.println("pins: " + num); // prints "pins: 17"
}
}
この JRuby プログラムは正しく動作しません。
以下のJRubyプログラムを入力するだけで実行したところ、jruby bug_reproduce.rb
「pins: 0」と出力されました。Java プログラムのように「pins: 17」と表示されると思います。
["mplab_ide/mdbcore/modules/*.jar",
"mplab_ide/mplablibs/modules/*.jar",
"mplab_ide/mplablibs/modules/ext/*.jar",
"mplab_ide/platform/lib/org-openide-util*.jar",
"mplab_ide/mdbcore/modules/ext/org-openide-filesystems.jar"
].each do |pattern|
Dir.glob("C:/Program Files (x86)/Microchip/MPLABX/" + pattern).each do |x|
require x
end
end
assemblyFactory = org.openide.util.Lookup.getDefault.lookup(com.microchip.mplab.mdbcore.assemblies.AssemblyFactory.java_class)
assembly = assemblyFactory.create("PIC18F14K50")
simulator = assembly.getLookup.lookup(com.microchip.mplab.mdbcore.simulator.Simulator.java_class)
num = simulator.getDataStore.getProcessor.getPinSet.getNumPins
puts "pins: #{num}" # => pins: 0
詳細
約 80 個のサードパーティの jar ファイルがあります。それらはMPLAB Xの一部として Microchip によって提供され、マイクロコントローラ用のシミュレータを実装します。jar ファイルは MPLAB X に付属しており、MPLAB X SDKもダウンロードして使用方法を調べました。ライブラリの文書化されていない機能を多数使用していますが、代替手段がありません。
Windows 7 64 ビット SP1 を使用しています。次のJava関連のものをインストールし、「プログラムと機能」の下にリストしました。
- Java 7 アップデート 17
- Java 7 アップデート 17 (64 ビット)
- Java SE 開発キット 7 Update 17 (64 ビット)
- Java(TM) 6 Update 22 (64 ビット)
- Java(TM) 6 アップデート 29
- Java(TM) SE 開発キット 6 Update 22 (64 ビット)
- JRuby 1.7.3
- IntelliJ IDEA コミュニティ エディション 12.0.4
- NetBeans IDE 7.3
- MPLAB X IDE v1.70
System.getProperty("java.version")
両方のプログラムが Java 1.6.0_22 で実行されていることを確認していました。MPLAB X SDK の指示に従ったので、「最良の結果を得るには、コードが通信する IDE/MDBCore をビルドしたものとまったく同じ JDK を使用してください。MPLAB X v1.70 の場合、これは JDK 6u22 です。オラクルから。」この問題が発生した後、JDK 7u17 のみをインストールしましたが、違いはありませんでした。
例で特定された特定の問題に対する回避策を見つけることができましたが、開発を続けたところ、ライブラリの動作が異なるという別の問題に遭遇しました。これは、JRuby の使い方が根本的に間違っていると思います。
異なるクラス パスがこの問題を引き起こす可能性があると考えて、Java プログラムにそのクラス パスを出力させようとし、JRuby プログラムを編集してそのリスト内のファイルを正確に要求するようにしましたが、違いはありませんでした。
質問
- Java ではなく JRuby から呼び出された場合に、JAR ファイル内のコードの動作が異なる可能性があることを知っていますか?
- JRuby 1.7.3 が使用する JDK のバージョンは何ですか?それとも、その質問は理にかなっていますか?
更新:解決済み
実際に MPLAB X を入手し、私の問題を解決してくれた D3mon-1stVFW に感謝します! 核心的な詳細に興味がある人のために: ピンは PinSet.getPin(String) でアクセスされるときに遅延ロードされるため、ピンの数は 0 でした。ペリフェラルがピンをロードするため、通常はすべてのピンがロードされますが、JRuby ではペリフェラルが検出されませんでした。これは、周辺文書が見つからなかったためです。これは、PerDocumentLocator.findDocs() が空のリストを返したためです。PerDocumentLocatorcom.microchip.mplab.open.util.pathretrieval.PathRetrieval.getPath(com.microchip.mplab.libs.MPLABDocumentLocator.MPLABDocumentLocator.class))
は間違ったものを返していたため失敗しました。
PathRetrieval.getPath 内で起こっていることと似ている次のコードを考えてみましょう (Java で書かれていることを除いて)。
com.microchip.mplab.libs.MPLABDocumentLocator.MPLABDocumentLocator.java_class.resource("MPLABDocumentLocator.class").getFile()
D3mon-1stVFW のヒントに従って、JAR ファイルを $CLASSPATH に追加すると、そのコードは次のように戻ります。
ファイル:C:/Program Files (x86)/Microchip/MPLABX/mplab_ide/mplablibs/modules/com-mi crochip-mplab-libs-MPLABDocumentLocator.jar!/com/microchip/mplab/libs/MPLABDocum entLocator/MPLABDocumentLocator.class
ただし、クラスパスに何かを追加しないと、そのコードは奇妙なことに次のように返されます。
ファイル:C:%5CProgram%20Files%20(x86)%5CMicrochip%5CMPLABX%5Cmplab_ide%5Cmplablibs% 5Cmodules%5Ccom-microchip-mplab-libs-MPLABDocumentLocator.jar!/com/microchip/mpl ab/libs/MPLABDocumentLocator/MPLABDocumentLocator.クラス"
%5C は実際にはバックスラッシュのコードです。PathRetrieval.getPath の Microchip コードは多くの文字列操作を行い、スラッシュが %5C で表されるケースを適切に処理しません。%5Cs が表示される理由についてさらに洞察を持っている人がいれば、知りたいと思いますが、私の問題は解決しました。
結論: Java のgetResource()がスラッシュの代わりに %5C を含む URL を返す場合があり、これは CLASSPATH の内容に影響されます。安全を確保したい場合は、次のように、要求する前に jar ファイルを $CLASSPATH に追加します。
require 'java'
$CLASSPATH << jar_filename
require jar_filename