J2ME 找不到我的 java.util.TreeMap 实现
我正在尝试
在 J2ME 应用程序中使用 java.util.TreeMap 。我知道 TreeMap
存在于 J2SE 上,但不存在于 J2ME 上,因此我做了一些努力将 J2SE 6.0 TreeMap
移植到 J2ME 1.2 并将其包含在我的 Midlet Jar 中。这涉及到移植一半的集合框架,但现在我(理论上)已经完成了,并且想要测试它。
错误
但是当我在 SUN J2ME SDK 3.0 模拟器 (DefaultClclPhone2) 上启动我的应用程序时,我收到此异常:
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,因此我的预验证器使用类路径 ${wtk.home}/lib/cldc_1.0.jar, ${wtk.home}/lib/midp_1.0.jar< /code>
只是一个想法:J2ME 类加载器中是否有任何特殊检查可以阻止它从某个类加载 java.util.*
或 java.lang.*
类应用程序罐子?我从来没有听说过,但也许他们做了这样的事情作为安全功能?
结论和解决方案
正如 Joachim Sauer 指出的那样,如果我定义了类,类加载器将不会加载 java.*
中的类。所以我不得不将它们移动到另一个包,实际上是 com.companyname.j2meport.java.util
。虽然我自己的代码可以从那里导入这些类,但这对于引用 java.util.TreeMap 的闭源第三方库来说不是一个选项。
我终于设法使用 Retrotranslator 的扩展机制(我的一个工具)将这些引用更改为我自己的类。已经在我的构建过程中使用,但我并不完全了解其功能。
我的 J2SE 库依赖于其他 J2SE 库,现在可以在 J2ME 上运行!
What I'm trying
I'm trying to use java.util.TreeMap
in a J2ME application. I know that TreeMap
is present on J2SE but not on J2ME, so I've made some efforts to port the J2SE 6.0 TreeMap
to J2ME 1.2 and included it in my Midlet Jar. This involved porting half of the collections framework, but now I'm (theoretically) done with that and want to test it.
The error
But when I start my app on a SUN J2ME SDK 3.0 emulator (DefauldClclPhone2) I get this exception:
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
On a real device I get "Error in Application"
but can't see the actual Exception because I don't have the matching SDK right now.
What's so stange about that error
I'm puzzled by the fact that my application successfully underwent the preverification process. I always experienced that a missing class (and I had many of them some days ago) triggers an error in the preverifier. So I concluded that after successfull preverification there cannot be any NoClassDefFoundError
on the device.
Details
The directory structure inside my jar looks like this:
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)
I also made sure that TreeMap.class
is in the Java 1.2 class file format.
I'm targeting CDLC 1.0 and MIDP 1.0, so my preverifier is using the classpath ${wtk.home}/lib/cldc_1.0.jar, ${wtk.home}/lib/midp_1.0.jar
Just a thought: Is there any special check in the J2ME classloader that prevents it from loading a java.util.*
or java.lang.*
class from an application jar? I never heard of that, but maybe they did something like this as a security feature?
Conclusion and Solution
As Joachim Sauer pointed out, the classloader will not load classes in java.*
if I defined them. So I had to move them to another package, actually to com.companyname.j2meport.java.util
. While my own code could then import those classes from there, this is not an option for closed-source third-party-libs which refer to java.util.TreeMap.
I finally managed to change these references to my own classes using the extension mechanism of Retrotranslator, a tool I was already using in my build process but of whose capabilities I was not fully aware.
My J2SE library, which has dependencies on other J2SE libraries, now runs on J2ME!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
只有 bootstrap 引导加载程序可以从以
java.
开头的包中加载类。这意味着您必须将您的类移至另一个包中。
请参阅 ClassLoader.defineClass() 了解详细信息。
Only the bootstrap bootloader can load classes from packages that start with
java.
.This means that you will have to move your class into another package.
See the JavaDoc of ClassLoader.defineClass() for details.
在这两种情况下,您都是对的 - CLDC1.0 不包括 NoClassDefFoundError (请参阅 CLDC1 .0 规范),并且不可以创建自己的 java.* 类;请参阅上面答案中的链接。
You are right in both cases -- CLDC1.0 does not include NoClassDefFoundError (see the CLDC1.0 spec), and no you may not create your own java.* classes; see the link in the above answer.