JamVM для Motorola FX9500 Проблемы - что мне делать?
Я использую Motorola FX9500 RFID-считыватель, который запускает Linux с jamvm версии 1.5.0 (я могу только развернуть приложения к нему - я не могу изменить виртуальную машину Java или что-то еще, так что мои параметры ограничены) - вот что я вижу, когда проверяю версию:
[[email protected] ~]$ /usr/bin/jamvm -version
java version "1.5.0"
JamVM version 1.5.4
Copyright (C) 2003-2010 Robert Lougher <[email protected]>
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, поэтому у него есть эта версия:
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 и запустите его на ПК следующим образом:
C:\>javac TestApp.java
C:\>java TestApp
8
Все отлично. Жизнь хорошая, поэтому я беру этот файл .class
и помещаю его на FX9500 и запускаю его так:
[[email protected] ~]$ /usr/bin/jamvm TestApp
-2
Eek, что... как вы можете видеть - он возвращает другой результат.
Итак, почему и кто не прав или это что-то вроде спецификации, неясно, как справляться с этим расчетом (конечно же, нет)? Может быть, мне нужно скомпилировать его с помощью другого компилятора?
Почему я об этом забочусь?
Причина, по которой я пришел к этой ситуации, заключается в том, что расчет точно так же происходит внутри java.lang.Long.toString
, и у меня есть ошибка в моем реальном приложении, где я выхожу из long и получаю a java.lang.ArrayIndexOutOfBoundsException
. Поскольку значение, которое я хочу регистрировать, вполне может быть на концах Long
.
Я думаю, что могу обойти это, проверив Long.MIN_VALUE и Long.MAX_VALUE и запустив в журнал "Err, я не могу сказать вам номер, но на самом деле это Long.XXX, поверьте, я вам солгал?". Но когда я нахожу это, я чувствую, что мое приложение теперь построено на песчаном фундаменте, и оно должно быть действительно надежным. Я серьезно подумываю просто сказать, что JamVM не справляется с заданием и записывает приложение в Python (поскольку у читателя также есть время выполнения Python).
Я как бы надеюсь, что кто-то скажет мне, что я сумасшедший, и я должен был скомпилировать его на моем ПК с Windows, например... и тогда это сработает, поэтому, пожалуйста, скажите мне, что (если это правда, конечно)!
Обновление
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
Еще одна вещь, которую я пробовал, которая не имела никакого значения, заключалась в том, чтобы скопировать файлы classes.zip и glibj.zip с FX9500 на ПК, а затем сделать кросс-компиляцию так (это должен означать скомпилированный файл должно быть в порядке?):
javac -source 1.4 -target 1.4 -bootclasspath classes.zip;glibj.zip -extdirs "" TestApp2.java
Но полученный файл .class, когда он запускается на считывателе, печатает одно и то же сообщение.
Ответы
Ответ 1
Я написал JamVM. Как вы, вероятно, догадались бы, такие ошибки были бы замечены к настоящему времени, и JamVM не пропустил бы с ними даже самых простых наборов тестов (у GNU Classpath есть свой собственный Mauve, а OpenJDK - jtreg). Я регулярно запускаю ARM (FX9500 использует PXA270 ARM) и x86-64, но различные платформы проходят тестирование как часть IcedTea.
Поэтому я не очень понимаю, что здесь произошло. Я предполагаю, что это влияет только на Java longs, поскольку они используются нечасто, и поэтому большинство программ работают. JamVM отображает Java longs на длинные длинные C, поэтому я предполагаю, что компилятор, используемый для сборки JamVM, создает неверный код для длительной обработки 32-разрядной ARM.
К сожалению, вы не можете много сделать (кроме избегания длин), если вы не можете заменить JVM. Единственное, что вы можете сделать, это попытаться отключить JIT (простое копирование кода JIT, а также встроенная потоковая передача). Для этого используйте -Xnoinlining в командной строке, например:
jamvm -Xnoinlining...
Ответ 2
Проблема заключается в различных реализациях модуля:
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.6.2) дает такое значение результата, что (a/b) * b + (a% b) равна a.
В соответствии с этим JamVM прерывает спецификацию языка. Очень плохо.
Ответ 3
Я бы прокомментировал, но по какой-то причине это требует репутации.
Длительное отрицание на этом устройстве не работает. Я не понимаю его точный характер, но если вы делаете два унарных минуса, вы возвращаетесь туда, где вы начали, например. х = 10; -x == 4294967286; -x == 10. 4294967286 очень близко к Integer.MAX_VALUE * 2 (2147483647 * 2 = 4294967294). Это еще ближе к Integer.MAX_VALUE * 2-10!
Кажется, что он изолирован от этой одной операции и не влияет на долготы более фундаментальным образом. Это просто, чтобы избежать операции в вашем собственном коде, и с помощью какого-либо некорректного использования bootclasspath можно избежать вызовов в коде класса GNU Classpath, заменив их на * -1s. Если вам нужно запустить приложение из графического интерфейса устройства, вы можете включить параметр -Xbootclasspath =... в параметр args для его передачи в JamVM).
Ошибка на самом деле уже исправлена в последнем (чем последняя версия) JamVM-код:
* https://github.com/ansoncat/jamvm/commit/736c2cb76baf1fedddc1eda5825908f5a0511373
* https://github.com/ansoncat/jamvm/commit/ac83bdc886ac4f6e60d684de1b4d0a5e90f1c489
но не помогает нам с фиксированной версией на устройстве. Роб Лоугер упомянул об этой проблеме как о причине выпуска новой версии JamVM, хотя я не знаю, когда это будет, или же Motorola будет достаточно убеждена в обновлении своей прошивки.
FX9500 на самом деле является переупакованным Sirit IN610, что означает, что оба устройства используют эту ошибку. Sirit более дружелюбны, чем Motorola, и предлагают обновление прошивки, которые будут доступны в ближайшем будущем. Я надеюсь, что Motorola также включит исправление, хотя я не знаю деталей договоренности между двумя сторонами.
В любом случае у нас очень большое приложение, работающее на FX9500, и операция с длинным отрицанием не оказалась непроходимым барьером.
Удачи, Дэн.