什么原因导致Java库在被JRuby调用时行为有所不同?

我对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 bug_reproduce.rb来运行JRuby程序,并打印出“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 Update 17
  • Java 7 Update 17(64位)
  • Java SE开发工具包7更新17(64位)
  • Java(TM)6 Update 22(64位)
  • Java(TM)6 Update 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中的说明:“为获得最佳结果,请使用完全相同的JDK,您的代码将与之建立的IDE / MDBCore进行通信。对于MPLAB X v1.70,这是JDK 6u22来自Oracle“。 我遇到这个问题后我只安装了JDK 7u17,并没有什么区别。

    我能够找到解决方案中的具体问题,但后来我继续我的发展,并遇到另一个问题,图书馆的行为有所不同。 这使我认为我在使用JRuby的方式上做了一些根本性错误。

    考虑到不同的类路径可能导致这个问题,我试图让java程序打印出它的类路径,然后编辑我的JRuby程序以精确地要求列表中的文件,但它没有区别。

    问题

  • 你知道任何可能导致JAR文件中的代码在从JRuby而不是Java中调用时的行为有所不同吗?
  • JRuby 1.7.3使用的是什么版本的JDK,或者这个问题甚至有意义?
  • 更新:已解决

    感谢D3mon-1stVFW实际获得MPLAB X并为我解决问题! 对于那些对基本细节感兴趣的人:引脚数量为0,因为当使用PinSet.getPin(String)访问引脚时,引脚被延迟加载。 通常所有引脚都会因为外设加载而被加载,但在JRuby下,没有检测到外设。 这是因为无法找到periphal文件。 这是因为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-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
    

    我能够使用此实现获得预期结果。 这种植入的主要区别是将jar添加到classpath中。 如果您注释此行( $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

    链接地址: http://www.djcxy.com/p/70651.html

    上一篇: What causes a Java library to behave differently when called by JRuby?

    下一篇: jvectormap: Draw lines between markers?