Skip to content

Commit 3d0d593

Browse files
[Tests] Add NativeAOT regression test for R8-kept runtime ACWs
Adds NativeAotKeepsRuntimeAcwJavaTypesUnderR8, which builds a Release NativeAOT app with r8 and asserts that classes.dex still contains the runtime UncaughtExceptionMarshaler ACW kept by the generated NativeAOT ProGuard rules. If those keep rules are missing, R8 tree-shakes the runtime JCWs and the app crashes at startup inside JavaInteropRuntime.init. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 251663a commit 3d0d593

1 file changed

Lines changed: 30 additions & 0 deletions

File tree

  • src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1536,6 +1536,36 @@ public void BuildProguardEnabledProject ([Values ("", "android-arm64")] string r
15361536
}
15371537
}
15381538

1539+
[Test]
1540+
public void NativeAotKeepsRuntimeAcwJavaTypesUnderR8 ()
1541+
{
1542+
const bool isRelease = true;
1543+
if (IgnoreUnsupportedConfiguration (AndroidRuntime.NativeAOT, release: isRelease)) {
1544+
return;
1545+
}
1546+
var proj = new XamarinAndroidApplicationProject {
1547+
IsRelease = isRelease,
1548+
LinkTool = "r8",
1549+
};
1550+
proj.SetRuntime (AndroidRuntime.NativeAOT);
1551+
using (var b = CreateApkBuilder ()) {
1552+
Assert.IsTrue (b.Build (proj), "Build should have succeeded.");
1553+
1554+
var intermediate = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath);
1555+
var dexFile = Path.Combine (intermediate, "android", "bin", "classes.dex");
1556+
FileAssert.Exists (dexFile);
1557+
1558+
// Regression test: the trimmable NativeAOT path generates its ACW keep rules from the
1559+
// ILC DGML into proguard_project_references.cfg. If that file is not passed to R8, R8
1560+
// tree-shakes the runtime ACW/JCW classes out of classes.dex and the app crashes at
1561+
// startup inside JavaInteropRuntime.init with a ClassNotFoundException for the
1562+
// UncaughtExceptionMarshaler Java Callable Wrapper. The JCW class name is CRC-hashed
1563+
// (e.g. `scrc64...UncaughtExceptionMarshaler`), so match on the type name suffix.
1564+
Assert.IsTrue (DexUtils.ContainsClass ("UncaughtExceptionMarshaler;", dexFile, AndroidSdkPath),
1565+
$"`{dexFile}` should include the UncaughtExceptionMarshaler ACW kept by the generated NativeAOT ProGuard rules.");
1566+
}
1567+
}
1568+
15391569
XamarinAndroidApplicationProject CreateMultiDexRequiredApplication (string debugConfigurationName = "Debug", string releaseConfigurationName = "Release")
15401570
{
15411571
var proj = new XamarinAndroidApplicationProject (debugConfigurationName, releaseConfigurationName);

0 commit comments

Comments
 (0)