我正在使用摩托罗拉FX9500 RFID阅读器,它运行带有jamvm版本1.5.0的Linux (我只能部署应用程序 - 我无法更改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
Run Code Online (Sandbox Code Playgroud)
我需要编写一个应用程序,所以我抓住了Oracle Java SDK 1.5.0并将其安装到我的Windows 7 PC上,所以它有这个版本:
C:\>javac -version
javac 1.5.0
Run Code Online (Sandbox Code Playgroud)
考虑到我使用该编译器编译的应用程序可以在上述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);
}
}
Run Code Online (Sandbox Code Playgroud)
用前面提到的javac编译器编译它并在PC上运行它,如下所示:
C:\>javac TestApp.java
C:\>java TestApp
8
Run Code Online (Sandbox Code Playgroud)
一切都很好.生活是美好的,所以我拿起那个.class文件放在FX9500上并运行它:
[cliuser@FX9500D96335 ~]$ /usr/bin/jamvm TestApp
-2
Run Code Online (Sandbox Code Playgroud)
Eek,正如你所看到的那样 - 它会返回不同的结果.
那么,为什么和谁错了或者这个规范之类的东西不清楚如何处理这个计算(肯定不是)?难道我需要用不同的编译器编译它吗?
我为什么关心这个?
我遇到这种情况的原因是,完全像在内部发生的计算java.lang.Long.toString,我在我的实际应用程序中有一个错误,我正在注销一个很长的并得到一个java.lang.ArrayIndexOutOfBoundsException.因为我想要记录的值很可能在a的末尾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");
}
}
Run Code Online (Sandbox Code Playgroud)
我再次在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
Run Code Online (Sandbox Code Playgroud)
但是,在读取器上运行时生成的.class文件会打印相同的消息.
小智 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 ...