私が試していること
java.util.TreeMap
J2MEアプリケーションで使用しようとしています。TreeMap
これはJ2SEには存在しますが、J2MEには存在しないことを知っているのでTreeMap
、J2SE6.0をJ2ME1.2に移植し、MidletJarに含めるように努力しました。これには、コレクションフレームワークの半分の移植が含まれていましたが、今では(理論的には)それで終わり、テストしたいと思っています。
エラー
しかし、SUN J2ME SDK 3.0エミュレーター(DefauldClclPhone2)でアプリを起動すると、次の例外が発生します。
java.lang.NoClassDefFoundError: java/util/TreeMap
java.lang.Class.invoke_verify(), bci=0
java.lang.Class.initialize(), bci=117
com.companyname.test.TestMidlet.<init>(), bci=19
java.lang.Class.newInstance(), bci=0
com.sun.midp.main.CldcMIDletLoader.newInstance(), bci=46
com.sun.midp.midlet.MIDletStateHandler.createMIDlet(), bci=66
com.sun.midp.midlet.MIDletStateHandler.createAndRegisterMIDlet(), bci=17
com.sun.midp.midlet.MIDletStateHandler.startSuite(), bci=27
com.sun.midp.main.AbstractMIDletSuiteLoader.startSuite(), bci=52
com.sun.midp.main.CldcMIDletSuiteLoader.startSuite(), bci=8
com.sun.midp.main.AbstractMIDletSuiteLoader.runMIDletSuite(), bci=161
com.sun.midp.main.AppIsolateMIDletSuiteLoader.main(), bci=26
実際のデバイスで"Error in Application"
は、一致するSDKが現在ないため、実際の例外は表示されません。
そのエラーについて何がそんなにスタンジなのか
私のアプリケーションが事前検証プロセスを正常に実行したという事実に戸惑っています。私はいつも、クラスが見つからない(そして数日前に多くのクラスがあった)と、事前検証ツールでエラーが発生することを経験しました。NoClassDefFoundError
したがって、事前検証が成功した後は、デバイス上に何も存在しない可能性があると結論付けました。
詳細
私のjar内のディレクトリ構造は次のようになります。
test.jar
com
companyname
(my application classes, including the Midlet class)
java
lang
Comarable.class
Iterable.class
(some others which are missing on J2ME)
util
TreeMap.class
TreeSet.class
(many others which are missing on J2ME)
TreeMap.class
また、それがJava1.2クラスのファイル形式であることを確認しました。
CDLC1.0とMIDP1.0をターゲットにしているので、事前検証ツールはクラスパスを使用しています${wtk.home}/lib/cldc_1.0.jar, ${wtk.home}/lib/midp_1.0.jar
考えてみてください。J2MEクラスローダーに、アプリケーションjarからjava.util.*
またはクラスをロードできないようにする特別なチェックはありますか?java.lang.*
私はそれを聞いたことがありませんが、おそらく彼らはセキュリティ機能としてこのようなことをしましたか?
結論と解決策
Joachim Sauerが指摘したように、クラスローダーは、クラスjava.*
を定義した場合、クラスをロードしません。そのため、それらを別のパッケージ、実際にはに移動する必要がありましたcom.companyname.j2meport.java.util
。私自身のコードはそこからそれらのクラスをインポートできますが、これはjava.util.TreeMapを参照するクローズドソースのサードパーティライブラリのオプションではありません。
私はついに、Retrotranslatorの拡張メカニズムを使用して、これらの参照を自分のクラスに変更することができました。これは、ビルドプロセスですでに使用していたツールですが、その機能については完全には認識していませんでした。
他のJ2SEライブラリに依存している私のJ2SEライブラリは、J2MEで実行されるようになりました。