Enable opt-in R8 JNI name obfuscation for CoreCLR and NativeAOT - #12575
Draft
simonrozsival wants to merge 13 commits into
Draft
Enable opt-in R8 JNI name obfuscation for CoreCLR and NativeAOT#12575simonrozsival wants to merge 13 commits into
simonrozsival wants to merge 13 commits into
Conversation
Rebuild managed PE metadata and IL with obfuscated JNI class, method, field, descriptor, RegisterNatives, and FieldRVA string data. Preserve compression descriptor ordering when rewritten assembly sizes change. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Run a naming-only R8 pass before managed optimization, stage rewritten inputs for ILLink and ILC, and reuse the mapping during final Java shrinking. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Use descriptor-aware reverse member mappings and regenerate the post-link ACW reachability map while retaining the original Java input set. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Record the exact seed mapping entries consumed while rewriting managed assemblies and verify that final R8 preserves every surviving name. Removed entries remain valid linker or R8 trimming outcomes. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Generate post-link manifests from the CoreCLR and NativeAOT keep-rule inputs, then fail final R8 when a required Java class or member disappears. Cover registered fields and overload-aware methods in the CoreCLR rules. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Reuse the full JNI rewrite planner in reverse over linked CoreCLR assemblies so final R8 keep rules cover attributes, direct lookups, descriptors, interfaces, typemap metadata, and FieldRVA data. Preserve every ambiguous reverse member candidate and index exact lookups. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Normalize expected multiline output to the host line ending so the new test passes on Windows as well as Unix. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Add a supported opt-in, collision-safe staging, multi-ABI and project-reference coverage, identity-preserving strong-name handling, and deduplicated ACW keep rules. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Member
Author
|
/review |
Contributor
|
🚀 Android PR Reviewer has started processing this issue comment |
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.
Context
Advances #12535.
.NET for Android currently disables R8 name obfuscation because managed bindings embed Java/JNI class, method, field, and descriptor names. If R8 renames the Java side while managed metadata and IL retain the original names, JNI lookup and native registration fail.
This change implements build-time rewriting without a runtime lookup table. R8 remains the naming authority: a naming-only pass establishes names, managed assemblies are rewritten before ILLink or NativeAOT ILC, and final R8 performs normal shrinking and optimization with
-applymapping.The feature is opt-in through
AndroidEnableR8JniNameObfuscation. It requiresAndroidLinkTool=r8,AndroidTypeMapImplementation=trimmable, and either CoreCLR or NativeAOT.Pipeline
-applymapping.NativeAOT's prebuilt host performs fixed native lookups against
mono.android.Runtime, so that small bridge remains deliberately preserved.Production hardening
StrongNameSignedflag is cleared. These private rewritten inputs are intentionally delay-signed because the original private keys are unavailable.Validation coverage
Automated Release integration tests cover CoreCLR and NativeAOT and verify:
The focused hardening matrix passes all 7 CoreCLR, NativeAOT, multi-ABI, project-reference/custom-rule, incrementality, and strong-name tests. Existing JNI mapping, rewriting, scanning, mapping-consistency, and reachability coverage remains in place.
Measurements
Across 86 generated typemap assemblies, rewriting 13,031 real typemap entries reduced raw PE size by 1,016,832 bytes (9.42%) and gzip-equivalent size by 107,446 bytes (6.61%). NativeAOT's packaged saving came primarily from
classes.dex, because those managed assemblies are compiled into the application native library.Naming-only R8 remains the dominant added clean-build cost. Replacing it with a managed allocator would reproduce R8 inheritance, interface dispatch, override, keep-rule, and minifier semantics, so this design intentionally keeps R8 as the naming authority.
Remaining follow-up
Additional ACW class-name obfuscation is intentionally deferred. Allowing those classes to be renamed caused CoreCLR final R8 to remove reachable generated native declarations such as
nctor_0; the reachability validator correctly rejected the output. Supporting this safely requires a separate native registration/retention design rather than weaker validation or another superficial ProGuard modifier.