views:

454

answers:

2

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!

+6  A: 

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.

Joachim Sauer
This makes pretty clear that it's just not possible the way I intended to do it. I guess on a J2SE machine I would actually get a SecurityException which would make this much more obvious that the NoClassDefFoundError. And you're right, I'll have to move my classes somewhere else. Bad news for me (because this opens a lot of new problems), but huge thanks anyway.
Brian Schimmel
By the way http://www.developer.com/java/other/print.php/10936_2248831_2 states that the same goes for javax.*
Brian Schimmel
@Brian: i thought I'd rememberd the same thing about javax.* as well, but didn't mention it since the documentation I linked to didn't mention it. I wonder if that fact should be considered a documentation bug.
Joachim Sauer
+2  A: 

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.

funkybro
Yes, I also read about the fact that CLDC 1.0 does not have NoClassDefFoundError. This was actually accepted as a bug and fixed in CLDC 1.1, see http://bugs.sun.com/view_bug.do?bug_id=4313429Anyway, it seemed as if there was no real problem with that, and the error on CLDC 1.1 lookes excactly the same as the one on CLDC 1.0. Maybe my 1.0 emulator has this class though it should not have it.
Brian Schimmel