Commit f234612
[native] Use full marshal method signature when a method is overloaded (#10433)
Fixes: #10417
Context: https://docs.oracle.com/en/java/javase/17/docs/specs/jni/design.html#resolving-native-method-names
Context: #10417 (comment)
Whenever we generate marshal methods code for overloaded Java methods, we must be sure to use full native signature
instead of the short form, even if one of the overloads doesn't have parameters.
Failure to do so results in hard-to fix subtle bugs like in case of #10417. In this instance, we had a
class (`Android.Runtime.InputStreamAdapter`) with 3 method overloads:
* `public override int Read ();`
* `public override int Read (byte[] bytes)`
* `public override int Read (byte[] bytes, int offset, int length)`
The sample application failed to load an image using a Glide decoder, which called the `Read (byte[], int, int)`
overload above. It was puzzling, because the Java code clearly called the right native function and yet, it ended up in
a marshal method wrapper for the `Read ()` overload.
The cause became apparent when I checked names of the generated native functions. All of them were valid and yet the
whole was subtly broken: the `Read ()` overload used a (valid) "short form" native symbol name, which omits the part
that encodes parameter types in the symbol name. The reason for this was that the generator code saw there were no
parameters and so it output the short form, because it is the **first** symbol name looked up by JavaVM - thus it seemed
to be a good optimization at the time of implementing the marshal methods generator.
The problems began when **both** overloads were used somewhere in the application code and the `Read()` overload
was **always** found first, since it used the short form name, and thus Java never got to looking up the other overload!
Then it proceeded to call the parameter-less overload, which caused sort-of worked (as in it didn't crash) it it was far
from correct.
The fix implemented here is to always emit the `__` native symbol suffix for any overloaded methods that have no
parameters.
* Added on-device test to repro issue.
These tests should return 1024, but fail with `$(AndroidEnableMarshalMethods)`:
08-21 11:53:13.738 16263 16289 I NUnit : InputStreamAdapter_Read_bytes
08-21 11:53:13.738 16263 16289 D StreamTest: StreamTest.InputStreamAdapter_Read_bytes, underlying stream type: mono.android.runtime.InputStreamAdapter
08-21 11:53:13.745 16263 16289 E NUnit : [FAIL]
08-21 11:53:13.746 16263 16289 E NUnit : : Expected: 1024
08-21 11:53:13.746 16263 16289 E NUnit : But was: 0
08-21 11:53:13.746 16263 16289 E NUnit : at System.IOTests.StreamTest.InputStreamAdapter_Read_bytes()
If `0` is returned, it means that `read()` was called instead of the `read(...)` overload
which reproduces the issue.
This test appears to pass with the above changes.
Co-authored-by: Jonathan Peppers <[email protected]>1 parent 988371e commit f234612
File tree
4 files changed
+73
-2
lines changed- src/Xamarin.Android.Build.Tasks/Utilities
- tests/Mono.Android-Tests/Mono.Android-Tests
- System.IO
- java/net/dot/android/test
4 files changed
+73
-2
lines changedLines changed: 7 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
346 | 346 | | |
347 | 347 | | |
348 | 348 | | |
349 | | - | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
350 | 353 | | |
351 | | - | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
352 | 357 | | |
353 | 358 | | |
354 | 359 | | |
| |||
Lines changed: 1 addition & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
105 | 105 | | |
106 | 106 | | |
107 | 107 | | |
| 108 | + | |
108 | 109 | | |
109 | 110 | | |
110 | 111 | | |
| |||
Lines changed: 34 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 | + | |
| 34 | + | |
Lines changed: 31 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 | + | |
0 commit comments