7

我是 Java 世界的新手,但对 Ruby 很熟悉。我正在尝试编写一个与一些第三方 jar 文件交互的程序。

虽然如果从 Java 调用这些库似乎表现良好,但当我在 JRuby 中调用它们时它们的行为不正确。这是一个问题,因为我真的很想使用 JRuby。例如,下面的两个程序尝试做完全相同的事情,但它们产生不同的输出:

该 Java 程序运行正常。

我在 Netbeans 中开发了下面的 Java 程序并按 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文件。它们由 Microchip 作为MPLAB X的一部分提供,并为其微控制器实现模拟器。jar 文件随 MPLAB X 一起提供,我还下载了MPLAB X SDK以获得使用它们的帮助。我正在使用库的许多未记录的功能,但我没有看到任何替代方案。

我正在使用 Windows 7 64 位 SP1。我在“程序和功能”下安装并列出了以下与 Java 相关的东西:

  • Java 7 更新 17
  • Java 7 更新 17(64 位)
  • Java SE 开发工具包 7 更新 17(64 位)
  • Java(TM) 6 更新 22(64 位)
  • Java(TM) 6 更新 29
  • Java(TM) SE 开发工具包 6 更新 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 程序以精确地要求该列表中的文件,但这没有任何区别。

问题

  • 您是否知道从 JRuby 而不是 Java 调用时可能导致 JAR 文件中的代码行为不同的任何事情?
  • JRuby 1.7.3 使用什么版本的 JDK,或者这个问题是否有意义?

更新:已解决

感谢 D3mon-1stVFW 真正获得 MPLAB X 并为我解决了我的问题!对于那些对细节感兴趣的人:引脚数为 0,因为引脚在使用 PinSet.getPin(String) 访问时是延迟加载的。通常所有引脚都会被加载,因为外围设备会加载它们,但在 JRuby 下没有检测到外围设备。这是因为找不到外围文档。这是因为 PerDocumentLocator.findDocs() 返回了一个空列表。PerDocumentLocator 失败,因为com.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-microchip-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 表示的情况。如果有人对 %5C 出现的原因有任何进一步的了解,我很想知道,但我的问题已经解决了。

结论:有时 Java 的getResource()会返回一个带有 %5C 而不是斜杠的 URL,这会受到 CLASSPATH 上的内容的影响。如果您想安全起见,请在需要之前将 jar 文件添加到 $CLASSPATH,如下所示:

require 'java'
$CLASSPATH << jar_filename
require jar_filename
4

1 回答 1

4

使用此实现,我能够获得预期的结果。这种植入的主要区别是将 jars 添加到类路径中。如果您评论此行 ( $CLASSPATH << jar_file),您将获得 0 个引脚。(问题底部的解释)

require 'java'

Dir.glob("C:/MyCustomLibraries/MATLAB/*.jar").each do |jar_file| #Has all MPLab jars except org.netbeans.*
  $CLASSPATH << jar_file
  require jar_file
end

module Mplab
  include_package "org.openide.util" #Lookup
  include_package "com.microchip.mplab.mdbcore.simulator" #PinSet, Simulator
  include_package "com.microchip.mplab.mdbcore.assemblies" #Assembly, AssemblyFactory
end

assembly_factory = Mplab::Lookup.getDefault.lookup(Mplab::AssemblyFactory.java_class)
assembly = assembly_factory.create("PIC18F14K50")
simulator = assembly.getLookup.lookup(Mplab::Simulator.java_class)
num = simulator.getDataStore.getProcessor.getPinSet.getNumPins
puts "pins: #{num}" 

输出

内容/mplab/mplab.deviceSupport

内容/mplab/MPHeader.xml

内容/mplab/PluginBoardSupport.xml

针数:17

于 2013-04-03T21:42:26.873 回答