简体   繁体   English

什么原因导致Java库在JRuby调用时表现不同?

[英]What causes a Java library to behave differently when called by JRuby?

I am new to the Java world, but am familiar with Ruby. 我是Java世界的新手,但我熟悉Ruby。 I am trying to write a program that interacts with some third-party jar files. 我正在尝试编写一个与某些第三方jar文件交互的程序。

While the libraries seem to behave fine if called from Java, they behave incorrectly when I call them in JRuby. 虽然从Java调用库似乎表现得很好,但是当我在JRuby中调用它们时它们的行为不正确。 This is a problem because I would really like to use JRuby. 这是一个问题因为我真的想使用JRuby。 For example, the two programs below try to do exactly the same thing but they produce different output: 例如,下面的两个程序尝试完全相同的东西,但它们产生不同的输出:

This Java program behaves correctly. 这个Java程序行为正常。

I developed the Java program below in Netbeans and ran it by pressing F6 (Run Main Project). 我在Netbeans中开发了下面的Java程序,然后按F6(运行主项目)运行它。 The Libraries folder for the project is set to "C:\\Program Files (x86)\\Microchip\\MPLABX\\mplab_ide\\lib\\nblibraries.properties". 项目的Libraries文件夹设置为“C:\\ Program Files(x86)\\ Microchip \\ MPLABX \\ mplab_ide \\ lib \\ nblibraries.properties”。 When I run it, it prints "pins: 17". 当我运行它时,它会打印“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"
    }

}

This JRuby program behaves incorrectly. 这个JRuby程序行为不正确。

I ran the JRuby program below by just typing jruby bug_reproduce.rb and it printed "pins: 0". 我只需输入jruby bug_reproduce.rb运行下面的JRuby程序,然后打印“pins:0”。 I would expect it to print "pins: 17" like the Java program. 我希望它像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

More details 更多细节

There are about 80 third-party jar files. 大约有80个第三方jar文件。 They are provided by Microchip as part of MPLAB X and implement a simulator for their microcontrollers. 它们由Microchip作为MPLAB X的一部分提供,并为其微控制器实现仿真器。 The jar files come with MPLAB X and I also downloaded the MPLAB X SDK to get help with using them. jar文件随MPLAB X一起提供,我还下载了MPLAB X SDK以获得使用它们的帮助。 I am using lots of undocumented features of the libraries, but I don't see any alternative. 我使用了大量未记录的库的功能,但我没有看到任何替代方案。

I am using Windows 7 64-bit SP1. 我使用的是Windows 7 64位SP1。 I have the following Java-related things installed and listed under "Programs and Features": 我在“程序和功能”下安装并列出了以下与Java相关的内容:

  • Java 7 Update 17 Java 7 Update 17
  • Java 7 Update 17 (64-bit) Java 7 Update 17(64位)
  • Java SE Development Kit 7 Update 17 (64-bit) Java SE开发工具包7更新17(64位)
  • Java(TM) 6 Update 22 (64-bit) Java(TM)6 Update 22(64位)
  • Java(TM) 6 Update 29 Java(TM)6 Update 29
  • Java(TM) SE Development Kit 6 Update 22 (64-bit) Java(TM)SE开发套件6更新22(64位)
  • JRuby 1.7.3 JRuby 1.7.3
  • IntelliJ IDEA Community Edition 12.0.4 IntelliJ IDEA社区版12.0.4
  • Netbeans IDE 7.3 Netbeans IDE 7.3
  • MPLAB X IDE v1.70 MPLAB X IDE v1.70

I used System.getProperty("java.version") to verify that both of my programs are running under Java 1.6.0_22. 我使用System.getProperty("java.version")来验证我的两个程序都在Java 1.6.0_22下运行。 That is good, because I followed the instructions in the MPLAB X SDK that say "For best results, use the exact same JDK that built the IDE/MDBCore your code will be talking to. For MPLAB X v1.70, this is JDK 6u22 from Oracle." 这很好,因为我按照MPLAB X SDK中的说明说“为了获得最佳结果,请使用构建IDE / MDBCore的完全相同的JDK,您的代码将与之交谈。对于MPLAB X v1.70,这是JDK 6u22来自甲骨文。“ I only installed JDK 7u17 after I encountered this problem, and it didn't make a difference. 我遇到这个问题后才安装了JDK 7u17,并没有什么区别。

I was able to find a workaround to the specific problem identified in the examples, but then I continued my development and ran into another problem where the libraries behaved differently. 我能够找到示例中确定的特定问题的解决方法,但后来我继续我的开发并遇到另一个问题,其中库的行为不同。 This makes me think that I am doing something fundamentally wrong in the way I use JRuby. 这让我觉得我在使用JRuby的方式上做了一些根本性的错误。

Thinking that a differing class path might cause this problem, I tried getting the java program to print out its class path and then edited my JRuby program to require precisely the files in that list, but it made no difference. 考虑到不同的类路径可能会导致此问题,我尝试让java程序打印出它的类路径,然后编辑我的JRuby程序以准确要求该列表中的文件,但它没有任何区别。

Questions 问题

  • Do you know of anything that might cause code in JAR files to behave differently when called from JRuby instead of Java? 你知道任何可能导致JAR文件中的代码在从JRuby而不是Java调用时表现不同的行为吗?
  • What version of the JDK does JRuby 1.7.3 use, or does that question even make sense? JRuby 1.7.3使用什么版本的JDK,或者这个问题是否有意义?

Update: SOLVED 更新:已解决

Thanks to D3mon-1stVFW for actually getting MPLAB X and solving my problem for me! 感谢D3mon-1stVFW实际获得MPLAB X并为我解决了我的问题! For those who are interested in the nitty gritty details: The number of pins was 0 because the pins are lazy loaded when they are accessed with PinSet.getPin(String). 对于那些对细节有兴趣的人:引脚数为0,因为当使用PinSet.getPin(String)访问它们时,引脚是延迟加载的。 Normally all pins would have been loaded because the peripherals load them, but under JRuby no peripherals were detected. 通常所有引脚都已加载,因为外设加载它们,但在JRuby下没有检测到外设。 This is because the periphal document could not be found. 这是因为无法找到周围文件。 This is because PerDocumentLocator.findDocs() returned an empty list. 这是因为PerDocumentLocator.findDocs()返回了一个空列表。 PerDocumentLocator failed because com.microchip.mplab.open.util.pathretrieval.PathRetrieval.getPath(com.microchip.mplab.libs.MPLABDocumentLocator.MPLABDocumentLocator.class)) was returning the wrong thing. PerDocumentLocator失败,因为com.microchip.mplab.open.util.pathretrieval.PathRetrieval.getPath(com.microchip.mplab.libs.MPLABDocumentLocator.MPLABDocumentLocator.class))返回了错误的内容。

Consider the following code, which is similar to what is happening inside PathRetrieval.getPath (except there it was written in Java): 请考虑以下代码,它类似于PathRetrieval.getPath中发生的代码(除了它是用Java编写的):

com.microchip.mplab.libs.MPLABDocumentLocator.MPLABDocumentLocator.java_class.resource("MPLABDocumentLocator.class").getFile()

If I follow D3mon-1stVFW's tip and add JAR files to the $CLASSPATH, then that code returns: 如果我按照D3mon-1stVFW的提示并将JAR文件添加到$ CLASSPATH,那么该代码将返回:

file: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 file: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

However, if I don't add things to the class path, then that code strangely returns: 但是,如果我不向类路径添加内容,那么该代码奇怪地返回:

file:C:%5CProgram%20Files%20(x86)%5CMicrochip%5CMPLABX%5Cmplab_ide%5Cmplablibs% 5Cmodules%5Ccom-microchip-mplab-libs-MPLABDocumentLocator.jar!/com/microchip/mpl ab/libs/MPLABDocumentLocator/MPLABDocumentLocator.class" file:C:%5CProgram%20Files%20(x86)%5CMicrochip%5CMPLABX%5Cmplab_ide%5Cmplablibs%5Cmodules%5Ccom-microchip-mplab-libs-MPLABDocumentLocator.jar!/ com / microchip / mpl ab / libs / MPLABDocumentLocator / MPLABDocumentLocator。类”

The %5C is actually the code for a backslash. %5C实际上是反斜杠的代码。 The Microchip code in PathRetrieval.getPath does a lot of string manipulation and does not properly handle the case where slashes are represented by %5C. PathRetrieval.getPath中的Microchip代码执行了大量字符串操作,并且无法正确处理由%5C表示斜杠的情况。 If anyone has any further insight about why the %5Cs are appearing, I would be interested to know, but my problem is solved. 如果有人对%5Cs出现的原因有任何进一步的了解,我很想知道,但我的问题已经解决了。

Conclusion: Sometimes Java's getResource() returns a URL with %5C instead of slashes in it and this is affected by what is on the CLASSPATH. 结论:有时Java的getResource()返回一个带有%5C而不是斜杠的URL,这受到CLASSPATH上的内容的影响。 If you want to be safe, add the jar file to $CLASSPATH before requiring it, like this: 如果您想要安全,请在需要之前将jar文件添加到$ CLASSPATH,如下所示:

require 'java'
$CLASSPATH << jar_filename
require jar_filename

I was able to get the expected results using this implementation. 我能够使用此实现获得预期的结果。 The main difference in this implantation is adding the jars to the classpath. 这种植入的主要区别在于将罐子添加到类路径中。 If you comment this line ( $CLASSPATH << jar_file ) you will get 0 pins. 如果你注释这一行( $CLASSPATH << jar_file )你会得到0个引脚。 (Explanation in the bottom of the question) (问题底部的解释)

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}" 

outputs 输出

content/mplab/mplab.deviceSupport 内容/ MPLAB / mplab.deviceSupport

content/mplab/MPHeader.xml 内容/ MPLAB / MPHeader.xml

content/mplab/PluginBoardSupport.xml 内容/ MPLAB / PluginBoardSupport.xml

pins: 17 别针:17

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Java中的字符串行为不同 - strings in java behave differently Java日历的行为有所不同 - Java Calendar behave differently 为什么Google数据存储区控制台的行为与数据存储区的GAE Java库不同? - Why does the Google Datastore console behave differently to the GAE Java library for Datastore? 是什么导致Java对ArrayLists和Integers的这两种对象类型进行不同的处理? - What causes java to treat this two object types of ArrayLists and Integers differently? 什么原因导致调用View的OnDraw方法以及何时调用 - What causes OnDraw method of View to be called and when 为什么 java 参数在 Windows 和 Linux 中表现不同? - Why java arguments behave differently in Windows and Linux? 为什么用Java创建的两个子流程表现不同? - Why two subprocesses created by Java behave differently? 将Spring Security添加为依赖项会导致应用行为不同 - Adding Spring Security as a dependency causes the app behave differently 当我从.jar运行时,为什么Java Sound的行为会有所不同? - Why does Java Sound behave differently when I run from a .jar? Java中的数组声明和初始化。当其下标索引的位置在其声明中更改时,数组的行为会有所不同 - Array declaration and initialization in Java. Arrays behave differently, when the position of their subscript indices is changed in their declaration
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM