Motorola FX9500上的JamVM问题 - 我该怎么办?

时间:2013-04-05 08:07:29

标签: java jamvm

我正在使用Motorola FX9500 RFID阅读器,它运行Linux jamvm版本1.5.0(我只能部署应用程序 - 我不能更改Java VM或其他任何东西,所以我的选项是有限的) - 这是我在检查版本时看到的内容:

[cliuser@FX9500D96335 ~]$ /usr/bin/jamvm -version
java version "1.5.0"
JamVM version 1.5.4
Copyright (C) 2003-2010 Robert Lougher <rob@jamvm.org.uk>

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2,
or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

Build information:

Execution Engine: inline-threaded interpreter with stack-caching
Compiled with: gcc 4.2.2

Boot Library Path: /usr/lib/classpath
Boot Class Path: /usr/local/jamvm/share/jamvm/classes.zip:/usr/share/classpath/glibj.zip

我需要编写一个应用程序,所以我抓住了Oracle Java SDK 1.5.0并将其安装到我的Windows 7 PC上,所以它有这个版本:

C:\>javac -version
javac 1.5.0

在考虑使用该编译器编译的应用程序在前面提到的JamVM上是否正常工作时,我是否过于理想化?无论如何,在无知中按下我写这个小应用程序:

public final class TestApp {
    public static void main(final String[] args) {
        long p = Long.MIN_VALUE;
        int o = (int)(-(p + 10) % 10);
        System.out.println(o);
    }
}

使用前面提到的javac编译器进行编译,并在PC上运行它,如下所示:

C:\>javac TestApp.java

C:\>java TestApp
8

那里很好。生活是美好的,所以我把.class文件放在FX9500上,然后像这样运行:

[cliuser@FX9500D96335 ~]$ /usr/bin/jamvm TestApp
-2
Eek,正如你所看到的那样 - 它会返回不同的结果。

那么,为什么以及谁错了,或者像规范这样的东西不清楚如何处理这个计算(肯定不是)?难道我需要用不同的编译器编译它吗?


我为什么关心这个?

我遇到这种情况的原因是,java.lang.Long.toString内部的计算完全一样,我的实际应用程序中有一个错误,我正在注销一个很长的java.lang.ArrayIndexOutOfBoundsException。因为我想要记录的值很可能位于Long的末尾。

我想我可以通过检查Long.MIN_VALUE和Long.MAX_VALUE来解决它并记录“错误,我不能告诉你这个数字,但它真的是Long.XXX,相信我,我会欺骗你吗? ”。但是当我发现这个时,我觉得我的应用程序现在建立在一个沙质基础上,它需要非常强大。我正在认真地考虑说JamVM不能胜任工作并用Python编写应用程序(因为读者也有Python运行时)。

我有点希望有人告诉我,我是一个笨蛋,我应该在我的Windows PC上编译它......然后它会工作,所以请告诉我(如果是真的,当然)!


更新

Noofiz让我思考(谢谢),我敲了这个额外的测试应用程序:

public final class TestApp2 {
    public static void main(final String[] args) {

        long p = Long.MIN_VALUE + 10;

        if (p != -9223372036854775798L) {
            System.out.println("O....M.....G");
            return;
        }

        p = -p;

        if (p != 9223372036854775798L) {
            System.out.println("W....T.....F");
            return;            
        }

        int o = (int)(p % 10);

        if (o != 8) {
            System.out.println("EEEEEK");
            return;
        }

        System.out.println("Phew, that was a close one");
    }
}

我再次在Windows机器上编译并运行它。

打印Phew, that was a close one

我将.class文件复制到有问题的装置并运行它。

打印......

......等等......

W....T.....F

亲爱的,亲爱的。我觉得有点傻,我想我需要一杯茶......

更新2

我试过的另一件事,没有任何区别,就是将来自FX9500的classes.zip和glibj.zip文件复制到PC,然后像这样进行交叉编译(这必须意味着编译后的文件)应该没问题?):

javac -source 1.4 -target 1.4 -bootclasspath classes.zip;glibj.zip -extdirs "" TestApp2.java

但是,在阅读器上运行时生成的.class文件会打印相同的消息。

3 个答案:

答案 0 :(得分:5)

我写了JamVM。正如您可能猜到的那样,此类错误现在已经被注意到了,而JamVM甚至无法通过最简单的测试套件(GNU Classpath有自己的Mauve,而OpenJDK有jtreg)。我经常在ARM(FX9500使用PXA270 ARM)和x86-64上运行,但是各种平台都作为IcedTea的一部分进行了测试。

所以我对这里发生的事情并不了解。我猜它只会影响Java的长度,因为这些很少使用,所以大多数程序都可以工作。 JamVM将Java longs映射到C long longs,所以我的猜测是用于构建JamVM的编译器会在32位ARM上长时间处理错误的代码。

不幸的是,如果你不能替换JVM,你可以做的事情不多(除了避免长时间)。你唯一能做的就是尝试关闭JIT(一个简单的代码复制JIT,也就是内联线程)。为此,请在命令行中使用-Xnoinlining,例如:

jamvm -Xnoinlining ...

答案 1 :(得分:4)

问题在于不同的模块实现:

public static long mod(long a, long b){
    long result = a % b;
    if (result < 0)
    {
        result += b;
    }
    return result;
}

此代码返回 -2 ,而这个:

public static long mod2(long a, long b){
    long result = a % b;
    if (result > 0 && a < 0)
    {
        result -= b;
    }
    return result;
}

返回 8 。 JamVM这样做的原因是我理解的原因。

来自JLS:

  

<强> 15.17.3。剩余运营商%

     

二进制后整数操作数的余数运算   数字促销(第5.5.2节)产生一个结果值   (a / b)* b +(a%b)等于a。

根据这个JamVM中断语言规范。非常糟糕。

答案 2 :(得分:2)

我会评论,但出于某种原因,这需要声誉。

长时间否定不适用于此设备。我不明白它的确切性质,但是如果你做了两个一元的弊端,你会回到你开始的地方,例如: X = 10; -x == 4294967286; -x == 10。 4294967286非常接近Integer.MAX_VALUE * 2(2147483647 * 2 = 4294967294)。它甚至更接近Integer.MAX_VALUE * 2-10!

这似乎与这一个操作是隔离的,并且不会以更进一步的方式影响多头。在你自己的代码中避免操作是很简单的,并且使用一些灵巧的滥用bootclasspath可以避免在GNU Classpath代码中调用,用* -1s替换它们。如果需要从设备GUI启动应用程序,可以将-Xbootclasspath = ...切换到args参数中,以便将其传递给JamVM)。

该bug实际上已在后者(比最新版本)JamVM代码中修复: * https://github.com/ansoncat/jamvm/commit/736c2cb76baf1fedddc1eda5825908f5a0511373 * https://github.com/ansoncat/jamvm/commit/ac83bdc886ac4f6e60d684de1b4d0a5e90f1c489

虽然对设备上的固定版本没有帮助。 Rob Lougher已经提到这个问题是发布新版JamVM的一个原因,虽然我不知道这是什么时候,或者摩托罗拉是否足以说服他们更新固件。

FX9500实际上是一个重新包装的Sirit IN610,这意味着两个设备共享此错误。 Sirit对摩托罗拉更友好,并提供固件升级,将在不久的将来推出。我希望摩托罗拉也能提供修复,但我不知道双方安排的细节。

无论哪种方式,我们都在FX9500上运行了一个非常大的应用程序,并且长时间的否定操作并未被证明是不可逾越的障碍。

祝你好运,Dan。