Skip to content

Fix R8 stripping JNI callback methods causing SIGABRT#6247

Open
stevenelliottjr wants to merge 1 commit intogoogle-ai-edge:masterfrom
stevenelliottjr:fix/proguard-r8-callback-strip-6045
Open

Fix R8 stripping JNI callback methods causing SIGABRT#6247
stevenelliottjr wants to merge 1 commit intogoogle-ai-edge:masterfrom
stevenelliottjr:fix/proguard-r8-callback-strip-6045

Conversation

@stevenelliottjr
Copy link
Copy Markdown

Summary

Fixes #6045 — Android apps using MediaPipe tasks with R8 minification (isMinifyEnabled = true) crash with a fatal SIGABRT when running inference (e.g. ImageSegmenter.segment()).

Root cause: R8 tree-shakes process() method implementations on lambda-desugared anonymous classes that implement PacketCallback, PacketListCallback, or PacketWithHeaderCallback. R8 cannot see that these methods are invoked from native JNI code (graph.cc CallbackToJavaGetMethodIDCallVoidMethod), so it considers them dead code and strips them. When GetMethodID fails to find the method at runtime, the JNI layer triggers a hard SIGABRT that bypasses try/catch.

The existing ProGuard rule -keep public interface com.google.mediapipe.framework.* { public *; } preserves the interface definitions but does not prevent R8 from removing method implementations on anonymous/synthetic classes.

Fix: Add explicit -keep class * implements <Interface> rules for the three callback interfaces so R8 retains process() on all implementing classes, including lambda-desugared synthetics.

Changes

  • mediapipe/java/com/google/mediapipe/framework/proguard.pgcfg — Added keep rules for:
    • PacketCallback.process(Packet)
    • PacketListCallback.process(List)
    • PacketWithHeaderCallback.process(Packet, Packet)

Reproduction

Minimal repro from the issue reporter: https://github.com/rvp-diconium/mediapipe-bug-report

val segmenter = ImageSegmenter.createFromOptions(context, options)
segmenter.segment(inputImage).confidenceMasks() // SIGABRT here with R8 enabled

Logcat shows:

JNI DETECTED ERROR IN APPLICATION: JNI GetMethodID called with pending exception java.lang.NoSuchMethodError

Test plan

  • Build the mediapipe_aar target and verify the updated proguard.pgcfg is bundled
  • Build the minimal repro app (linked above) with isMinifyEnabled = true against the patched AAR
  • Verify ImageSegmenter.segment() completes without crash
  • Verify the same with PacketCallback (single-stream) and PacketWithHeaderCallback callbacks

…#6045)

R8 tree-shakes process() implementations on lambda-desugared
classes implementing PacketCallback, PacketListCallback, and
PacketWithHeaderCallback because it cannot see that these methods
are invoked from native JNI code in graph.cc (CallbackToJava).

When GetMethodID fails to find the stripped process() method at
runtime, the JNI layer triggers a fatal SIGABRT that cannot be
caught by try/catch.

The existing -keep rule on the interfaces preserves the interface
definitions but does not prevent R8 from removing method
implementations on anonymous classes. Add explicit -keep rules
for all classes implementing the three callback interfaces to
retain their process() methods.

Fixes: google-ai-edge#6045
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Android Runtime crash when ProGuard enabled. "No pending exception expected, NoSuchMethodError. no non-static method java/util/List"

1 participant