2013-04-05 11 views
11

jamvmバージョン1.5.0のLinuxを実行しているMotorola FX9500 RFIDリーダーを使用しています(私はアプリケーションをデプロイすることしかできません - Java VMなどのオプションを変更することはできません)。私はバージョンを確認する場合:Motorola FX9500のJamVMの問題 - どうすればよいですか?

[[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の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上に置きますので、同じようにそれを実行します:あなたが見ることができるようにするもの...

[[email protected] ~]$ /usr/bin/jamvm TestApp 
-2 

イーク、 - それは別の結果を返します。

だから、なぜ、誰が間違っているのか、このような仕様のようなものは、この計算をどのように扱うかについてはっきりしていません(確かにそうではありません)?私はそれを別のコンパイラでコンパイルする必要がありますか?


なぜこれについて気にしますか?

私はこのような状況に来た理由は、まさにそのような計算がjava.lang.Long.toStringの内部で起こると私は長い間をログアウトしてjava.lang.ArrayIndexOutOfBoundsExceptionを取得しています、私の実際のアプリケーションのバグを持っているということです。私が記録したい値は、Longの終わりにある可能性が非常に高いからです。

私はLong.MIN_VALUEとLong.MAX_VALUEをチェックし、 "Err、私はあなたに番号を教えることはできませんが、本当に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マシン上でコンパイルして実行します。

それは私が問題のからくりに.classファイルをコピーし、それを実行Phew, that was a close one

を印刷します。

それは...

...それを待つ...

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

ああ親愛を印刷します。私はアップデート2は、任意の違いはありませんでした私が試したもうひとつ、

...私はお茶を必要だと思う、ビットwoozy感じclasses.zipをコピーしたとglibj.zipファイルをPCにFX9500のオフしてからのクロスが(つまり、コンパイル済みのファイルは罰金、右でなければなりません意味する必要があります?)そうのようにコンパイルします:

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

しかし、結果の.classファイル、上の実行時にリーダーは同じメッセージを出力します。

+1

+1よく紡績された糸(すなわち質問がうまく楽しく書かれている)については、私は思う。 Windows用のjamvmコンパイラはありませんか?定期的なSDKコンパイラがそれをしているかわからない... –

+0

ありがとう。私はjamvmコンパイラを見つけることができませんでした - 私はそれが単なる仮想マシンだと思います。 – kmp

+1

カスタムモジュラス演算を使用しようとしましたか? %bの代わりに - (a/b)* bを意味します。実装に若干の違いがあるかもしれません。追加と否定の操作は問題を引き起こすためにまっすぐに進むことです。 – Mikhail

答えて

4

私はJamVMを書きました。おそらくこのようなエラーは今まで気付いていただろうが、JamVMはもっとも簡単なテストスイートを渡すことはできないだろう(GNU ClasspathにはMauveと呼ばれ、OpenJDKにはjtregがある)。私は定期的にARM(FX9500はPXA270 ARMを使用)とx86-64を使用していますが、さまざまなプラットフォームがIcedTeaの一部としてテストされています。

私はここで何が起こったのかについての手掛かりはほとんどありません。私はそれがまれにしか使われず、ほとんどのプログラムが動作するので、Java longsに影響すると思います。 JamVMはJava longをC long longにマッピングするので、JamVMを構築するために使用されるコンパイラは、32ビットARMで長いlong handlingのために間違ったコードを生成していると思います。

JVMを置き換えることができない場合は残念ながら、あなたはできることはほとんどありません。あなたができる唯一のことは、JITをオフにしようとすることです(単純なコードをコピーするJIT、別名インラインスレッド)。これを行うには、コマンド行で-Xnoinliningを使用します。:

jamvm -Xnoinlining ...

+1

あなたの(kmp)コメントの1つは、JamVMがMotorolaによってFX9500に付属のソフトウェアの一部であることを意味します。これは本当ですか?そうであれば、JamVMが変更されていない、またはハッキングされていないという保証はありません。あなたはGPLの下でJamVMをリリースしているので、モトローラにソースを尋ねることができます。 – user2251099

+0

本当にありがとうございます - 私はこれについてとても驚いています - jamvmで非常に単純なもののバグは非常にありそうもないと思いました - それがどのように構築されたかのアイデアは可能性が高いようです - 私は自分でそれを置き換えることができればいいと思うが、それは完全にロックされているので、助けを頼まれたモトローラ – kmp

+0

ちょうどあなたを更新する - 渡す-Xnoinliningは何の違いもありません。 – kmp

4

問題は、異なるモジュラス実装である:

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

戻り:

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

このコードこの間、-2を返します。 JamVMがこのようにしている理由は私の理解の背後にある。 JLSから

15.17.3。剰余演算子%は

バイナリ数値昇格後整数であるオペランド用剰余演算は、(5.6.2)は、結果値を生成すること (/ B)* B +(%のB)と同じです。

これによると、JamVMは言語仕様を破ります。ひどい。

+0

さて、jamvmのソースコードが利用可能で、いつでも見ることができます。しかし、私はjamvmのような問題を抱えていたのを覚えていませんが、私はそれを自分自身で、x86ターゲット(モトローラの装置が何を実行しているのか分かりません)でのみコンパイルしました。 – Archie

+0

私はモジュラス演算子ではないと思う - 質問への私の更新を参照してください – kmp

+1

これは本当のWTFです! JVMにプリミティブ型に関する仕様の有線解釈がある場合、中規模のプロジェクトでもどのように使用するのか分かりません。 – Mikhail

2

私はコメントしているだろうが、何らかの理由で、それは評判が必要です。

このデバイスでは長時間の否定は機能しません。私はその正確な性質を理解していませんが、2つの単項マイナスを行うと、あなたが始めた場所に戻ります。 x = 10; -x == 4294967286; -x == 10。 4294967286はInteger.MAX_VALUE * 2(2147483647 * 2 = 4294967294)に非常に近いです。それはInteger.MAX_VALUE * 2-10にさらに近いです!

この1つの操作に分離されているように見え、さらに基本的な方法ではロングには影響しません。あなた自身のコードでの操作を避けるのは簡単ですし、bootclasspathをちょっと酷使すると、GNU Classpathコードの呼び出しを回避して* -1sに置き換えることができます。デバイスのGUIからアプリケーションを起動する必要がある場合は、-Xbootclasspath = ...スイッチをargsパラメータに含めてJamVMに渡すことができます。

バグが実際にすでに(最新のリリースより)後者JamVMコードに固定されている:デバイス上の固定バージョンで私たちを助けていませんが、* https://github.com/ansoncat/jamvm/commit/736c2cb76baf1fedddc1eda5825908f5a0511373 * https://github.com/ansoncat/jamvm/commit/ac83bdc886ac4f6e60d684de1b4d0a5e90f1c489

。 Rob Lougher氏は、この問題がJamVMの新しいバージョンをリリースする理由として言及していますが、これはいつかわかりませんが、Motorolaがファームウェアのアップデートに十分に納得できるかどうかは分かりません。

FX9500は実際には再パッケージ化されたSirit IN610です。つまり、両方のデバイスがこのバグを共有しています。 Siritはモトローラと近い将来に利用できるように、ファームウェアのアップグレードを提供しています。両当事者間の契約の詳細はわかりませんが、モトローラにもこの修正が含まれていることを願っています。

どちらの方法でも、私たちはFX9500上で動作する非常に大きなアプリケーションを持っています。長い否定操作は、不可解な障壁であるとは証明されていません。

幸運、ダン。

+0

ダンに感謝します - 特に、-Xbootclasspathに関するヒントです。実際、私たちが問題を抱えていた唯一の場所は、String.format( "%d"、x)を実行していた場所で、xは任意の負の数(-1があった)でした。私はちょうど整数をlongに変換していない独自のString.formatメソッドを書き、その代わりに使用しました(ログメッセージを書くときにしか使用していませんでした。私がこれまでと同じデバイスをもう一度使っていれば、私はPythonインタプリタを代わりに使うと思います。 – kmp

関連する問題