Tag Archives: javac

jar, javac and Android

TL;DR – Each Android build has a required javac version, if there is a mismatch between this version and javac used to create a jar file bad things will happen.

Story Version – Integrating a jar into an Android application is pretty straight forward and well documented. (For the lazy this link shows you a couple of ways to do it.)

My setup though is a little different, I was trying to include the jar file using the Android build system (Marshmallow with Jack and Jill compiler turned on by default). Creating a jar in android build system is pretty easy to do (It can be created by including BUILD_STATIC_JAVA_LIBRARY in the Android.mk file and in the application refer to the new jar using LOCAL_STATIC_JAVA_LIBRARIES)

But what if you wanted to created the jar outside of the Android build system, pretty straight forward right – build all the class files and create a jar file using the cmd javac from cmd line (you can also build jar files in Eclipse and Android Studio). While trying to include the jar created this way, I was getting a very strange error – “Binary transformation of <jarfile> failed.”

A little digging around in the source code gave pointed me to this location, which points to the Jill tool, makes sense I am trying to include the jar and the Jill tool is responsible for converting the jar classes to the Android library format. The error though was still not very helpful at all, with an another round of googling I found this patch – “bad class file magic (cafebabe) or version (0034.0000)”. Now we are getting somewhere, the version mentioned 34 is in hexadecimal, which is 52 in decimal, looking at the Java class file description, it 52 means that it is for Java SE 1.8. Now this made sense since I used JDK 1.8 to compile the jar, so 1.8 is not supported?

So I tried to create the jar using my linux setup which had JDK 1.7 installed, and this jar compiled straight away!! So looks like Android full build has a dependency on the java compiler version?! For now it looks like it, since when I built the jar using the Android full build system the jar works fine and when I compiled it with JDK 1.7 it works as well. So I started looking (grepping rather) for any inkling of java compiler version mentioned in the make file somewhere in the build system.

Lo and behold what I found – The required javac version for Android build system is mentioned in <root>/build/core/main.mk with the variable name as “required_javac_version” and no points for guessing what this was pointing to,  1.7 🙂

Further exploring the javac options, I found that you can tell the compiler which version of the java you want to target and also what feature set are you targeting in the java source files, both of these can be passed to the compiler as options – eg -javac -source 1.7 -target 1.7 .\testJar.java

One thing that threw me off was that a jar that I had received from an another team was compiling fine, and this jar was build using the javac and Ant build system and not in Android build system. I spoke to this guy and he said he was using JDK 1.8 as well!! That didn’t make any sense, so I asked him to show me his makefile for the Ant build system and this is what I found – “<javac target=”1.7″ destdir=”${build.dir}/classes-ant”>” 🙂

We take the tools we use everyday for granted, if it works we look no further, this exercise has taught me a valuable lesson to learn the tools of the trade and that source code triumphs everything else. Don’t believe everything everyone says or don’t take your tools for granted.