Manufacturers: Keep VM Namespaces Clean, M'kay?
When an Android application starts up in a new process, one of the first things that happens is that a bunch of classes become available to the application. Courtesy of some Dalvik VM magic, those classes are memory-mapped into our new process, so all running applications can share the same read-only copy of those class definitions.
In stock Android, these classes include your expected Android framework
android.*), third-party packages that are exposed in
the SDK (e.g.,
org.apache.*), and some third-party packages that are used
by the Android framework but, for whatever reason, are not exposed in the
The most notorious of this latter group also happens to be my all-time-favorite
open source project name: the Legion of the Bouncy Castle (BC).
BC provides the
javax.crypto implementation used by Android. However,
there are other classes and methods in BC outside the
interfaces. These are not part of the Android SDK. In fact, as I understand
it, Android does not have a complete implementation of BC, though I may
be wrong about that.
If a developer attempts to include the BC JAR in her project, it may not
work properly. The reason is that, unlike desktop or server Java, developers
have no control over the classpath on Android. The net is that the firmware
always wins. You try to use the BC classes from the JAR, and it even compiles,
but at runtime it crashes with a
VerifyError or other problems, because
you are actually using the built-in BC implementation at runtime, not the one
from the JAR.
This is frustrating to developers. The principle workaround is to migrate
the code into some new package, whether using
jarjar or by hand. In fact,
the BC situation got so bad that somebody went and created Spongy Castle,
a clone of BC in an
org.spongycastle package, just to allow developers
to have a complete and clean BC implementation that they can use.
However, AFAIK, no new packages have been added by the core Android team that cause this effect. So, we have the handful that, like BC, cause grief, but it is a manageable and fixed roster.
This is important. Any new such package that would be added might break a bunch of existing apps that are using code from that package already via their own JARs. In this respect, not only are classes and methods part of a public API, but so are the “white spaces” — the things that are not included are also part of the public API, insofar as backwards- and forwards- compatibilty is concerned.
Alas, not all device manufacturers think of things like this.
HTC appears to have bundled GSON into some of their devices, such as the Desire HD, MyTouch 4G, and Desire Z. Rather than only use GSON in some of their own apps as a JAR, they appear to be loading it into all VMs for all applications, breaking those apps that have their own (incompatible) copy of GSON.
Now, this problem was first reported a bit over a year ago, and with luck HTC has stopped this practice. With further luck, no other manufacturer will try doing this. With yet further luck, HTC will eventually update these devices to a new firmware where they have fixed this problem.
If a manufacturer really needs to add third-party
code to the VM classes, it is incumbent upon the manufacturer to
jarjar or the equivalent and rename the code, to maintain compatibilty
with other Android devices.
Want an expert opinion on your Android app architecture decisions? Perhaps Mark Murphy can help!