Skip to content

Commit 6820a9c

Browse files
[Java.Interop] Make JavaProxyObject.RegisterNativeMembers private again (#1468)
#1441 changed `JavaProxyObject.RegisterNativeMembers` from `private` to `internal` so the new reflection-free `JniRuntime.JniTypeManager.TryRegisterBuiltInNativeMembers ()` could call it directly. A side effect is that the `[JniAddNativeMethodRegistrationAttribute]`- annotated method now appears in Java.Interop's *reference* assembly. dotnet/android's trimmable typemap scanner reads reference assemblies and rejects any type carrying that attribute (XA4251), so every trimmable typemap build now fails on the built-in `JavaProxyObject` (see dotnet/android#11622). Restore the method to `private` (so it is stripped from the reference assembly) and expose a small attribute-free `internal` entry point, `RegisterBuiltInNativeMembers (JniType)`, for the built-in registration path to call. Runtime behavior is unchanged. ### [Java.Interop] Restore pure-reflection registration for JavaProxyObject #1441 added `JniRuntime.JniTypeManager.TryRegisterBuiltInNativeMembers ()` -- a reflection-free direct call to `JavaProxyObject.RegisterNativeMembers` -- and bumped that method to `internal` so the call would compile. That method is dead code: nothing in Java.Interop (or dotnet/android) ever calls it, and the base `JniTypeManager.RegisterNativeMembers` is a no-op. `JavaProxyObject`'s native members are -- and were before #1441 -- registered purely via reflection in `ReflectionJniTypeManager` (`FindAndCallRegisterMethod` discovering the `[JniAddNativeMethodRegistrationAttribute]`-annotated method), which finds private methods just fine via `GetRuntimeMethods ()`. Remove the unused `TryRegisterBuiltInNativeMembers` and restore `RegisterNativeMembers` to `private` (its state before #1441). Making it private again also strips the attribute-bearing method from the reference assembly, which fixes dotnet/android's trimmable typemap scanner falsely rejecting the built-in `JavaProxyObject` with XA4251 (dotnet/android#11622). ### Address review: restore TryRegisterBuiltInNativeMembers (not dead code) The previous commit deleted JniRuntime.JniTypeManager.TryRegisterBuiltInNativeMembers claiming it was unused. That was wrong: it has two live callers in the NativeAOT samples (samples/Hello-NativeAOTFromJNI/NativeAotTypeManager.cs and samples/Hello-NativeAOTFromAndroid/NativeAotTypeManager.cs), both JniTypeManager subclasses. Deleting it broke them (CS0103) and removed the only path that registers JavaProxyObject's equals/hashCode/toString natives for NativeAOT type managers (which don't use the reflection-based FindAndCallRegisterMethod path). The breakage was hidden in CI only because the NativeAOT sample steps use continueOnError: true. Keep the XA4251 fix (RegisterNativeMembers stays private, so the [JniAddNativeMethodRegistrationAttribute] is stripped from the reference assembly) and restore TryRegisterBuiltInNativeMembers by extracting the registration logic into a new attribute-free internal helper, JavaProxyObject.AddBuiltInRegistrations. Both the private attributed RegisterNativeMembers (reflection path) and TryRegisterBuiltInNativeMembers (NativeAOT path) call it. Restore the PublicAPI.Unshipped.txt entry as well. Verified: Java.Interop.dll builds clean; the reference assembly contains no method carrying [JniAddNativeMethodRegistration]; the sample's call to TryRegisterBuiltInNativeMembers resolves (no CS0103). ### Keep built-in registration in the samples via ReflectionJniTypeManager Replaces the production TryRegisterBuiltInNativeMembers helper with a samples-only solution, restoring the pre-#1441 behavior for the NativeAOT type managers. Background: making JavaProxyObject.RegisterNativeMembers private (the XA4251 fix) is sufficient for the default Android runtime, which discovers and invokes it via reflection (FindAndCallRegisterMethod -> GetRuntimeMethods(), which returns private methods). The only thing that needed JavaProxyObject's registration via a non-reflection path was the two NativeAOT samples, which #1441 had rewritten to derive from the reflection-free JniRuntime.JniTypeManager base. That is why #1441 introduced TryRegisterBuiltInNativeMembers. Instead of carrying that helper in production, have the sample type managers derive from JniRuntime.ReflectionJniTypeManager again - exactly what the base JniRuntime.JniTypeManager provided before #1441. Built-in types such as JavaProxyObject/JavaProxyThrowable are then registered automatically via reflection, and the samples no longer need any custom registration code. Changes: - JavaProxyObject.RegisterNativeMembers: internal -> private. The marshalers stay (the default reflection runtime registers them by reflecting over this type); only the visibility changes, which strips the attribute from the reference assembly and fixes the dotnet/android XA4251 scanner failure. - Delete JniRuntime.JniTypeManager.TryRegisterBuiltInNativeMembers (+ its PublicAPI.Unshipped.txt entry); no longer needed. - Hello-NativeAOTFromJNI / Hello-NativeAOTFromAndroid: derive from JniRuntime.ReflectionJniTypeManager and drop the reflection-free overrides and hand-written JavaProxyObject registration. ReflectionJniTypeManager is [RequiresDynamicCode]/[RequiresUnreferencedCode], so the constructor suppresses IL2026/IL3050 with [UnconditionalSuppressMessage]. A #pragma is insufficient here: it silences the Roslyn analyzer but not the ILLink/ILC publish passes, which only honor the attribute (verified with a trim-publish of the real type manager against Java.Interop.dll). Net: production loses code (1-line visibility change + deletions) and the samples shrink substantially. ### Drop verbose explanatory comments from the NativeAOT sample type managers The [UnconditionalSuppressMessage] Justification strings already convey the necessary context. ### Fix NativeAOT sample type resolution: override GetTypeForSimpleReference Build 1465402's "run Hello-NativeAOTFromJNI" step failed at runtime: System.NotSupportedException: Could not find System.Type corresponding to Java type JniTypeSignature(TypeName=example/ManagedType ...) at Java.Interop.ManagedPeer.RegisterNativeMembers(...) at example.ManagedType.<clinit>(ManagedType.java:15) Root cause: after #1441, JniRuntime.JniTypeManager.GetType() dispatches through GetTypeForSimpleReference (singular), not GetTypesForSimpleReference (plural). The previous sample rewrite only overrode the plural method, so app types like example/ManagedType were never resolved (the base ReflectionJniTypeManager's GetTypeForSimpleReference only knows built-in types), and ManagedPeer registration threw before it could register the type. Fix: override GetTypeForSimpleReference (singular) in both NativeAOT sample type managers to resolve the sample's own managed types, falling back to the base for built-ins. Registration and the reverse Type->JNI mapping continue to be handled by the reflection base (the pre-#1441 behavior). The override carries the same [return: DynamicallyAccessedMembers(...)] as the base to satisfy IL2093. ### Address review: drop unreachable null guard in FromAndroid sample `typeMappings` is assigned in its field initializer and never set to null, so the `if (typeMappings == null) yield break;` guard in CreateSimpleReferencesEnumerator was unreachable dead code. Remove it. ### Document why the NativeAOT sample trim/AOT suppressions are acceptable Add a class-level comment to both NativeAOT sample type managers explaining the rationale for the [UnconditionalSuppressMessage] IL2026/IL3050 suppressions: - These are *samples*, not product code. .NET for Android (what we ship) does not pair ReflectionJniTypeManager with NativeAOT, so it isn't worth the effort to make these samples fully trim/AOT-clean right now. - The reflection paths were always trim/AOT-unsafe. Before #1441 the equivalent suppressions lived inside JniTypeManager itself (justified "NotUsedInAndroid"); #1441 simply moved that responsibility to callers via [RequiresDynamicCode]/[RequiresUnreferencedCode]. ### Reword NativeAOT sample suppression justifications to describe why it's safe The previous IL2026/IL3050 justifications ("does not require unreferenced code / runtime code generation") read as the opposite of reality, since ReflectionJniTypeManager is exactly [RequiresUnreferencedCode]/[RequiresDynamicCode]. Reword to describe why the suppression is correct for this sample: - IL2026: the assembly is rooted via TrimmerRootAssembly and the reflected registration members are preserved by the [DynamicallyAccessedMembers] annotations on the RegisterNativeMembers(Type) -> FindAndCallRegisterMethod path. - IL3050: registration uses CreateDelegate on compile-time-known static methods (no MakeGenericType / expression compilation), so no runtime codegen is required. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent a2159d7 commit 6820a9c

5 files changed

Lines changed: 69 additions & 269 deletions

File tree

samples/Hello-NativeAOTFromAndroid/NativeAotTypeManager.cs

Lines changed: 31 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,22 @@
44

55
namespace Java.Interop.Samples.NativeAotFromAndroid;
66

7-
partial class NativeAotTypeManager : JniRuntime.JniTypeManager {
8-
9-
internal const DynamicallyAccessedMemberTypes Methods = DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods;
10-
internal const DynamicallyAccessedMemberTypes MethodsAndPrivateNested = Methods | DynamicallyAccessedMemberTypes.NonPublicNestedTypes;
11-
internal const DynamicallyAccessedMemberTypes MethodsConstructors = MethodsAndPrivateNested | DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors;
7+
// This sample derives from the reflection-based JniRuntime.ReflectionJniTypeManager, which is
8+
// annotated [RequiresDynamicCode]/[RequiresUnreferencedCode], so the constructor below suppresses
9+
// the resulting IL2026/IL3050 trim/AOT warnings.
10+
//
11+
// Suppressing here is intentional and good enough: these NativeAOT projects are *samples*, not
12+
// product code. .NET for Android (what we actually ship) does not pair ReflectionJniTypeManager
13+
// with NativeAOT, so it isn't worth the effort to make these samples fully trim/AOT-clean right now.
14+
// The reflection paths were always trim/AOT-unsafe: before dotnet/java-interop#1441 the equivalent
15+
// suppressions lived (buried) inside JniTypeManager itself, justified "NotUsedInAndroid"; #1441 just
16+
// moved that responsibility to callers via [RequiresDynamicCode]/[RequiresUnreferencedCode].
17+
partial class NativeAotTypeManager : JniRuntime.ReflectionJniTypeManager {
18+
19+
const DynamicallyAccessedMemberTypes MethodsConstructors =
20+
DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods |
21+
DynamicallyAccessedMemberTypes.NonPublicNestedTypes |
22+
DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors;
1223

1324
Dictionary<string, Type> typeMappings = new () {
1425
["android/app/Activity"] = typeof (Android.App.Activity),
@@ -20,136 +31,41 @@ partial class NativeAotTypeManager : JniRuntime.JniTypeManager {
2031
["my/MainActivity"] = typeof (MainActivity),
2132
};
2233

23-
public override void RegisterNativeMembers (
24-
JniType nativeClass,
25-
[DynamicallyAccessedMembers (MethodsAndPrivateNested)]
26-
Type type,
27-
ReadOnlySpan<char> methods)
34+
[UnconditionalSuppressMessage ("Trimming", "IL2026", Justification = "Sample only (see class comment): this assembly is rooted via TrimmerRootAssembly and the members reflected over during registration are preserved by the [DynamicallyAccessedMembers] annotations on the RegisterNativeMembers(Type) -> FindAndCallRegisterMethod path, so trimming does not remove what reflection needs.")]
35+
[UnconditionalSuppressMessage ("AOT", "IL3050", Justification = "Sample only (see class comment): built-in member registration calls CreateDelegate on compile-time-known static methods (no MakeGenericType / expression compilation), so no runtime code generation is required.")]
36+
public NativeAotTypeManager ()
2837
{
29-
if (TryRegisterBuiltInNativeMembers (nativeClass, nativeClass.Name, methods))
30-
return;
31-
if (!methods.IsEmpty)
32-
throw new NotSupportedException ($"Could not register native members for type '{type.FullName}'.");
3338
}
3439

35-
[Obsolete ("Use RegisterNativeMembers(JniType, Type, ReadOnlySpan<char>)")]
36-
public override void RegisterNativeMembers (
37-
JniType nativeClass,
38-
[DynamicallyAccessedMembers (MethodsAndPrivateNested)]
39-
Type type,
40-
string? methods)
40+
// GetType() dispatches through GetTypeForSimpleReference (singular), so the sample's own type
41+
// map has to be applied here; the base ReflectionJniTypeManager only knows the built-in types.
42+
[return: DynamicallyAccessedMembers (MethodsConstructors)]
43+
protected override Type? GetTypeForSimpleReference (string jniSimpleReference)
4144
{
42-
RegisterNativeMembers (nativeClass, type, methods.AsSpan ());
45+
if (typeMappings.TryGetValue (jniSimpleReference, out var target))
46+
return target;
47+
return base.GetTypeForSimpleReference (jniSimpleReference);
4348
}
4449

4550
protected override IEnumerable<Type> GetTypesForSimpleReference (string jniSimpleReference)
4651
{
47-
var target = GetTypeForSimpleReference (jniSimpleReference);
48-
if (target != null)
52+
if (typeMappings.TryGetValue (jniSimpleReference, out var target))
4953
yield return target;
50-
}
51-
52-
protected override string? GetSimpleReference (Type type)
53-
{
54-
return GetSimpleReferences (type).FirstOrDefault ();
55-
}
56-
57-
[return: DynamicallyAccessedMembers (MethodsConstructors)]
58-
protected override Type? GetTypeForSimpleReference (string jniSimpleReference)
59-
{
60-
return jniSimpleReference switch {
61-
"V" => typeof (void),
62-
"Z" => typeof (bool),
63-
"java/lang/Boolean" => typeof (bool?),
64-
"B" => typeof (sbyte),
65-
"java/lang/Byte" => typeof (sbyte?),
66-
"C" => typeof (char),
67-
"java/lang/Character" => typeof (char?),
68-
"S" => typeof (short),
69-
"java/lang/Short" => typeof (short?),
70-
"I" => typeof (int),
71-
"java/lang/Integer" => typeof (int?),
72-
"J" => typeof (long),
73-
"java/lang/Long" => typeof (long?),
74-
"F" => typeof (float),
75-
"java/lang/Float" => typeof (float?),
76-
"D" => typeof (double),
77-
"java/lang/Double" => typeof (double?),
78-
"android/app/Activity" => typeof (Android.App.Activity),
79-
"android/content/Context" => typeof (Android.Content.Context),
80-
"android/content/ContextWrapper" => typeof (Android.Content.ContextWrapper),
81-
"android/os/BaseBundle" => typeof (Android.OS.BaseBundle),
82-
"android/os/Bundle" => typeof (Android.OS.Bundle),
83-
"android/view/ContextThemeWrapper" => typeof (Android.View.ContextThemeWrapper),
84-
"my/MainActivity" => typeof (MainActivity),
85-
_ => null,
86-
};
54+
foreach (var t in base.GetTypesForSimpleReference (jniSimpleReference))
55+
yield return t;
8756
}
8857

8958
protected override IEnumerable<string> GetSimpleReferences (Type type)
9059
{
91-
return CreateSimpleReferencesEnumerator (type);
60+
return base.GetSimpleReferences (type)
61+
.Concat (CreateSimpleReferencesEnumerator (type));
9262
}
9363

9464
IEnumerable<string> CreateSimpleReferencesEnumerator (Type type)
9565
{
96-
if (typeMappings == null)
97-
yield break;
9866
foreach (var e in typeMappings) {
9967
if (e.Value == type)
10068
yield return e.Key;
10169
}
10270
}
103-
104-
public override IEnumerable<Type> GetTypes (JniTypeSignature typeSignature)
105-
{
106-
if (!typeSignature.IsValid || typeSignature.ArrayRank != 0 || typeSignature.SimpleReference == null)
107-
return [];
108-
return GetTypesForSimpleReference (typeSignature.SimpleReference);
109-
}
110-
111-
public override IEnumerable<JniRuntime.JniTypeManager.ReflectionConstructibleType> GetReflectionConstructibleTypes (JniTypeSignature typeSignature)
112-
{
113-
if (!typeSignature.IsValid || typeSignature.ArrayRank != 0 || typeSignature.SimpleReference == null)
114-
yield break;
115-
var target = GetTypeForSimpleReference (typeSignature.SimpleReference);
116-
if (target != null)
117-
yield return new JniRuntime.JniTypeManager.ReflectionConstructibleType (target);
118-
}
119-
120-
protected override JniTypeSignature GetTypeSignatureCore (Type type)
121-
{
122-
var simpleReference = GetSimpleReferences (type).FirstOrDefault ();
123-
return simpleReference == null ? default : new JniTypeSignature (simpleReference, 0, false);
124-
}
125-
126-
protected override IEnumerable<JniTypeSignature> GetTypeSignaturesCore (Type type)
127-
{
128-
var signature = GetTypeSignatureCore (type);
129-
if (signature.IsValid)
130-
yield return signature;
131-
}
132-
133-
[return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
134-
protected override Type? GetInvokerTypeCore (
135-
[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
136-
Type type)
137-
{
138-
return null;
139-
}
140-
141-
protected override IReadOnlyList<string>? GetStaticMethodFallbackTypesCore (string jniSimpleReference)
142-
{
143-
return null;
144-
}
145-
146-
protected override string? GetReplacementTypeCore (string jniSimpleReference)
147-
{
148-
return null;
149-
}
150-
151-
protected override JniRuntime.ReplacementMethodInfo? GetReplacementMethodInfoCore (string jniSourceType, string jniMethodName, string jniMethodSignature)
152-
{
153-
return null;
154-
}
15571
}
Lines changed: 37 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -1,148 +1,49 @@
1-
using Java.Interop;
21
using System.Diagnostics.CodeAnalysis;
32

4-
namespace Hello_NativeAOTFromJNI;
5-
6-
class NativeAotTypeManager : JniRuntime.JniTypeManager {
7-
internal const DynamicallyAccessedMemberTypes Methods = DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods;
8-
internal const DynamicallyAccessedMemberTypes MethodsAndPrivateNested = Methods | DynamicallyAccessedMemberTypes.NonPublicNestedTypes;
9-
internal const DynamicallyAccessedMemberTypes MethodsConstructors = MethodsAndPrivateNested | DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors;
3+
using Java.Interop;
104

11-
protected override IEnumerable<Type> GetTypesForSimpleReference (string jniSimpleReference)
12-
{
13-
var target = GetTypeForSimpleReference (jniSimpleReference);
14-
if (target != null)
15-
yield return target;
16-
}
5+
namespace Hello_NativeAOTFromJNI;
176

7+
// This sample derives from the reflection-based JniRuntime.ReflectionJniTypeManager, which is
8+
// annotated [RequiresDynamicCode]/[RequiresUnreferencedCode], so the constructor below suppresses
9+
// the resulting IL2026/IL3050 trim/AOT warnings.
10+
//
11+
// Suppressing here is intentional and good enough: these NativeAOT projects are *samples*, not
12+
// product code. .NET for Android (what we actually ship) does not pair ReflectionJniTypeManager
13+
// with NativeAOT, so it isn't worth the effort to make these samples fully trim/AOT-clean right now.
14+
// The reflection paths were always trim/AOT-unsafe: before dotnet/java-interop#1441 the equivalent
15+
// suppressions lived (buried) inside JniTypeManager itself, justified "NotUsedInAndroid"; #1441 just
16+
// moved that responsibility to callers via [RequiresDynamicCode]/[RequiresUnreferencedCode].
17+
class NativeAotTypeManager : JniRuntime.ReflectionJniTypeManager {
18+
19+
const DynamicallyAccessedMemberTypes MethodsConstructors =
20+
DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods |
21+
DynamicallyAccessedMemberTypes.NonPublicNestedTypes |
22+
DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors;
23+
24+
[UnconditionalSuppressMessage ("Trimming", "IL2026", Justification = "Sample only (see class comment): this assembly is rooted via TrimmerRootAssembly and the members reflected over during registration are preserved by the [DynamicallyAccessedMembers] annotations on the RegisterNativeMembers(Type) -> FindAndCallRegisterMethod path, so trimming does not remove what reflection needs.")]
25+
[UnconditionalSuppressMessage ("AOT", "IL3050", Justification = "Sample only (see class comment): built-in member registration calls CreateDelegate on compile-time-known static methods (no MakeGenericType / expression compilation), so no runtime code generation is required.")]
26+
public NativeAotTypeManager ()
27+
{
28+
}
29+
30+
// The base ReflectionJniTypeManager resolves built-in types (primitives, java/lang/String,
31+
// JavaProxyObject, ...) and handles registration and the reverse Type->JNI mapping (via the
32+
// [JniTypeSignature] attribute) for us. We only need to teach it about this sample's own
33+
// managed types.
1834
[return: DynamicallyAccessedMembers (MethodsConstructors)]
1935
protected override Type? GetTypeForSimpleReference (string jniSimpleReference)
2036
{
21-
return jniSimpleReference switch {
22-
"V" => typeof (void),
23-
"Z" => typeof (bool),
24-
"java/lang/Boolean" => typeof (bool?),
25-
"B" => typeof (sbyte),
26-
"java/lang/Byte" => typeof (sbyte?),
27-
"C" => typeof (char),
28-
"java/lang/Character" => typeof (char?),
29-
"S" => typeof (short),
30-
"java/lang/Short" => typeof (short?),
31-
"I" => typeof (int),
32-
"java/lang/Integer" => typeof (int?),
33-
"J" => typeof (long),
34-
"java/lang/Long" => typeof (long?),
35-
"F" => typeof (float),
36-
"java/lang/Float" => typeof (float?),
37-
"D" => typeof (double),
38-
"java/lang/Double" => typeof (double?),
39-
Example.ManagedType.JniTypeName => typeof (Example.ManagedType),
40-
"java/lang/Object" => typeof (Java.Lang.Object),
41-
"java/lang/String" => typeof (Java.Lang.String),
42-
_ => null,
43-
};
44-
}
45-
46-
public override IEnumerable<Type> GetTypes (JniTypeSignature typeSignature)
47-
{
48-
if (!typeSignature.IsValid || typeSignature.ArrayRank != 0 || typeSignature.SimpleReference == null)
49-
return [];
50-
return GetTypesForSimpleReference (typeSignature.SimpleReference);
51-
}
52-
53-
public override IEnumerable<JniRuntime.JniTypeManager.ReflectionConstructibleType> GetReflectionConstructibleTypes (JniTypeSignature typeSignature)
54-
{
55-
if (!typeSignature.IsValid || typeSignature.ArrayRank != 0 || typeSignature.SimpleReference == null)
56-
yield break;
57-
var target = GetTypeForSimpleReference (typeSignature.SimpleReference);
58-
if (target != null)
59-
yield return new JniRuntime.JniTypeManager.ReflectionConstructibleType (target);
60-
}
61-
62-
protected override IEnumerable<string> GetSimpleReferences (Type type)
63-
{
64-
return CreateSimpleReferencesEnumerator (type);
65-
}
66-
67-
IEnumerable<string> CreateSimpleReferencesEnumerator (Type type)
68-
{
69-
if (type == typeof (Example.ManagedType))
70-
yield return Example.ManagedType.JniTypeName;
71-
else if (type == typeof (Java.Lang.Object))
72-
yield return "java/lang/Object";
73-
else if (type == typeof (Java.Lang.String))
74-
yield return "java/lang/String";
75-
}
76-
77-
protected override string? GetSimpleReference (Type type)
78-
{
79-
return GetSimpleReferences (type).FirstOrDefault ();
37+
if (jniSimpleReference == Example.ManagedType.JniTypeName)
38+
return typeof (Example.ManagedType);
39+
return base.GetTypeForSimpleReference (jniSimpleReference);
8040
}
8141

82-
protected override JniTypeSignature GetTypeSignatureCore (Type type)
83-
{
84-
var simpleReference = GetSimpleReference (type);
85-
return simpleReference == null ? default : new JniTypeSignature (simpleReference, 0, false);
86-
}
87-
88-
protected override IEnumerable<JniTypeSignature> GetTypeSignaturesCore (Type type)
89-
{
90-
var signature = GetTypeSignatureCore (type);
91-
if (signature.IsValid)
92-
yield return signature;
93-
}
94-
95-
[return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
96-
protected override Type? GetInvokerTypeCore (
97-
[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
98-
Type type)
99-
{
100-
return null;
101-
}
102-
103-
protected override IReadOnlyList<string>? GetStaticMethodFallbackTypesCore (string jniSimpleReference)
104-
{
105-
return null;
106-
}
107-
108-
protected override string? GetReplacementTypeCore (string jniSimpleReference)
109-
{
110-
return null;
111-
}
112-
113-
protected override JniRuntime.ReplacementMethodInfo? GetReplacementMethodInfoCore (string jniSourceType, string jniMethodName, string jniMethodSignature)
114-
{
115-
return null;
116-
}
117-
118-
public override void RegisterNativeMembers (
119-
JniType nativeClass,
120-
[DynamicallyAccessedMembers (MethodsAndPrivateNested)]
121-
Type type,
122-
ReadOnlySpan<char> methods)
123-
{
124-
if (TryRegisterBuiltInNativeMembers (nativeClass, nativeClass.Name, methods))
125-
return;
126-
127-
if (type != typeof (Example.ManagedType)) {
128-
if (!methods.IsEmpty)
129-
throw new NotSupportedException ($"Could not register native members for type '{type.FullName}'.");
130-
return;
131-
}
132-
133-
var registrations = new List<JniNativeMethodRegistration> ();
134-
Example.ManagedType.RegisterNativeMembers (new JniNativeMethodRegistrationArguments (registrations, null));
135-
if (registrations.Count > 0)
136-
nativeClass.RegisterNativeMethods (registrations.ToArray ());
137-
}
138-
139-
[Obsolete ("Use RegisterNativeMembers(JniType, Type, ReadOnlySpan<char>)")]
140-
public override void RegisterNativeMembers (
141-
JniType nativeClass,
142-
[DynamicallyAccessedMembers (MethodsAndPrivateNested)]
143-
Type type,
144-
string? methods)
42+
protected override IEnumerable<Type> GetTypesForSimpleReference (string jniSimpleReference)
14543
{
146-
RegisterNativeMembers (nativeClass, type, methods.AsSpan ());
44+
if (jniSimpleReference == Example.ManagedType.JniTypeName)
45+
yield return typeof (Example.ManagedType);
46+
foreach (var t in base.GetTypesForSimpleReference (jniSimpleReference))
47+
yield return t;
14748
}
14849
}

src/Java.Interop/Java.Interop/JavaProxyObject.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ sealed class JavaProxyObject : JavaObject, IEquatable<JavaProxyObject>
1616
static readonly ConditionalWeakTable<object, JavaProxyObject> CachedValues = new ConditionalWeakTable<object, JavaProxyObject> ();
1717

1818
[JniAddNativeMethodRegistrationAttribute]
19-
internal static void RegisterNativeMembers (JniNativeMethodRegistrationArguments args)
19+
static void RegisterNativeMembers (JniNativeMethodRegistrationArguments args)
2020
{
2121
args.Registrations.Add (new JniNativeMethodRegistration ("equals", "(Ljava/lang/Object;)Z", new EqualsMarshalMethod (Equals)));
2222
args.Registrations.Add (new JniNativeMethodRegistration ("hashCode", "()I", new GetHashCodeMarshalMethod (GetHashCode)));

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

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -253,22 +253,6 @@ static JniTypeSignature GetBuiltInTypeSignature (Type type)
253253
};
254254
}
255255

256-
protected static bool TryRegisterBuiltInNativeMembers (
257-
JniType nativeClass,
258-
string jniSimpleReference,
259-
ReadOnlySpan<char> methods)
260-
{
261-
if (jniSimpleReference == JavaProxyObject.JniTypeName) {
262-
var registrations = new List<JniNativeMethodRegistration> ();
263-
JavaProxyObject.RegisterNativeMembers (new JniNativeMethodRegistrationArguments (registrations, null));
264-
if (registrations.Count > 0)
265-
nativeClass.RegisterNativeMethods (registrations.ToArray ());
266-
return true;
267-
}
268-
269-
return jniSimpleReference == JavaProxyThrowable.JniTypeName && methods.IsEmpty;
270-
}
271-
272256
/// <include file="../Documentation/Java.Interop/JniRuntime.JniTypeManager.xml" path="/docs/member[@name='M:GetInvokerType']/*" />
273257
[return: DynamicallyAccessedMembers (Constructors)]
274258
public Type? GetInvokerType (

0 commit comments

Comments
 (0)