我在想什么

我正在尝试在J2ME应用程序中使用java.util.TreeMap。我知道TreeMap在J2SE上存在,但在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

在实际设备上,我得到了"Error in Application",但是看不到实际的异常,因为我现在没有匹配的SDK。

这个错误到底是什么

我的应用程序成功进行了预验证过程,这使我感到困惑。我总是经历过缺少类(几天前有很多此类)会触发预 validator 中的错误。因此,我得出结论,在成功进行预验证之后,设备上将没有任何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,所以我的前置 validator 正在使用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的封闭源第三方库,这不是一个选择。

最终,我使用the extension mechanism of Retrotranslator将这些引用更改为自己的类,这是我在构建过程中已经使用过的工具,但我对其功能尚不完全了解。

我的J2SE库依赖于其他J2SE库,现在可以在J2ME上运行!

最佳答案

只有 bootstrap 引导加载程序才能从以java.开头的包中加载类。

这意味着您将不得不将您的类移到另一个包中。

有关详细信息,请参见ClassLoader.defineClass()的JavaDoc。

09-09 21:13
查看更多