Mobile Development 11 min read

How I Reduced a Rust Android Dynamic Library from 495KB to 95KB

This article explains how the size of a Rust‑based Android dynamic library, initially 495 KB, was dramatically reduced to 95 KB through compiler optimization levels, link‑time optimization, panic handling changes, stripping unused sections, and custom linker scripts, providing practical tips for mobile developers.

JD Cloud Developers
JD Cloud Developers
JD Cloud Developers
How I Reduced a Rust Android Dynamic Library from 495KB to 95KB

Background

The size of an application package directly impacts download volume, installation time, and device storage usage. Google Play statistics show that every 6 MB increase in app size reduces conversion rate by 1 %.

This article focuses on reducing the size of a dynamic library (JNI) written in Rust for Android, rather than covering all possible size‑reduction techniques for DEX, resources, or native binaries.

Why Rust?

1. Stability : JNI calls are complex and involve native memory management. Rust’s strict compiler checks eliminate many classes of bugs, leading to more stable code.

2. Security : Rust binaries are harder to reverse‑engineer because existing decompilers (IDA, Ghidra) do not fully support Rust’s calling conventions.

However, Rust’s default build produces a relatively large binary (≈495 KB after stripping).

Optimization Steps

1. Adjust Optimization Level

Change the release profile from the default O3 (which expands loops) to opt-level = 'z' to prioritize minimal binary size.

[profile.release]
opt-level = 'z'

Result: 495 KB → 437 KB.

2. Enable LTO (Link‑Time Optimization)

LTO removes redundant code at link time, at the cost of longer linking.

[profile.release]
opt-level = 'z'
lto = true

Result: 437 KB → 436 KB (marginal gain).

3. Switch Panic Strategy to abort

Replace the default backtrace‑generating panic with an immediate abort to save space.

[profile.release]
opt-level = 'z'
lto = true
panic = 'abort'

Result: 436 KB → 366 KB.

4. Remove Unused Strings and Enable panic_immediate_abort

Trim unnecessary error‑message strings from third‑party crates and disable the generation of formatted panic strings.

.cargo/config.toml
[unstable]
build-std-features = ["panic_immediate_abort"]
build-std = ["std", "panic_abort"]

Result: 366 KB → 135 KB.

5. Analyze Binary with bloat

Using bloat reveals that the core jdmp crate occupies only ~46.9 KB, while the rest is overhead from the standard library and dependencies.

File   .text   Size   Crate
std    4.1%   192 KiB
jdmp   1.0%    46.9 KiB
...

6. Strip Unnecessary Sections

Inspect ELF sections with readelf -S and discard sections that are not required at runtime (e.g., .eh_frame, .comment, version tables). Removing them reduces the binary further.

aarch64-linux-gnu-readelf -S target/aarch64-linux-android/release/libjdmp.so

7. Custom Linker Script

Create a linker script that keeps only the essential sections ( .text, .rodata, .data, .dynamic) and discards the rest.

PHDRS {
  headers PT_PHDR PHDRS ;
  text PT_LOAD FILEHDR PHDRS ;
  data PT_LOAD ;
  dynamic PT_DYNAMIC ;
}
SECTIONS {
  . = SIZEOF_HEADERS;
  .text : { *(.text .text.*) } :text
  .rodata : { *(.rodata .rodata.*) } :text
  .data : { *(.data .data.*) *(.got*) *(.dynamic*) } :data
  /DISCARD/ : { *(.comment .eh_frame_hdr .eh_frame .gnu.version*) }
}

Update Cargo to use the custom script:

.cargo/config.toml
[build]
target = ["aarch64-linux-android", "armv7-linux-androideabi"]
[unstable]
build-std-features = ["panic_immediate_abort"]
build-std = ["std", "panic_abort"]
[target.aarch64-linux-android]
rustflags = ["-C", "link-arg=-Tlinker.lds"]
[target.armv7-linux-androideabi]
rustflags = ["-C", "link-arg=-Tlinker.lds"]

Final binary size after all optimizations: 95 KB, comfortably meeting the size requirement.

Conclusion

The series of optimizations—changing the optimization level, enabling LTO, switching panic handling, stripping unused sections, and applying a minimal linker script—reduced the Rust Android dynamic library from 495 KB to 95 KB. Many of these techniques are also applicable to C/C++ projects targeting mobile platforms.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

AndroidRustLTODynamic Librarysize optimizationlinker-scriptPanic Abort
JD Cloud Developers
Written by

JD Cloud Developers

JD Cloud Developers (Developer of JD Technology) is a JD Technology Group platform offering technical sharing and communication for AI, cloud computing, IoT and related developers. It publishes JD product technical information, industry content, and tech event news. Embrace technology and partner with developers to envision the future.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.