jjzjj

java - 是什么导致 Java 库在被 JRuby 调用时表现不同?

coder 2024-03-20 原文

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

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

此 Java 程序运行正常。

我在 Netbeans 中开发了下面的 Java 程序,然后按 F6(运行主项目)运行它。项目的库文件夹设置为“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 的一部分提供并为其微 Controller 实现模拟器。 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,则该代码返回:

    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:%5CProgram%20Files%20(x86)%5CMicrochip%5CMPLABX%5Cmplab_ide%5Cmplablibs% 5Cmodules%5Ccom-microchip-mplab-libs-MPLABDocumentLocator.jar!/com/microchip/mpl ab/libs/MPLABDocumentLocator/MPLABDocumentLocator.class"



    %5C 实际上是反斜杠的代码。 PathRetrieval.getPath 中的 Microchip 代码做了很多字符串操作,并没有正确处理斜杠由 %5C 表示的情况。如果有人对 %5C 出现的原因有任何进一步的了解,我很想知道,但我的问题已解决。

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

    最佳答案

    我能够使用此实现获得预期的结果。此植入的主要区别在于将 jar 添加到类路径中。如果您评论此行( $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}" 
    
    产出

    content/mplab/mplab.deviceSupport

    content/mplab/MPHeader.xml

    content/mplab/PluginBoardSupport.xml

    pins: 17

    关于java - 是什么导致 Java 库在被 JRuby 调用时表现不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15794170/

    有关java - 是什么导致 Java 库在被 JRuby 调用时表现不同?的更多相关文章

    1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

      类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

    2. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

      我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

    3. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

      我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

    4. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

      我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

    5. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

      为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

    6. ruby - 在 jRuby 中使用 'fork' 生成进程的替代方案? - 2

      在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',

    7. ruby - ruby 中的 TOPLEVEL_BINDING 是什么? - 2

      它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput

    8. ruby - Infinity 和 NaN 的类型是什么? - 2

      我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串

    9. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

      如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

    10. ruby - 为什么 SecureRandom.uuid 创建一个唯一的字符串? - 2

      关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?

    随机推荐