When you build and Android app, it can consist of some combination of Java code and native code connected via JNI. The native code is represented as a .so (shared library) with the Android .apk file.

A common step in generating an apk is to run Proguard on the Java portion of the code, which strips out unused Java classes and methods to reduce binary size. However, Proguard won't touch the native shared library.

When a *static* native library is linked into an executable, the linker can similarly discard symbols that aren't needed. However, a shared library doesn't do this, because it theoretically doesn't know at link time what symbols are or aren't going to be needed. You can strip out symbol tables and debug info using --strip-all, and you can restrict the set of exported symbols to those explicitly identified with visibility=hidden, but there's no obvious way to say "just remove symbols that aren't used in this app."

My question is this. In the special case of Android or any other mixed Java/native app, even though the native code is represented as a shared library, you really do know exactly which symbols are and are not needed. Especially after Proguard runs, the set of JNI methods that are actually ever called may be reduced. Is there any way to further strip the shared library using this criteria, to minimize binary size?