J2ME无法找到我实现的java.util.TreeMap。

4

我正在尝试

我正在尝试在 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库的依赖关系。

2个回答

8

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

这意味着您需要将您的类移动到另一个包中。

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


这很清楚地表明,按照我打算的方式是不可能实现的。我猜在J2SE机器上,我实际上会得到一个SecurityException,这将比NoClassDefFoundError更明显。而且你说得对,我必须把我的类移到别的地方。对我来说这是个坏消息(因为这会带来很多新问题),但无论如何还是非常感谢。 - Lena Schimmel
1
顺便提一下,http://www.developer.com/java/other/print.php/10936_2248831_2 表示javax.*也是同样的情况。 - Lena Schimmel
@Brian:我也记得javax.*的同样事情,但由于我链接的文档没有提到它,所以没有提及。我想知道这个事实是否应该被视为文档错误。 - Joachim Sauer

3

在这两种情况下,您都是正确的——CLDC1.0不包括NoClassDefFoundError(请参见CLDC1.0规范),而且您不能创建自己的java.*类;请参见上面回答中的链接。


是的,我也看到了关于CLDC 1.0没有NoClassDefFoundError的事实。这实际上被认为是一个bug,并在CLDC 1.1中修复,详见http://bugs.sun.com/view_bug.do?bug_id=4313429不管怎样,似乎这并不是真正的问题,在CLDC 1.1上出现的错误看起来和CLDC 1.0上的错误完全一样。也许我的1.0仿真器有这个类,尽管它不应该有。 - Lena Schimmel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接