Skip to main content
Android historically supported 32-bit architectures, but several ABI design decisions in early Android versions led to compatibility issues. This page covers common 32-bit problems and best practices for migration.

Overview

Starting with Android 5.0 (API level 21), Google began requiring 64-bit support. As of August 2019, all apps on Google Play must include 64-bit versions of native libraries alongside 32-bit versions. Understanding 32-bit ABI issues is still important for:
  • Maintaining legacy code
  • Supporting older devices
  • Debugging compatibility issues
  • Ensuring correct migration to 64-bit
Google Play no longer accepts apps without 64-bit support. Ensure your app includes both 32-bit and 64-bit native libraries, or exclusively 64-bit libraries.

Common 32-bit ABI bugs

The following issues are specific to 32-bit Android ABIs (armeabi-v7a and x86).

time_t is 32-bit

On 32-bit Android, time_t is a 32-bit signed integer, leading to the Year 2038 problem.
Implications:
  • time_t will overflow on January 19, 2038 at 03:14:07 UTC
  • Dates after 2038 cannot be represented
  • Calculations involving future dates will fail
Solutions:
  • Use 64-bit types for time calculations: int64_t or long long
  • Migrate to 64-bit architecture (where time_t is 64-bit)
  • For portable code, use C++20’s std::chrono or custom time types

off_t is 32-bit by default

off_t (file offset type) is 32-bit by default on 32-bit Android, limiting files to 2GB.
Solutions: Define _FILE_OFFSET_BITS=64 to use 64-bit file offsets:
Or use explicit 64-bit functions:
Always define _FILE_OFFSET_BITS=64 when building for 32-bit targets if you handle files larger than 2GB.

stat structure differences

The stat structure has different field sizes on 32-bit vs 64-bit:
This causes issues when:
  • Serializing stat structures
  • Passing them between 32-bit and 64-bit code
  • Storing them in files or databases
Solution: Use stat64 explicitly on 32-bit:

Long double is the same as double

On 32-bit ARM, long double is only 64 bits (same as double), not 80 or 128 bits as on other platforms.
This affects numerical precision in calculations expecting extended precision. Solution: Be aware of precision limitations or use 64-bit architecture.

System calls use 32-bit parameters

Many system calls accept 32-bit parameters on 32-bit Android:
This limits:
  • Maximum mmap() size to 4GB
  • Maximum process memory to 4GB
  • Various kernel resource limits

ABI-specific considerations

armeabi-v7a (32-bit ARM)

  • Removed: armeabi (non-Thumb ARM) was removed in NDK r17
  • Supports NEON SIMD (check at runtime with android_getCpuFeatures())
  • Requires Thumb-2 instruction set
  • Hardware floating-point support

x86 (32-bit Intel/AMD)

  • Less common than ARM on Android devices
  • Uses System V ABI calling conventions
  • SIMD via SSE (check CPU features)

Migrating to 64-bit

Why migrate?

  • Required by Google Play - Apps must support 64-bit
  • Better performance - More registers, improved instruction set
  • Larger address space - No 4GB memory limit
  • Future-proof - 32-bit support may be deprecated

Migration checklist

1

Enable 64-bit ABIs in build configuration

2

Fix type assumptions

  • Don’t assume int and pointers are the same size
  • Don’t assume long is 32 bits (it’s 64 bits on 64-bit)
  • Use intptr_t, uintptr_t for pointer-sized integers
  • Use int32_t, int64_t for explicit-width integers
3

Update third-party libraries

Ensure all native dependencies support 64-bit:
  • Rebuild from source for 64-bit targets
  • Update to latest versions that support 64-bit
  • Check vendor documentation
4

Test thoroughly

  • Test on 64-bit devices
  • Run automated tests for both 32-bit and 64-bit builds
  • Check for crashes related to pointer size assumptions

Common migration issues

Pointer truncation

JNI type mismatches

Structure packing differences

Structure alignment and padding can differ between 32-bit and 64-bit:
Solution: Use __attribute__((packed)) or explicit padding if binary compatibility is required.

Testing 32-bit and 64-bit builds

Run both ABIs

Test your app on both 32-bit and 64-bit devices:

Check installed ABI

Force 32-bit on 64-bit device

For testing, you can force 32-bit mode:
Even if you only support 64-bit, test that your app gracefully handles 32-bit scenarios if fallback occurs.

Performance considerations

Memory usage

64-bit apps use more memory due to:
  • Larger pointers (8 bytes vs 4 bytes)
  • Increased structure padding
  • Larger code size
Typical increase: 10-30% more memory usage.

Performance improvements

64-bit offers:
  • More CPU registers (32 vs 16 on ARM)
  • Better instruction set (ARMv8 vs ARMv7)
  • Hardware crypto acceleration
  • Improved SIMD capabilities
Typical performance gain: 10-30% for compute-intensive tasks.

Additional resources