Commit 4787e01
authored
[Java.Base-Tests] Test Java-to-Managed invocations for Java.Base (#975)
Commit bc5bcf4 (Desktop `Java.Base` binding) had a TODO:
> ~~ TODO: Marshal Methods ~~
>
> Marshal methods are currently skipped. Java-to-managed invocations
> are not currently supported.
No marshal methods means no facility for Java-to-managed invocations.
Add a new `tests/Java.Base-Tests` unit test assembly, and test
Java-to-managed invocations.
This requires touching and updating ~everything. 😅
Update `Java.Interop.dll` to contain a new
`Java.Interop.JniMethodSignatureAttribute` custom attribute.
Update `generator` to begin emitting `[JniMethodSignature]` on bound
methods. This is necessary so that `jcw-gen` knows the JNI method
signature of Java methods to emit. As part of this, *remove* the
`JniTypeSignatureAttr` type added in bc5bcf4; trying to follow the
`JniTypeSignatureAttr` pattern for `JniMethodSignatureAttr` would
make for more intrusive code changes. Instead, "re-use" the existing
`RegisterAttr` type, adding a `RegisterAttr.MemberType` property so
that we can select between Android `[Register]` output vs. "Desktop"
`[JniTypeSignature]` and `[JniMethodSignature]` output. This in turn
requires updating many `generator-Tests` artifacts.
Update `Java.Interop.Tools.JavaCallableWrappers` to look for
`Java.Interop.JniTypeSignatureAttribute` and
`Java.Interop.JniMethodSignatureAttribute`. This allows
`jcw-gen Java.Base-Tests.dll` to generate Java Callable Wrappers for
`Java.BaseTests.MyRunnable`.
Update `Java.Interop.Export.dll` so that `MarshalMemberBuilder`
doesn't use `Expression.GetActionType()` or
`Expression.GetFuncType()`, as .NET doesn't support the use of
generic types in [`Marshal.GetFunctionPointerForDelegate()`][0].
Instead, we need to use `System.Reflection.Emit` to define our own
custom delegate types.
~~ Comparison with Android ~~
Android bindings (both Classic Xamarin.Android and
.NET SDK for Android) use `generator`-emitted "connector methods"
which are specified in the `[Register]` attribute (see also 99897b2):
namespace Java.Lang {
[Register ("java/lang/Object" DoNotGenerateAcw=true)]
partial class Object {
[Register ("equals", "(Ljava/lang/Object;)Z", "GetEquals_Ljava_lang_Object_Handler")]
public virtual unsafe bool Equals (Java.Lang.Object? obj)
=> …
static Delegate GetEquals_Ljava_lang_Object_Handler()
=> JNINativeWrapper.CreateDelegate((_JniMarshal_PPL_Z) n_Equals_Ljava_lang_Object_);
static bool n_Equals_Ljava_lang_Object_ (IntPtr jnienv, IntPtr native__this, IntPtr native_obj)
=> …
}
}
`jcw-gen` emits the "connector method" into the resulting
Java Callable Wrappers for appropriate subclasses:
String __md_methods =
"n_equals:(Ljava/lang/Object;)Z:GetEquals_Ljava_lang_Object_Handler\n";
At runtime, `AndroidTypeManager.RegisterNativeMembers()` will lookup
`Object.GetEquals_Ljava_lang_Object_Handler()` and invoke it.
The returned `Delegate` instance is provided to
`JNIEnv::RegisterNatives()`.
The problem with this approach is that it's inflexible: there is no
way to participate in the "connector method" infrastructure to alter
marshaling behavior. If you need custom behavior, e.g.
`Android.Graphics.Color` customizations, you need to update
`generator` and rebuild the binding assemblies.
(This has been "fine" for the past 10+ years, so this hasn't been a
deal breaker.)
For `Java.Base`, @jonpryor wants to support the custom marshaling
infrastructure introduced in 77a6bf8. This would allow types to
participate in JNI marshal method ("connector method") generation
*at runtime*, allowing specialization based on the current set of
types and assemblies.
This means we *don't* need to specify a "connector method" in
`[JniMethodSignatureAttribute]`, nor generate them.
namespace Java.Lang {
[JniTypeSignatureAttribute("java/lang/Object", GenerateJavaPeer=false)]
partial class Object {
[JniMethodSignatureAttribute("equals", "(Ljava/lang/Object;)Z")]
public virtual unsafe bool Equals (Java.Lang.Object? obj)
=> …
// No GetEquals_Ljava_lang_Object_Handler()
// No n_Equals_Ljava_lang_Object_()
}
}
This should result in smaller binding assemblies.
The downside is that runtime costs *increase*, significantly.
Instead of looking up and invoking a "connector method", the method
must be *generated* via System.Linq.Expressions expression trees,
then compiled into IL, then JIT'd, all before it can be used.
We have no timing data to indicate how "bad" this overhead will be.
As always, the hope is that `tools/jnimarshalmethod-gen` (176240d)
can be used to get the "best of both worlds": the flexibility of
custom marshalers, without the runtime overhead. But…
* #14
* #616
At this point in time, `jnimarshalmethod-gen` *cannot* work under
.NET 6. This will need to be addressed in order for custom marshalers
to be a useful solution.
`Java.Base` will use "connector method"-less bindings to act as a
"forcing function" in getting `jnimarshalmethod-gen` working in .NET.
[0]: https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.marshal.getfunctionpointerfordelegate?view=net-6.01 parent 5971625 commit 4787e01
File tree
69 files changed
+2464
-201
lines changed- build-tools/automation/templates
- src
- Java.Interop.Export/Java.Interop
- Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers
- Java.Interop.Tools.TypeNameMappings/Java.Interop.Tools.TypeNameMappings
- Java.Interop/Java.Interop
- Java.Runtime.Environment
- Java.Interop
- tests
- Java.Base-Tests
- Java.Base
- java/com/microsoft/java_base_tests
- Java.Interop.Tools.JavaCallableWrappers-Tests/Java.Interop.Tools.JavaCallableWrappers
- TestJVM
- generator-Tests
- Integration-Tests
- Unit-Tests
- CodeGeneratorExpectedResults/JavaInterop1
- expected.ji
- AccessModifiers
- Arrays
- CSharpKeywords
- InterfaceMethodsConflict
- NormalProperties
- StaticMethods
- StaticProperties
- Streams
- tools
- generator
- SourceWriters
- Attributes
- jcw-gen
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
69 files changed
+2464
-201
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
105 | 105 | | |
106 | 106 | | |
107 | 107 | | |
| 108 | + | |
| 109 | + | |
108 | 110 | | |
109 | 111 | | |
110 | 112 | | |
| |||
296 | 298 | | |
297 | 299 | | |
298 | 300 | | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
299 | 305 | | |
300 | 306 | | |
301 | 307 | | |
| |||
346 | 352 | | |
347 | 353 | | |
348 | 354 | | |
| 355 | + | |
349 | 356 | | |
350 | 357 | | |
351 | 358 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
35 | 38 | | |
36 | 39 | | |
37 | 40 | | |
| |||
44 | 47 | | |
45 | 48 | | |
46 | 49 | | |
| 50 | + | |
47 | 51 | | |
48 | 52 | | |
49 | 53 | | |
| |||
123 | 127 | | |
124 | 128 | | |
125 | 129 | | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
126 | 135 | | |
127 | 136 | | |
128 | 137 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
130 | 130 | | |
131 | 131 | | |
132 | 132 | | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
133 | 142 | | |
134 | 143 | | |
135 | 144 | | |
| |||
Large diffs are not rendered by default.
Lines changed: 48 additions & 9 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| 7 | + | |
7 | 8 | | |
8 | 9 | | |
9 | 10 | | |
| |||
241 | 242 | | |
242 | 243 | | |
243 | 244 | | |
244 | | - | |
245 | | - | |
246 | | - | |
247 | | - | |
248 | | - | |
249 | | - | |
250 | | - | |
251 | | - | |
252 | | - | |
253 | 245 | | |
254 | 246 | | |
255 | 247 | | |
| |||
265 | 257 | | |
266 | 258 | | |
267 | 259 | | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
268 | 263 | | |
| 264 | + | |
269 | 265 | | |
270 | 266 | | |
271 | 267 | | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
272 | 310 | | |
| 311 | + | |
273 | 312 | | |
274 | 313 | | |
275 | 314 | | |
| |||
0 commit comments