Understanding x86 vs ARM Memory Alignment on Android

With Google’s recent release of the NDK (r6), it is now possible build Android application for x86 processors in addition to ARM. In general, this only involves rebuilding native code to port applications from ARM to x86. However, there are a few pitfalls to avoid.

One difference between x86 and ARM is the memory alignment requirements for data. Let’s look at a simple example:

This example just logs the size and offset of variables in TestStruct. The output for this program isn’t too surprising:

The 8-byte (64-bit) mVar2 results in different layout for TestStruct. This is because ARM requires 8-byte alignment for 64-bit variables like mVar2. In most cases, this won’t cause problems because building for x86 vs ARM requires a full rebuild.

However, if an application serializes class or structures, this could cause a size mismatch. For example, say you create a save file on an ARM application and it writes TestStruct to a file. If you later load this file on an x86 platform, the class size in the application will be different than the saved file. As you can imagine, similar memory alignment issues can happen for network traffic that expects a specific memory layout.

The GCC compiler option “-malign-double” will generate the same memory alignment on x86 and ARM. However, since the OS was not built with this flag, it will break some OS calls.

You can control the alignment of variables through compiler attributes. So, if we tell GCC to align(8) for mVar2, x86 and ARM will have the same alignment:

Yes, the Java side will handle these differences automatically (e.g. ObjectInputStream. ObjectOutputStream, etc). If an app use native C/C++ code middleware (e.g. the C/C++ version of sqlite3), then the memory alignment differences need to be kept in mind. Most middleware was originally written for x86, so most handle memory management properly.

Ugh, never thought about it, that's a critical consideration.
ObjectInputStream and ObjectOutputStream and following Android persistency framewok (ContentProvider, sqlite3, etc) whenever it's possible should address it in many of the cases, no?