Skip to content

Commit 7d1e705

Browse files
[Java.Interop] ignore remaining trimming warnings (#1190)
Fixes: #1157 The remaining trimmer warnings are around usage of System.Reflection such as: * Creating an `Invoker` type from an original type via `Type.Assembly.GetType()`, within `JniRuntime.JniValueManager.GetInvokerType()`. * Create a `JniValueMarshaler` corresponding to `ParameterInfo.ParameterType` in `JniRuntime.JniMarshalMemberBuilder.GetParameterMarshaler()`. * Create a value corresponding to `ParameterInfo.ParameterType` in `ManagedPeer.GetValues()`. * Use `typeof(JavaObjectArray<>).MakeGenericType()` in `JniRuntime.JniTypeManager.GetTypes(JniTypeSignature)`. * Use `Type.MakeArrayType()` in `JniRuntime.JniTypeManager.GetTypes(JniTypeSignature)`. The trimming warnings themselves all indicate that these types "might be trimmed", in that nothing explicitly preserves them. However, we have a plethora of custom trimmer steps that work to preserve these types involved in Java interop, such as: * https://github.com/xamarin/xamarin-android/blob/71b6fcc92f9e86246e0fe575bc1f44bbf73c3132/src/Microsoft.Android.Sdk.ILLink/PreserveApplications.cs * https://github.com/xamarin/xamarin-android/blob/71b6fcc92f9e86246e0fe575bc1f44bbf73c3132/src/Microsoft.Android.Sdk.ILLink/PreserveExportedTypes.cs * https://github.com/xamarin/xamarin-android/blob/71b6fcc92f9e86246e0fe575bc1f44bbf73c3132/src/Microsoft.Android.Sdk.ILLink/PreserveJavaExceptions.cs * https://github.com/xamarin/xamarin-android/blob/71b6fcc92f9e86246e0fe575bc1f44bbf73c3132/src/Microsoft.Android.Sdk.ILLink/PreserveJavaInterfaces.cs * https://github.com/xamarin/xamarin-android/blob/71b6fcc92f9e86246e0fe575bc1f44bbf73c3132/src/Microsoft.Android.Sdk.ILLink/PreserveRegistrations.cs One day, in a perfect world, we could remove these trimmer steps and completely rely on the trimmer's warnings & attributing mechanisms. That day doesn't have to be today -- as our goal is begin surfacing trimmer warnings to users in their own code and dependencies. With these warnings ignored, we can fully enable analyzers with: <IsTrimmable>true</IsTrimmable> <EnableAotAnalyzer>true</EnableAotAnalyzer> We can then remove: [assembly: AssemblyMetadata ("IsTrimmable", "True")] As the MSBuild property does this for us, in addition to enabling analyzers. I don't think we should enable `$(IsAotCompatible)` quite yet, as `Java.Interop.dll` likely *won't work* yet on NativeAOT, and this places metadata that says an assembly is supported. We should just use the `$(EnableAotAnalyzer)` analyzers for now, so we don't introduce new issues.
1 parent b8f6f88 commit 7d1e705

7 files changed

+71
-18
lines changed

src/Java.Interop/Java.Interop.csproj

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,8 @@
1515
<Nullable>enable</Nullable>
1616
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
1717
<EnableSingleFileAnalyzer>true</EnableSingleFileAnalyzer>
18-
<!-- TODO: enable these when all warnings are solved -->
19-
<!--<IsTrimmable>true</IsTrimmable>-->
20-
<!--<EnableAotAnalyzer>true</EnableAotAnalyzer>-->
18+
<IsTrimmable>true</IsTrimmable>
19+
<EnableAotAnalyzer>true</EnableAotAnalyzer>
2120
<MSBuildWarningsAsMessages>NU1702</MSBuildWarningsAsMessages>
2221
</PropertyGroup>
2322
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">

src/Java.Interop/Java.Interop/JniRuntime.JniMarshalMemberBuilder.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,12 @@ string GetTypeSignature (ParameterInfo p)
152152

153153
public JniValueMarshaler GetParameterMarshaler (ParameterInfo parameter)
154154
{
155+
// Activator.CreateInstance requires DynamicallyAccessedMemberTypes.PublicParameterlessConstructor
156+
// GetValueMarshaler requires DynamicallyAccessedMemberTypes.Interfaces
157+
[UnconditionalSuppressMessage ("Trimming", "IL2072", Justification = "JniValueMarshalerAttribute is decorated with [DynamicallyAccessedMembers]")]
158+
static JniValueMarshaler GetValueMarshaler (JniValueManager manager, ParameterInfo parameter) =>
159+
manager.GetValueMarshaler (parameter.ParameterType);
160+
155161
if (parameter.ParameterType == typeof (IntPtr))
156162
return IntPtrValueMarshaler.Instance;
157163

@@ -164,7 +170,7 @@ public JniValueMarshaler GetParameterMarshaler (ParameterInfo parameter)
164170
if (attr != null) {
165171
return (JniValueMarshaler) Activator.CreateInstance (attr.MarshalerType)!;
166172
}
167-
return Runtime.ValueManager.GetValueMarshaler (parameter.ParameterType);
173+
return GetValueMarshaler (Runtime.ValueManager, parameter);
168174
}
169175

170176
// Heuristic: if first two parameters are IntPtr, this is a "direct" wrapper.

src/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -269,8 +269,18 @@ protected virtual IEnumerable<string> GetSimpleReferences (Type type)
269269

270270
static readonly string[] EmptyStringArray = Array.Empty<string> ();
271271
static readonly Type[] EmptyTypeArray = Array.Empty<Type> ();
272+
const string NotUsedInAndroid = "This code path is not used in Android projects.";
272273

274+
// FIXME: https://github.com/xamarin/java.interop/issues/1192
275+
[UnconditionalSuppressMessage ("AOT", "IL3050", Justification = NotUsedInAndroid)]
276+
static Type MakeArrayType (Type type) => type.MakeArrayType ();
273277

278+
// FIXME: https://github.com/xamarin/java.interop/issues/1192
279+
[UnconditionalSuppressMessage ("Trimming", "IL2055", Justification = NotUsedInAndroid)]
280+
[UnconditionalSuppressMessage ("AOT", "IL3050", Justification = NotUsedInAndroid)]
281+
static Type MakeGenericType (Type type, Type arrayType) => type.MakeGenericType (arrayType);
282+
283+
[UnconditionalSuppressMessage ("Trimming", "IL2073", Justification = "Types returned here should be preserved via other means.")]
274284
[return: DynamicallyAccessedMembers (MethodsConstructorsInterfaces)]
275285
public Type? GetType (JniTypeSignature typeSignature)
276286
{
@@ -309,7 +319,7 @@ IEnumerable<Type> CreateGetTypesEnumerator (JniTypeSignature typeSignature)
309319
var rank = typeSignature.ArrayRank;
310320
var arrayType = type;
311321
while (rank-- > 0) {
312-
arrayType = typeof (JavaObjectArray<>).MakeGenericType (arrayType);
322+
arrayType = MakeGenericType (typeof (JavaObjectArray<>), arrayType);
313323
}
314324
yield return arrayType;
315325
}
@@ -318,7 +328,7 @@ IEnumerable<Type> CreateGetTypesEnumerator (JniTypeSignature typeSignature)
318328
var rank = typeSignature.ArrayRank;
319329
var arrayType = type;
320330
while (rank-- > 0) {
321-
arrayType = arrayType.MakeArrayType ();
331+
arrayType = MakeArrayType (arrayType);
322332
}
323333
yield return arrayType;
324334
}
@@ -341,14 +351,14 @@ IEnumerable<Type> GetPrimitiveArrayTypesForSimpleReference (JniTypeSignature typ
341351
var rank = typeSignature.ArrayRank-1;
342352
var arrayType = t;
343353
while (rank-- > 0) {
344-
arrayType = typeof (JavaObjectArray<>).MakeGenericType (arrayType);
354+
arrayType = MakeGenericType (typeof (JavaObjectArray<>), arrayType);
345355
}
346356
yield return arrayType;
347357

348358
rank = typeSignature.ArrayRank-1;
349359
arrayType = t;
350360
while (rank-- > 0) {
351-
arrayType = arrayType.MakeArrayType ();
361+
arrayType = MakeArrayType (arrayType);
352362
}
353363
yield return arrayType;
354364
}
@@ -462,6 +472,11 @@ protected bool TryRegisterNativeMembers (
462472

463473
static Type [] registerMethodParameters = new Type [] { typeof (JniNativeMethodRegistrationArguments) };
464474

475+
// https://github.com/xamarin/xamarin-android/blob/5472eec991cc075e4b0c09cd98a2331fb93aa0f3/src/Microsoft.Android.Sdk.ILLink/PreserveRegistrations.cs#L85
476+
const string MarshalMethods = "'jni_marshal_methods' is preserved by the PreserveRegistrations trimmer step.";
477+
478+
[UnconditionalSuppressMessage ("Trimming", "IL2072", Justification = MarshalMethods)]
479+
[UnconditionalSuppressMessage ("Trimming", "IL2075", Justification = MarshalMethods)]
465480
bool TryLoadJniMarshalMethods (
466481
JniType nativeClass,
467482
[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicNestedTypes)]

src/Java.Interop/Java.Interop/JniRuntime.JniValueManager.cs

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -359,18 +359,36 @@ static Type GetPeerType ([DynamicallyAccessedMembers (Constructors)] Type type)
359359
static Type? GetInvokerType (Type type)
360360
{
361361
const string suffix = "Invoker";
362+
363+
// https://github.com/xamarin/xamarin-android/blob/5472eec991cc075e4b0c09cd98a2331fb93aa0f3/src/Microsoft.Android.Sdk.ILLink/MarkJavaObjects.cs#L176-L186
364+
const string assemblyGetTypeMessage = "'Invoker' types are preserved by the MarkJavaObjects trimmer step.";
365+
const string makeGenericTypeMessage = "Generic 'Invoker' types are preserved by the MarkJavaObjects trimmer step.";
366+
367+
[UnconditionalSuppressMessage ("Trimming", "IL2026", Justification = assemblyGetTypeMessage)]
368+
[UnconditionalSuppressMessage ("Trimming", "IL2073", Justification = assemblyGetTypeMessage)]
369+
[return: DynamicallyAccessedMembers (Constructors)]
370+
static Type? AssemblyGetType (Assembly assembly, string typeName) =>
371+
assembly.GetType (typeName);
372+
373+
// FIXME: https://github.com/xamarin/java.interop/issues/1192
374+
[UnconditionalSuppressMessage ("Trimming", "IL2055", Justification = makeGenericTypeMessage)]
375+
[UnconditionalSuppressMessage ("AOT", "IL3050", Justification = makeGenericTypeMessage)]
376+
[return: DynamicallyAccessedMembers (Constructors)]
377+
static Type MakeGenericType (Type type, Type [] arguments) =>
378+
type.MakeGenericType (arguments);
379+
362380
Type[] arguments = type.GetGenericArguments ();
363381
if (arguments.Length == 0)
364-
return type.Assembly.GetType (type + suffix);
382+
return AssemblyGetType (type.Assembly, type + suffix);
365383
Type definition = type.GetGenericTypeDefinition ();
366384
int bt = definition.FullName!.IndexOf ("`", StringComparison.Ordinal);
367385
if (bt == -1)
368386
throw new NotSupportedException ("Generic type doesn't follow generic type naming convention! " + type.FullName);
369-
Type? suffixDefinition = definition.Assembly.GetType (
387+
Type? suffixDefinition = AssemblyGetType (definition.Assembly,
370388
definition.FullName.Substring (0, bt) + suffix + definition.FullName.Substring (bt));
371389
if (suffixDefinition == null)
372390
return null;
373-
return suffixDefinition.MakeGenericType (arguments);
391+
return MakeGenericType (suffixDefinition, arguments);
374392
}
375393

376394
public object? CreateValue (
@@ -634,9 +652,17 @@ public JniValueMarshaler GetValueMarshaler (
634652

635653
static JniValueMarshaler GetObjectArrayMarshaler (Type elementType)
636654
{
655+
const string makeGenericMethodMessage = "This code path is not used in Android projects.";
656+
657+
// FIXME: https://github.com/xamarin/java.interop/issues/1192
658+
[UnconditionalSuppressMessage ("Trimming", "IL2060", Justification = makeGenericMethodMessage)]
659+
[UnconditionalSuppressMessage ("AOT", "IL3050", Justification = makeGenericMethodMessage)]
660+
static MethodInfo MakeGenericMethod (MethodInfo method, Type type) =>
661+
method.MakeGenericMethod (type);
662+
637663
Func<JniValueMarshaler> indirect = GetObjectArrayMarshalerHelper<object>;
638-
var reifiedMethodInfo = indirect.Method.GetGenericMethodDefinition ()
639-
.MakeGenericMethod (elementType);
664+
var reifiedMethodInfo = MakeGenericMethod (
665+
indirect.Method.GetGenericMethodDefinition (), elementType);
640666
Func<JniValueMarshaler> direct = (Func<JniValueMarshaler>) Delegate.CreateDelegate (typeof (Func<JniValueMarshaler>), reifiedMethodInfo);
641667
return direct ();
642668
}

src/Java.Interop/Java.Interop/JniValueMarshalerAttribute.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#nullable enable
1+
#nullable enable
22

33
using System;
44
using System.Diagnostics.CodeAnalysis;
@@ -8,13 +8,16 @@ namespace Java.Interop {
88

99
[AttributeUsage (Targets, AllowMultiple=false)]
1010
public class JniValueMarshalerAttribute : Attribute {
11+
const DynamicallyAccessedMemberTypes ParameterlessConstructorsInterfaces = DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.Interfaces;
1112

1213
const AttributeTargets Targets =
1314
AttributeTargets.Class | AttributeTargets.Enum |
1415
AttributeTargets.Interface | AttributeTargets.Struct |
1516
AttributeTargets.Parameter | AttributeTargets.ReturnValue;
1617

17-
public JniValueMarshalerAttribute (Type marshalerType)
18+
public JniValueMarshalerAttribute (
19+
[DynamicallyAccessedMembers (ParameterlessConstructorsInterfaces)]
20+
Type marshalerType)
1821
{
1922
if (marshalerType == null)
2023
throw new ArgumentNullException (nameof (marshalerType));
@@ -27,7 +30,7 @@ public JniValueMarshalerAttribute (Type marshalerType)
2730
}
2831

2932
public Type MarshalerType {
30-
[return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
33+
[return: DynamicallyAccessedMembers (ParameterlessConstructorsInterfaces)]
3134
get;
3235
}
3336
}

src/Java.Interop/Java.Interop/ManagedPeer.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,11 @@ static List<Type>[] GetConstructorCandidateParameterTypes (string signature)
229229

230230
static object?[]? GetValues (JniRuntime runtime, JniObjectReference values, ConstructorInfo cinfo)
231231
{
232+
// https://github.com/xamarin/xamarin-android/blob/5472eec991cc075e4b0c09cd98a2331fb93aa0f3/src/Microsoft.Android.Sdk.ILLink/MarkJavaObjects.cs#L51-L132
233+
[UnconditionalSuppressMessage ("Trimming", "IL2072", Justification = "Constructors are preserved by the MarkJavaObjects trimmer step.")]
234+
static object? ValueManagerGetValue (JniRuntime runtime, ref JniObjectReference value, ParameterInfo parameter) =>
235+
runtime.ValueManager.GetValue (ref value, JniObjectReferenceOptions.CopyAndDispose, parameter.ParameterType);
236+
232237
if (!values.IsValid)
233238
return null;
234239

@@ -240,7 +245,7 @@ static List<Type>[] GetConstructorCandidateParameterTypes (string signature)
240245
var pvalues = new object? [len];
241246
for (int i = 0; i < len; ++i) {
242247
var n_value = JniEnvironment.Arrays.GetObjectArrayElement (values, i);
243-
var value = runtime.ValueManager.GetValue (ref n_value, JniObjectReferenceOptions.CopyAndDispose, parameters [i].ParameterType);
248+
var value = ValueManagerGetValue (runtime, ref n_value, parameters [i]);
244249
pvalues [i] = value;
245250
}
246251

src/Java.Interop/Properties/AssemblyInfo.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
[assembly: AssemblyDescription ("")]
77
[assembly: AssemblyCulture ("")]
88
[assembly: AssemblyTrademark ("Microsoft Corporation")]
9-
[assembly: AssemblyMetadata ("IsTrimmable", "True")]
109

1110
[assembly: InternalsVisibleTo (
1211
"Java.Interop.GenericMarshaler, PublicKey=" +

0 commit comments

Comments
 (0)