javajava-memidptreemapcldc

J2ME does not find my implementation of java.util.TreeMap


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!


Solution

  • 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.