Commit dd3c1d0
authored
[Java.Interop] Add
Context: 78d5937
Context: be6cc8f
Context: dotnet/android@7a772f0
Context: dotnet/android#9716
Context: dotnet/android@694e975
dotnet/android@7a772f03 added the beginnings of a NativeAOT sample
to dotnet/android which built a ".NET for Android" app using
NativeAOT, which "rhymed with" the `Hello-NativeAOTFromAndroid`
sample in 78d5937.
Further work on the sample showed that it was lacking support for
`Android.App.Application` subclasses:
[Application (Name = "my.MainApplication")]
public class MainApplication : Application
{
public MainApplication (IntPtr handle, JniHandleOwnership transfer)
: base (handle, transfer)
{
}
public override void OnCreate ()
{
base.OnCreate ();
}
}
dotnet/android#9716 began fixing that oversight, but in the process
was triggering a stack overflow because when it needed to create a
"proxy" peer around the `my.MainApplication` Java type, which
subclassed `android.app.Application`. Instead of creating an instance
of the expected `MainApplication` C# type, it instead created an
instance of `Android.App.Application`. This was visible from the logs:
Created PeerReference=0x2d06/G IdentityHashCode=0x8edcb07 Instance=0x957d2a Instance.Type=Android.App.Application, Java.Type=my/MainApplication
Note that `Instance.Type` is `Android.App.Application`, not the
in-sample `MainApplication` C# type.
Because the runtime type was `Android.App.Application`, when we later
attempted to dispatch the `Application.OnCreate()` override, this
resulted in a *virtual* invocation of the Java `Application.onCreate()`
method instead of a *non-virtual* invocation of
`Application.onCreate()`. This virtual invocation was the root of a
recursive loop which eventually resulted in a stack overflow.
The fix in dotnet/android@694e975e was to fix
`NativeAotTypeManager.CreatePeer()` so that it properly checked for a
binding of the *runtime type* of the Java instance *before* using the
"fallback" type provided to `Object.GetObject<T>()` in the
`Application.n_OnCreate()` method:
partial class Application {
static void n_OnCreate (IntPtr jnienv, IntPtr native__this)
{
// …
var __this = global::Java.Lang.Object.GetObject<
Android.App.Application // This is the "fallback" NativeAotTypeManager
> (jnienv, native__this, JniHandleOwnership.DoNotTransfer)!;
__this.OnCreate ();
// …
}
}
All well and good.
The problem is that `NativeAotTypeManager` in dotnet/android needs to
support *both* dotnet/java-interop "activation constructors" with a
signature of `(ref JniObjectReference, JniObjectReferenceOptions)`,
*and* the .NET for Android signature of `(IntPtr, JniHandleOwnership)`.
Trying to support both constructors resulted in the need to copy
*all* of `JniRuntime.JniValueManager.CreatePeer()` *and dependencies*,
which felt a bit excessive.
Add a new `JniRuntime.JniValueManager.TryCreatePeer()` method, which
will invoke the activation constructor to create an `IJavaPeerable`:
partial class JniRuntime {
partial class JniValueManager {
protected virtual IJavaPeerable? TryCreatePeer (
ref JniObjectReference reference,
JniObjectReferenceOptions options,
Type targetType);
}
}
If the activation constructor is not found, then `TryCreatePeer()`
shall return `null`, allowing `CreatePeerInstance()` to try for
a base type or, ultimately, the fallback type.
This will allow a future dotnet/android to *remove*
`NativeAotTypeManager.CreatePeer()` and its dependencies entirely,
and instead do:
partial class NativeAotTypeManager {
const BindingFlags ActivationConstructorBindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
static readonly Type[] XAConstructorSignature = new Type [] { typeof (IntPtr), typeof (JniHandleOwnership) };
protected override IJavaPeerable TryCreatePeer (ref JniObjectReference reference, JniObjectReferenceOptions options, Type type)
{
var c = type.GetConstructor (ActivationConstructorBindingFlags, null, XAConstructorSignature, null);
if (c != null) {
var args = new object[] {
reference.Handle,
JniHandleOwnership.DoNotTransfer,
};
var p = (IJavaPeerable) c.Invoke (args);
JniObjectReference.Dispose (ref reference, options);
return p;
}
return base.TryCreatePeer (ref reference, options, type);
}
}
vastly reducing the code it needs to care about.
Additionally, add `JniRuntime.JniTypeManager.GetInvokerType()`:
partial class JniRuntime {
partial class JniTypeManager {
public Type? GetInvokerType (Type type);
protected virtual Type? GetInvokerTypeCore (Type type);
}
}
`GetInvokerType()` calls `GetInvokerTypeCore()`, allowing flexibility
for subclasses to lookup the "string-based" the .NET for Android -style
Invoker types that JavaInterop1-style bindings used before commit
be6cc8f.JniRuntime.JniValueManager.TryCreatePeer() (#1301)1 parent fb642c9 commit dd3c1d0
File tree
5 files changed
+146
-57
lines changed- src/Java.Interop
- Documentation/Java.Interop
- Java.Interop
- tests/Java.Interop-Tests/Java.Interop
5 files changed
+146
-57
lines changedLines changed: 28 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
Lines changed: 45 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
79 | 79 | | |
80 | 80 | | |
81 | 81 | | |
| 82 | + | |
82 | 83 | | |
83 | 84 | | |
| 85 | + | |
84 | 86 | | |
85 | 87 | | |
86 | 88 | | |
| |||
385 | 387 | | |
386 | 388 | | |
387 | 389 | | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
388 | 433 | | |
389 | 434 | | |
390 | 435 | | |
| |||
Lines changed: 37 additions & 57 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
336 | 336 | | |
337 | 337 | | |
338 | 338 | | |
339 | | - | |
340 | | - | |
| 339 | + | |
| 340 | + | |
341 | 341 | | |
342 | 342 | | |
343 | 343 | | |
344 | | - | |
345 | | - | |
346 | | - | |
347 | | - | |
348 | | - | |
349 | | - | |
350 | | - | |
351 | | - | |
352 | | - | |
353 | | - | |
354 | | - | |
355 | | - | |
| 344 | + | |
| 345 | + | |
356 | 346 | | |
357 | 347 | | |
358 | | - | |
359 | | - | |
360 | | - | |
| 348 | + | |
361 | 349 | | |
362 | 350 | | |
363 | | - | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
364 | 354 | | |
365 | 355 | | |
366 | 356 | | |
| |||
373 | 363 | | |
374 | 364 | | |
375 | 365 | | |
376 | | - | |
| 366 | + | |
377 | 367 | | |
378 | | - | |
| 368 | + | |
379 | 369 | | |
380 | | - | |
| 370 | + | |
381 | 371 | | |
382 | 372 | | |
383 | 373 | | |
| |||
391 | 381 | | |
392 | 382 | | |
393 | 383 | | |
394 | | - | |
| 384 | + | |
395 | 385 | | |
396 | 386 | | |
397 | | - | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
398 | 390 | | |
399 | 391 | | |
400 | 392 | | |
401 | | - | |
402 | | - | |
403 | | - | |
404 | | - | |
405 | | - | |
406 | | - | |
407 | | - | |
408 | | - | |
409 | | - | |
| 393 | + | |
| 394 | + | |
410 | 395 | | |
411 | 396 | | |
412 | | - | |
413 | | - | |
414 | | - | |
415 | | - | |
416 | | - | |
417 | | - | |
418 | | - | |
419 | | - | |
420 | | - | |
421 | | - | |
422 | | - | |
423 | | - | |
424 | | - | |
425 | | - | |
426 | | - | |
427 | | - | |
428 | | - | |
429 | | - | |
430 | | - | |
431 | | - | |
432 | | - | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
433 | 400 | | |
434 | | - | |
435 | | - | |
436 | | - | |
437 | 401 | | |
438 | | - | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
439 | 419 | | |
440 | 420 | | |
441 | 421 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
| 6 | + | |
| 7 | + | |
6 | 8 | | |
7 | 9 | | |
| 10 | + | |
8 | 11 | | |
9 | 12 | | |
10 | 13 | | |
Lines changed: 33 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
0 commit comments