我正在尝试
我正在尝试在 J2ME 应用程序中使用 java.util.TreeMap
。我知道在 J2SE 上有 TreeMap
,但在 J2ME 上没有,因此我努力将 J2SE 6.0 的 TreeMap
移植到 J2ME 1.2,并将其包含在我的 Midlet Jar 中。这涉及移植集合框架的一半,但现在我已经(理论上)完成了这个过程,并想要测试它。
错误信息
但是当我在 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
在真实设备上,我收到了"应用程序中的错误"
,但由于我现在没有匹配的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
是以Java 1.2类文件格式的。我针对CDLC 1.0和MIDP 1.0,所以我的预校验器使用的是classpath ${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的扩展机制成功将这些引用更改为我的自定义类。Retrotranslator是一个我已经在构建过程中使用但其功能我并不完全了解的工具。
我的J2SE库现在可以在J2ME上运行,它有其他J2SE库的依赖关系。