Skip to content
This repository was archived by the owner on Jul 6, 2026. It is now read-only.

Commit 2c06b3c

Browse files
[Java.Interop] remove DynamicallyAccessedMemberTypes.Interfaces (#1285)
Context: dotnet/android#9630 Context: ec2813a As dotnet/android#9630 required new declarations of `DynamicallyAccessedMemberTypes.Interfaces`, we intestigated to see *why* these were needed in Java.Interop. There are two cases that involve `.Interfaces` within `JniRuntime.JniValueManager.GetValueMarshaler(Type)`: The first case is around attempts to special-case array marshaling for builtin types: var listIface = typeof (IList<>); var listType = (from iface in type.GetInterfaces ().Concat (new[]{type}) where (listIface).IsAssignableFrom (iface.IsGenericType ? iface.GetGenericTypeDefinition () : iface) select iface) .FirstOrDefault (); If `IList<T>` is trimmed away (lol), then *we don't care*, as everything else within `GetValueMarshaler(Type)` still works, and if we can't get a value marshaler for `int[]` (which implements `IList<T>`!), then so be it. Suppress this IL2070 message. The second case is around looking for `[JniValueMarshaler]` on implemented interface types, from ec2813a: JniValueMarshalerAttribute? ifaceAttribute = null; foreach (var iface in type.GetInterfaces ()) { marshalerAttr = iface.GetCustomAttribute<JniValueMarshalerAttribute> (); if (marshalerAttr != null) { if (ifaceAttribute != null) throw new NotSupportedException ($"There is more than one interface with custom marshaler for type {type}."); ifaceAttribute = marshalerAttr; } } if (ifaceAttribute != null) return (JniValueMarshaler) Activator.CreateInstance (ifaceAttribute.MarshalerType)!; It is to support the scenario namespace Android.Runtime { [JniValueMarshaler(typeof(IJavaObjectValueMarshaler))] partial interface /* Android.RuntimIJavaObject {} } namespace Java.Lang { partial class Object : Android.Runtime.IJavaObject {} } to "retrofit" `Java.Lang.Object` and `Java.Lang.Throwable` to use `IJavaObjectValueMarshaler`. There are three problems with this case: 1. It's not actually covered by unit tests! Removing the above `foreach` loop doesn't break any unit tests. 2. While dotnet/android was updated for this scenario, it was only as part of trying to use `jnimarshalmethod-gen` on Xamarin.Android projects, which was never finished. 3. It doesn't "scale": the code throws a `NotSupportedException` if a type implements more than one interface that has `[JniValueMarshaler]`. This isn't used, and *shouldn't* be relied upon. Excise it entirely. With these changes we can remove `DynamicallyAccessedMemberTypes.Interfaces`. I also introduced `build-tools/trim-analyzers/trim-analyzers.props` that will setup the appropriate trimmer MSBuild properties to make trimmer warnings an error. This should keep us from accidentally creating warnings. I only use this setting in projects that were already using `$(EnableAotAnalyzer)`.
1 parent f800ea5 commit 2c06b3c

14 files changed

Lines changed: 146 additions & 113 deletions
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<!-- Import this to enable trim warnings of all kinds -->
2+
<Project>
3+
<PropertyGroup>
4+
<!-- Sets assembly metadata, enable analyzers -->
5+
<IsTrimmable>true</IsTrimmable>
6+
<EnableSingleFileAnalyzer>true</EnableSingleFileAnalyzer>
7+
<EnableAotAnalyzer>true</EnableAotAnalyzer>
8+
<!-- In app projects, tells ILLink to emit warnings as errors -->
9+
<ILLinkTreatWarningsAsErrors>true</ILLinkTreatWarningsAsErrors>
10+
<!--
11+
Trim warnings, codes listed here:
12+
* https://github.com/dotnet/runtime/blob/7403a062960d092c73ce3f07d3ff323ffdf7de43/src/tools/illink/src/linker/Resources/Strings.resx
13+
* https://github.com/dotnet/docs/tree/9cb45cf9cd34f3b7259a023c3d92a124a87090d5/docs/core/deploying/trimming/trim-warnings
14+
-->
15+
<WarningsAsErrors>
16+
$(WarningsAsErrors);
17+
IL2000;IL2001;IL2002;IL2003;IL2004;
18+
IL2005;IL2006;IL2007;IL2008;IL2009;
19+
IL2010;IL2011;IL2012;IL2013;IL2014;
20+
IL2015;IL2016;IL2017;IL2018;IL2019;
21+
IL2020;IL2021;IL2022;IL2023;IL2024;
22+
IL2025;IL2026;IL2027;IL2028;IL2029;
23+
IL2030;IL2031;IL2032;IL2033;IL2034;
24+
IL2035;IL2036;IL2037;IL2038;IL2039;
25+
IL2040;IL2041;IL2042;IL2043;IL2044;
26+
IL2045;IL2046;IL2047;IL2048;IL2049;
27+
IL2050;IL2051;IL2052;IL2053;IL2054;
28+
IL2055;IL2056;IL2057;IL2058;IL2059;
29+
IL2060;IL2061;IL2062;IL2063;IL2064;
30+
IL2065;IL2066;IL2067;IL2068;IL2069;
31+
IL2070;IL2071;IL2072;IL2073;IL2074;
32+
IL2075;IL2076;IL2077;IL2078;IL2079;
33+
IL2080;IL2081;IL2082;IL2083;IL2084;
34+
IL2085;IL2086;IL2087;IL2088;IL2089;
35+
IL2090;IL2091;IL2092;IL2093;IL2094;
36+
IL2095;IL2096;IL2097;IL2098;IL2099;
37+
IL2100;IL2101;IL2102;IL2103;IL2104;
38+
IL2105;IL2106;IL2107;IL2108;IL2109;
39+
IL2110;IL2111;IL2112;IL2113;IL2114;
40+
IL2115;IL2116;IL2117;IL2118;IL2119;
41+
IL2120;IL2121;IL2122;IL2123;IL2124;
42+
IL2125;IL2126;IL2127;IL2128;IL2129;
43+
</WarningsAsErrors>
44+
<!-- In NativeAOT app projects, tells Ilc to emit warnings as errors -->
45+
<IlcTreatWarningsAsErrors>true</IlcTreatWarningsAsErrors>
46+
<!--
47+
NativeAOT warnings, codes listed here:
48+
* https://github.com/dotnet/docs/tree/9cb45cf9cd34f3b7259a023c3d92a124a87090d5/docs/core/deploying/native-aot/warnings
49+
-->
50+
<WarningsAsErrors>
51+
$(WarningsAsErrors);
52+
IL3050;IL3051;IL3052;IL3053;IL3054;IL3055;IL3056;
53+
</WarningsAsErrors>
54+
</PropertyGroup>
55+
</Project>

‎src/Java.Interop.Tools.TypeNameMappings/Java.Interop.Tools.TypeNameMappings.csproj‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,11 @@
33
<TargetFramework>$(DotNetTargetFramework)</TargetFramework>
44
<Nullable>enable</Nullable>
55
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
6-
<IsTrimmable>true</IsTrimmable>
7-
<EnableSingleFileAnalyzer>true</EnableSingleFileAnalyzer>
8-
<EnableAotAnalyzer>true</EnableAotAnalyzer>
96
<DefineConstants>$(DefineConstants);JCW_ONLY_TYPE_NAMES;HAVE_CECIL</DefineConstants>
107
</PropertyGroup>
118

129
<ImportProject="..\..\TargetFrameworkDependentValues.props" />
10+
<ImportProject="..\..\build-tools\trim-analyzers\trim-analyzers.props" />
1311
<ImportProject="..\..\build-tools\scripts\cecil.projitems" />
1412

1513
<ItemGroup>

‎src/Java.Interop/Java.Interop.csproj‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,13 @@
1414
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
1515
<Nullable>enable</Nullable>
1616
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
17-
<EnableSingleFileAnalyzer>true</EnableSingleFileAnalyzer>
18-
<IsTrimmable>true</IsTrimmable>
19-
<EnableAotAnalyzer>true</EnableAotAnalyzer>
2017
<MSBuildWarningsAsMessages>NU1702</MSBuildWarningsAsMessages>
2118
</PropertyGroup>
2219
<PropertyGroupCondition=" '$(Configuration)' == 'Debug' ">
2320
<DefineConstants>DEBUG;$(DefineConstants)</DefineConstants>
2421
</PropertyGroup>
2522
<ImportProject="..\..\TargetFrameworkDependentValues.props" />
23+
<ImportProject="..\..\build-tools\trim-analyzers\trim-analyzers.props" />
2624
<PropertyGroup>
2725
<DefineConstants>INTEROP;FEATURE_JNIOBJECTREFERENCE_INTPTRS;$(JavaInteropDefineConstants)</DefineConstants>
2826
<IntermediateOutputPath>$(BaseIntermediateOutputPath)$(Configuration)\$(TargetFramework.ToLowerInvariant())\</IntermediateOutputPath>

‎src/Java.Interop/Java.Interop/JavaArray.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ public void Dispose ()
363363
}
364364

365365
publicabstractclassJavaPrimitiveArray<
366-
[DynamicallyAccessedMembers(ConstructorsAndInterfaces)]
366+
[DynamicallyAccessedMembers(Constructors)]
367367
T
368368
>
369369
:JavaArray<T>

‎src/Java.Interop/Java.Interop/JavaObject.cs‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ namespace Java.Interop
99
unsafepublicclassJavaObject:IJavaPeerable
1010
{
1111
internalconstDynamicallyAccessedMemberTypesConstructors=DynamicallyAccessedMemberTypes.PublicConstructors|DynamicallyAccessedMemberTypes.NonPublicConstructors;
12-
internalconstDynamicallyAccessedMemberTypesConstructorsAndInterfaces=Constructors|DynamicallyAccessedMemberTypes.Interfaces;
1312

1413
readonlystaticJniPeerMembers_members=newJniPeerMembers("java/lang/Object",typeof(JavaObject));
1514

‎src/Java.Interop/Java.Interop/JavaObjectArray.cs‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
namespaceJava.Interop
99
{
1010
publicclassJavaObjectArray<
11-
[DynamicallyAccessedMembers(ConstructorsAndInterfaces)]
11+
[DynamicallyAccessedMembers(Constructors)]
1212
T
1313
>
1414
:JavaArray<T>
@@ -171,7 +171,7 @@ internal sealed class ValueMarshaler : JniValueMarshaler<IList<T>> {
171171
publicoverrideIList<T>CreateGenericValue(
172172
refJniObjectReferencereference,
173173
JniObjectReferenceOptionsoptions,
174-
[DynamicallyAccessedMembers(ConstructorsAndInterfaces)]
174+
[DynamicallyAccessedMembers(Constructors)]
175175
Type?targetType)
176176
{
177177
returnJavaArray<T>.CreateValue(refreference,options,targetType,(refJniObjectReferenceh,JniObjectReferenceOptionst)=>newJavaObjectArray<T>(refh,t){
@@ -203,7 +203,7 @@ partial class JniEnvironment {
203203
partialclassArrays{
204204

205205
publicstaticJavaObjectArray<T>?CreateMarshalObjectArray<
206-
[DynamicallyAccessedMembers(JavaObject.ConstructorsAndInterfaces)]
206+
[DynamicallyAccessedMembers(JavaObject.Constructors)]
207207
T
208208
>(
209209
IEnumerable<T>?value)

‎src/Java.Interop/Java.Interop/JavaPrimitiveArrays.cs‎

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ internal override bool TargetTypeIsCurrentType (Type? targetType)
246246

247247
publicstaticobject?CreateMarshaledValue(
248248
IntPtrhandle,
249-
[DynamicallyAccessedMembers(ConstructorsAndInterfaces)]
249+
[DynamicallyAccessedMembers(Constructors)]
250250
Type?targetType)
251251
{
252252
returnArrayMarshaler.CreateValue(handle,targetType);
@@ -257,7 +257,7 @@ internal sealed class ValueMarshaler : JniValueMarshaler<IList<Boolean>> {
257257
publicoverrideIList<Boolean>CreateGenericValue(
258258
refJniObjectReferencereference,
259259
JniObjectReferenceOptionsoptions,
260-
[DynamicallyAccessedMembers(ConstructorsAndInterfaces)]
260+
[DynamicallyAccessedMembers(Constructors)]
261261
Type?targetType)
262262
{
263263
returnJavaArray<Boolean>.CreateValue(
@@ -450,7 +450,7 @@ internal override bool TargetTypeIsCurrentType (Type? targetType)
450450

451451
publicstaticobject?CreateMarshaledValue(
452452
IntPtrhandle,
453-
[DynamicallyAccessedMembers(ConstructorsAndInterfaces)]
453+
[DynamicallyAccessedMembers(Constructors)]
454454
Type?targetType)
455455
{
456456
returnArrayMarshaler.CreateValue(handle,targetType);
@@ -461,7 +461,7 @@ internal sealed class ValueMarshaler : JniValueMarshaler<IList<SByte>> {
461461
publicoverrideIList<SByte>CreateGenericValue(
462462
refJniObjectReferencereference,
463463
JniObjectReferenceOptionsoptions,
464-
[DynamicallyAccessedMembers(ConstructorsAndInterfaces)]
464+
[DynamicallyAccessedMembers(Constructors)]
465465
Type?targetType)
466466
{
467467
returnJavaArray<SByte>.CreateValue(
@@ -654,7 +654,7 @@ internal override bool TargetTypeIsCurrentType (Type? targetType)
654654

655655
publicstaticobject?CreateMarshaledValue(
656656
IntPtrhandle,
657-
[DynamicallyAccessedMembers(ConstructorsAndInterfaces)]
657+
[DynamicallyAccessedMembers(Constructors)]
658658
Type?targetType)
659659
{
660660
returnArrayMarshaler.CreateValue(handle,targetType);
@@ -665,7 +665,7 @@ internal sealed class ValueMarshaler : JniValueMarshaler<IList<Char>> {
665665
publicoverrideIList<Char>CreateGenericValue(
666666
refJniObjectReferencereference,
667667
JniObjectReferenceOptionsoptions,
668-
[DynamicallyAccessedMembers(ConstructorsAndInterfaces)]
668+
[DynamicallyAccessedMembers(Constructors)]
669669
Type?targetType)
670670
{
671671
returnJavaArray<Char>.CreateValue(
@@ -858,7 +858,7 @@ internal override bool TargetTypeIsCurrentType (Type? targetType)
858858

859859
publicstaticobject?CreateMarshaledValue(
860860
IntPtrhandle,
861-
[DynamicallyAccessedMembers(ConstructorsAndInterfaces)]
861+
[DynamicallyAccessedMembers(Constructors)]
862862
Type?targetType)
863863
{
864864
returnArrayMarshaler.CreateValue(handle,targetType);
@@ -869,7 +869,7 @@ internal sealed class ValueMarshaler : JniValueMarshaler<IList<Int16>> {
869869
publicoverrideIList<Int16>CreateGenericValue(
870870
refJniObjectReferencereference,
871871
JniObjectReferenceOptionsoptions,
872-
[DynamicallyAccessedMembers(ConstructorsAndInterfaces)]
872+
[DynamicallyAccessedMembers(Constructors)]
873873
Type?targetType)
874874
{
875875
returnJavaArray<Int16>.CreateValue(
@@ -1062,7 +1062,7 @@ internal override bool TargetTypeIsCurrentType (Type? targetType)
10621062

10631063
publicstaticobject?CreateMarshaledValue(
10641064
IntPtrhandle,
1065-
[DynamicallyAccessedMembers(ConstructorsAndInterfaces)]
1065+
[DynamicallyAccessedMembers(Constructors)]
10661066
Type?targetType)
10671067
{
10681068
returnArrayMarshaler.CreateValue(handle,targetType);
@@ -1073,7 +1073,7 @@ internal sealed class ValueMarshaler : JniValueMarshaler<IList<Int32>> {
10731073
publicoverrideIList<Int32>CreateGenericValue(
10741074
refJniObjectReferencereference,
10751075
JniObjectReferenceOptionsoptions,
1076-
[DynamicallyAccessedMembers(ConstructorsAndInterfaces)]
1076+
[DynamicallyAccessedMembers(Constructors)]
10771077
Type?targetType)
10781078
{
10791079
returnJavaArray<Int32>.CreateValue(
@@ -1266,7 +1266,7 @@ internal override bool TargetTypeIsCurrentType (Type? targetType)
12661266

12671267
publicstaticobject?CreateMarshaledValue(
12681268
IntPtrhandle,
1269-
[DynamicallyAccessedMembers(ConstructorsAndInterfaces)]
1269+
[DynamicallyAccessedMembers(Constructors)]
12701270
Type?targetType)
12711271
{
12721272
returnArrayMarshaler.CreateValue(handle,targetType);
@@ -1277,7 +1277,7 @@ internal sealed class ValueMarshaler : JniValueMarshaler<IList<Int64>> {
12771277
publicoverrideIList<Int64>CreateGenericValue(
12781278
refJniObjectReferencereference,
12791279
JniObjectReferenceOptionsoptions,
1280-
[DynamicallyAccessedMembers(ConstructorsAndInterfaces)]
1280+
[DynamicallyAccessedMembers(Constructors)]
12811281
Type?targetType)
12821282
{
12831283
returnJavaArray<Int64>.CreateValue(
@@ -1470,7 +1470,7 @@ internal override bool TargetTypeIsCurrentType (Type? targetType)
14701470

14711471
publicstaticobject?CreateMarshaledValue(
14721472
IntPtrhandle,
1473-
[DynamicallyAccessedMembers(ConstructorsAndInterfaces)]
1473+
[DynamicallyAccessedMembers(Constructors)]
14741474
Type?targetType)
14751475
{
14761476
returnArrayMarshaler.CreateValue(handle,targetType);
@@ -1481,7 +1481,7 @@ internal sealed class ValueMarshaler : JniValueMarshaler<IList<Single>> {
14811481
publicoverrideIList<Single>CreateGenericValue(
14821482
refJniObjectReferencereference,
14831483
JniObjectReferenceOptionsoptions,
1484-
[DynamicallyAccessedMembers(ConstructorsAndInterfaces)]
1484+
[DynamicallyAccessedMembers(Constructors)]
14851485
Type?targetType)
14861486
{
14871487
returnJavaArray<Single>.CreateValue(
@@ -1674,7 +1674,7 @@ internal override bool TargetTypeIsCurrentType (Type? targetType)
16741674

16751675
publicstaticobject?CreateMarshaledValue(
16761676
IntPtrhandle,
1677-
[DynamicallyAccessedMembers(ConstructorsAndInterfaces)]
1677+
[DynamicallyAccessedMembers(Constructors)]
16781678
Type?targetType)
16791679
{
16801680
returnArrayMarshaler.CreateValue(handle,targetType);
@@ -1685,7 +1685,7 @@ internal sealed class ValueMarshaler : JniValueMarshaler<IList<Double>> {
16851685
publicoverrideIList<Double>CreateGenericValue(
16861686
refJniObjectReferencereference,
16871687
JniObjectReferenceOptionsoptions,
1688-
[DynamicallyAccessedMembers(ConstructorsAndInterfaces)]
1688+
[DynamicallyAccessedMembers(Constructors)]
16891689
Type?targetType)
16901690
{
16911691
returnJavaArray<Double>.CreateValue(

0 commit comments

Comments
 (0)