[r8] Obfuscate private Java members by default - #12668
Open
jonathanpeppers wants to merge 3 commits into
Open
Conversation
Preserve Java class names and public/protected member names while allowing R8 to obfuscate private and package-private members. Keep _AndroidR8DontObfuscate as a private escape hatch that only restores the previous global -dontobfuscate behavior. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: cf67f43d-2eef-46ac-9d52-e9a677671fc8
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
The new device test can leave apps installed on failure paths, which risks flakiness and cross-test interference in device CI runs.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR changes the default R8 behavior to allow obfuscation of private/package-private Java implementation details while keeping Java class names and public/protected member names stable for JNI compatibility, with a private MSBuild escape hatch to restore the previous global -dontobfuscate behavior.
Changes:
- Add a new selective-obfuscation default by generating base ProGuard/R8 rules at build time (and wiring an internal
$(_AndroidR8DontObfuscate)toggle). - Update embedded ProGuard config resources to no longer globally disable obfuscation, and add a NativeAOT-specific keep rule for
mono.android.Runtimestartup fields. - Add device integration tests validating mapping + DEX output + runtime execution for CoreCLR and NativeAOT.
File summaries
| File | Description |
|---|---|
| tests/MSBuildDeviceIntegration/Tests/R8ObfuscationTests.cs | Adds device test coverage verifying selective obfuscation via mapping/DEX inspection and a runtime probe. |
| src/Xamarin.Android.Build.Tasks/Xamarin.Android.D8.targets | Plumbs a private MSBuild escape hatch property into the R8 task invocation. |
| src/Xamarin.Android.Build.Tasks/Tasks/R8.cs | Implements default selective-obfuscation ProGuard directives generation and supports DontObfuscate. |
| src/Xamarin.Android.Build.Tasks/Resources/proguard_xamarin.cfg | Removes the global -dontobfuscate default from the common R8 config resource. |
| src/Xamarin.Android.Build.Tasks/Resources/proguard_trimmable_nativeaot.cfg | Removes -dontobfuscate and adds a keep rule for mono.android.Runtime fields needed at NativeAOT startup. |
Review details
- Files reviewed: 5/5 changed files
- Comments generated: 1
- Review effort level: Lite
Track successful installation and attempt uninstall from a finally block so assertion failures do not leave packages on the test device. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: cf67f43d-2eef-46ac-9d52-e9a677671fc8
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: cf67f43d-2eef-46ac-9d52-e9a677671fc8
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
R8 currently disables all obfuscation by default. That avoids breaking JNI names, but also prevents R8 from shortening implementation details that are safe to rename.
Preserve Java class names and public/protected member names while allowing private and package-private members to be obfuscated:
This avoids managed IL rewriting while keeping Java names that can participate in JNI stable. The NativeAOT configuration also preserves the package-private
java.lang.Classfields onmono.android.Runtimebecause native hosts resolve those fields by literal name during startup.Escape hatch
$(_AndroidR8DontObfuscate)is a private escape hatch only. Setting it totruerestores the previous global-dontobfuscatebehavior. It is not a new supported public build property or an alternative configuration mode, and it remains blank by default.Tests
Added
R8ObfuscationTestsdevice coverage for CoreCLR and NativeAOT using anAndroidJavaSourceprobe. It verifies that class/public/protected names remain stable, private/package-private methods are renamed in the mapping and DEX output, and the resulting app launches and executes the JNI call successfully.