After not having built any Android apps for a few weeks, I returned to an attempt at that. Things went fine, until I tried to run my app on a device. The app crashed immediately upon startup with the following error in logcat:

E/AndroidRuntime( 6844): FATAL EXCEPTION: main
E/AndroidRuntime( 6844): java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{org.apache.marcelk/org.apache.marcelk.junk}: java.lang.ClassNotFoundException: Didn't find class "org.apache.marcelk.junk" on path: /data/app/org.apache.marcelk-1.apk

Huh? That’s my activity class. I’m sure it’s there. So I look in my Android project directory and there in the classes dir is org/apache/marcelk/junk.class. So why is it complaining it can’t find it?

If I look just 3 lines higher in logcat, I see the first indication that something went wrong:

I/ActivityManager( 476): Start proc org.apache.marcelk for activity org.apache.marcelk/.junk: pid=6844 uid=10065 gids={50065, 3003, 1028}
W/dalvikvm( 6844): Unable to resolve superclass of Lorg/apache/marcelk/junk; (97)

My superclass is CordovaActivity, so that is present, correct? The cordova jar which contains CordovaActivity is in my libs directory in my project. But did it make it into classes.dex? That’s hard to tell, classes.dex is not a zip file like the apk that I can easily peek in to. Running the command “strings classes.dex | grep CordovaActivity” isn’t conclusive, would be nice if there was something that was. Aha! Look in the Android SDK’s build-tools/android-4.3 directory and there is a cool utility – run this:

dexdump classes.dex

Indeed, my junk class references CordovaActivity as a superclass, but CordovaActivity is not present in classes.dex. Why isn’t it there?

I did build the project with the Cordova CLI tooling, which [in this case, unfortunately] masks output from the commands it fires. So maybe there is something being masked which is important. The Cordova project basically has an Android project in my_project/platforms/android, so run “ant clean” and “ant debug” there. Hmm, now I’m seeing 140 warnings like this:

[dx] trouble processing:
bad class file magic (cafebabe) or version (0033.0000)

And the CordovaActivity is one of those classes that it warns about. Indeed, the first 4 bytes of a class file are 0xCAFEBABE, so it must not like the version number. Version “0033.0000” is the java major/minor version in hex. 0x33 = 51 decimal. So let’s check that: I unzip cordova.jar and run “javap -verbose org.apache.cordova.CordovaActivity”, and sure enough it reports major version 51 and minor version 0. The class file layout indicates:

Java 5 = 49
Java 6 = 50
Java 7 = 51

So CordovaActivity was compiled with Java 7. Does dex have problems with Java 7? According to this article, yes. Dex likes only Java 5 and Java 6. If dex sees a Java 7-compiled class, it will silently omit it. Aha! Problem indentified. Now to fix it.

Now that you mention it, I did recently change my JAVA_HOME on my workstation to point to a Java 7 JDK instead of a Java 6 one. So where in the docs on developer.android.com does it say that you can’t use Java 7? Nowhere, according to what I’ve seen. Pfffft!

On my Mac, I simply change JAVA_HOME in ~/.bash_profile to be:

export JAVA_HOME=`/usr/libexec/java_home -v 1.6`

since I have both Java 6 and 7 installed, then I do an “ant clean” in my project directory, go back to the Cordova source and do an “ant clean” and “ant jar”, copy the cordova jar to my project, then go back to my project to do an “ant debug”. It works!

I’ll capture this experience here, in hopes that it will help someone else in the future. For the record, this was using Android SDK Tools 22.2.1 and Platform Tools 18.0.1 and API 18.

Update: OK, in the System Requirements section it does say JDK 6, but I usually interpret that to be the minimum level, not the maximum level.

And, specifically the Oracle JDK must be used due to a dependency on the sun.security package. The IBM JDK or Apache Harmony can’t be used.

Update November 2014:

The ADT as of version 22.6 now supports Java 7. And Android 5 (Lollipop) requires Java 7.