Skip to content

Commit 07c7300

Browse files
authored
[Java.Interop] Typemap support for JavaObject & [JniTypeSignature] (#1181)
Context: dotnet/android#8543 Context: dotnet/android#8625 Context: dotnet/android#8681 Context: #1168 Context: def5bc0 Context: 005c914 dotnet/android#8543 tested PR #1168, was Totally Green™ -- finding no issues -- and so we merged PR #1168 into 005c914. Enter dotnet/android#8625, which bumps xamarin-android to use def5bc0, which includes 005c914. dotnet/android#8625 contains *failing unit tests* (?!), including `Java.InteropTests.InvokeVirtualFromConstructorTests()`: Java.Lang.LinkageError : net.dot.jni.test.CallVirtualFromConstructorDerived ----> System.NotSupportedException : Could not find System.Type corresponding to Java type JniTypeSignature(TypeName=net/dot/jni/test/CallVirtualFromConstructorDerived ArrayRank=0 Keyword=False) . at Java.Interop.JniEnvironment.StaticMethods.GetStaticMethodID(JniObjectReference , String , String ) at Java.Interop.JniType.GetStaticMethod(String , String ) at Java.Interop.JniPeerMembers.JniStaticMethods.GetMethodInfo(String , String ) at Java.Interop.JniPeerMembers.JniStaticMethods.GetMethodInfo(String ) at Java.Interop.JniPeerMembers.JniStaticMethods.InvokeObjectMethod(String , JniArgumentValue* ) at Java.InteropTests.CallVirtualFromConstructorDerived.NewInstance(Int32 value) at Java.InteropTests.InvokeVirtualFromConstructorTests.ActivationConstructor() at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args) at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object , BindingFlags ) --- End of managed Java.Lang.LinkageError stack trace --- java.lang.NoClassDefFoundError: net.dot.jni.test.CallVirtualFromConstructorDerived at crc643df67da7b13bb6b1.TestInstrumentation_1.n_onStart(Native Method) at crc643df67da7b13bb6b1.TestInstrumentation_1.onStart(TestInstrumentation_1.java:35) at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2189) Caused by: android.runtime.JavaProxyThrowable: [System.NotSupportedException]: Could not find System.Type corresponding to Java type JniTypeSignature(TypeName=net/dot/jni/test/CallVirtualFromConstructorDerived ArrayRank=0 Keyword=False) . at Java.Interop.ManagedPeer.GetTypeFromSignature(Unknown Source:0) at Java.Interop.ManagedPeer.RegisterNativeMembers(Unknown Source:0) at net.dot.jni.ManagedPeer.registerNativeMembers(Native Method) at net.dot.jni.test.CallVirtualFromConstructorDerived.<clinit>(CallVirtualFromConstructorDerived.java:12) ... 3 more --NotSupportedException at Java.Interop.ManagedPeer.GetTypeFromSignature(JniTypeManager , JniTypeSignature , String ) at Java.Interop.ManagedPeer.RegisterNativeMembers(IntPtr jnienv, IntPtr klass, IntPtr n_nativeClass, IntPtr n_methods) :shocked-pikachu-face: (But dotnet/android#8543 was green!) The problem is twofold: 1. 005c914 now requires the presence of typemap entries from e.g. `net.dot.jni.test.CallVirtualFromConstructorDerived` to `Java.InteropTests.CallVirtualFromConstructorDerived`. 2. `Java.Interop.Tools.JavaCallableWrappers` et al doesn't create typemap entries for `Java.Interop.JavaObject` subclasses which have `[JniTypeSignature]`. Consequently, our units tests fail (and apparently weren't *run* on dotnet/android#8543?! Still not sure what happened.) Update typemap generation by adding a new `TypeDefinition.HasJavaPeer()` extension method to replace all the `.IsSubclassOf("Java.Lang.Object")` and similar checks, extending it to also check for `Java.Interop.JavaObject` and `Java.Interop.JavaException` base types. (Continuing to use base type checks is done instead of just relying on implementation of `Java.Interop.IJavaPeerable` as a performance optimization, as there could be *lots* of interface types to check.) Additionally, @jonathanpeppers -- while trying to investigate all this -- ran across a build failure: obj\Debug\net9.0-android\android\src\java\lang\Object.java(7,15): javac.exe error JAVAC0000: error: cyclic inheritance involving Object This suggests that `Java.Interop.Tools.JavaCallableWrappers` was encountering `Java.Interop.JavaObject` -- or some other type which has `[JniTypeSignature("java/lang/Object")]` -- which is why `java/lang/Object.java` was being generated. Audit all `[JniTypeSignature]` attributes, and add `GenerateJavaPeer=false` to all types which should *not* hava a Java Callable Wrapper generated for them. This includes nearly everything within `Java.Interop-Tests.dll`. (We want the typemaps! We *don't* want generated Java source, as we have hand-written Java peer types for those tests.) Add `[JniTypeSignature]` to `GenericHolder<T>`. This type mapping isn't *actually* required, but it *is* used in `JavaVMFixture`, and it confuses people (me!) if things are inconsistent. Additionally, remove `tests/` from the Java-side name, for consistency. ~~ Avoid multiple java/lang/Object bindings ~~ A funny thing happened when in dotnet/android#8681 -- which tested this commit -- when using an intermediate version of this commit: unit tests started crashing! E monodroid-assembly: typemap: unable to load assembly 'Java.Interop-Tests' when looking up managed type corresponding to Java type 'java/lang/Object' What appears to be happening is an Unfortunate Interaction™: 1. `Java.Interop-Tests.dll` contained *multiple bindings* for `java/lang/Object`. e.g. [JniTypeSignature ("java/lang/Object", GenerateJavaPeer=false)] partial class JavaDisposedObject : JavaObject { } 2. The typemap generator has no functionality to "prioritize" one binding vs. another; it's random. As such, there is nothing to cause `Java.Lang.Object, Mono.Android` to be used as the preferred binding for `java/lang/Object`. This meant that when we hit the typemap codepath in .NET Android, we looked for the C# type that corresponded to `java/lang/Object`, found *some random type* from `Java.Interop-Tests`, and… …and then we hit another oddity: that codepath only supported looking for C# types in assemblies which had already been loaded. This was occurring during startup, so `Java.Interop-Tests` had not yet been loaded yet, so it errored out, returned `nullptr`, and later Android just aborts things: F droid.NET_Test: runtime.cc:638] JNI DETECTED ERROR IN APPLICATION: use of deleted local reference 0x79 Just…eep! This didn't happen before because `Java.Interop.JavaObject` subclasses *didn't* participate in typemap generation. This commit *adds* that support, introducing this unforeseen interaction. Fix this by *removing* most "alternate bindings" for `java/lang/Object`: - [JniTypeSignature ("java/lang/Object", GenerateJavaPeer=false)] + [JniTypeSignature (JniTypeName)] partial class JavaDisposedObject : JavaObject { + internal const string JniTypeName = "net/dot/jni/test/JavaDisposedObject"; } This implicitly requires that we now have a Java Callable Wrapper for this type, so update `Java.Interop-Tests.csproj` to run `jcw-gen` as part of the build process. This ensures that we create the JCW for e.g. `JavaDisposedObject`. Update `JavaVMFixture` to add the required typemap entries. --- Aside: this project includes [T4 Text Templates][0]. To regenerate the output files *without involving Visual Studio*, you can install the [`dotnet-t4`][1] tool: $ dotnet tool install --global dotnet-t4 then run it separately for each `.tt` file: $HOME/.dotnet/tools/t4 -o src/Java.Interop/Java.Interop/JavaPrimitiveArrays.cs \ src/Java.Interop/Java.Interop/JavaPrimitiveArrays.tt [0]: https://learn.microsoft.com/visualstudio/modeling/code-generation-and-t4-text-templates?view=vs-2022 [1]: https://www.nuget.org/packages/dotnet-t4/
1 parent d529f3b commit 07c7300

File tree

28 files changed

+110
-45
lines changed

28 files changed

+110
-45
lines changed

src/Java.Interop.Dynamic/Java.Interop.Dynamic/JavaInstanceProxy.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
namespace Java.Interop.Dynamic {
1515

16-
[JniTypeSignature ("java/lang/Object")]
16+
[JniTypeSignature ("java/lang/Object", GenerateJavaPeer=false)]
1717
class JavaInstanceProxy : JavaObject {
1818

1919
public JavaInstanceProxy (ref JniObjectReference reference, JniObjectReferenceOptions transfer)

src/Java.Interop.Tools.Cecil/Java.Interop.Tools.Cecil/TypeDefinitionRocks.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,25 @@ public static bool IsSubclassOf (this TypeDefinition type, string typeName, IMet
9292
return false;
9393
}
9494

95+
public static bool HasJavaPeer (this TypeDefinition type, IMetadataResolver resolver)
96+
{
97+
if (type.IsInterface && type.ImplementsInterface ("Java.Interop.IJavaPeerable", resolver))
98+
return true;
99+
100+
foreach (var t in type.GetTypeAndBaseTypes (resolver)) {
101+
switch (t.FullName) {
102+
case "Java.Lang.Object":
103+
case "Java.Lang.Throwable":
104+
case "Java.Interop.JavaObject":
105+
case "Java.Interop.JavaException":
106+
return true;
107+
default:
108+
break;
109+
}
110+
}
111+
return false;
112+
}
113+
95114
[Obsolete ("Use the TypeDefinitionCache overload for better performance.", error: true)]
96115
public static bool ImplementsInterface (this TypeDefinition type, string interfaceName) => throw new NotSupportedException ();
97116

src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/JavaCallableWrapperGenerator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ void AddNestedTypes (TypeDefinition type)
121121
}
122122
children = children ?? new List<JavaCallableWrapperGenerator> ();
123123
foreach (TypeDefinition nt in type.NestedTypes) {
124-
if (!nt.IsSubclassOf ("Java.Lang.Object", cache))
124+
if (!nt.HasJavaPeer (cache))
125125
continue;
126126
if (!JavaNativeTypeManager.IsNonStaticInnerClass (nt, cache))
127127
continue;

src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/JavaTypeScanner.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,7 @@ public List<TypeDefinition> GetJavaTypes (AssemblyDefinition assembly)
6666

6767
void AddJavaTypes (List<TypeDefinition> javaTypes, TypeDefinition type)
6868
{
69-
if (type.IsSubclassOf ("Java.Lang.Object", cache) ||
70-
type.IsSubclassOf ("Java.Lang.Throwable", cache) ||
71-
(type.IsInterface && type.ImplementsInterface ("Java.Interop.IJavaPeerable", cache))) {
72-
// For subclasses of e.g. Android.App.Activity.
69+
if (type.HasJavaPeer (cache)) {
7370
javaTypes.Add (type);
7471
} else if (type.IsClass && !type.IsSubclassOf ("System.Exception", cache) && type.ImplementsInterface ("Android.Runtime.IJavaObject", cache)) {
7572
var level = ErrorOnCustomJavaObject ? TraceLevel.Error : TraceLevel.Warning;

src/Java.Interop.Tools.TypeNameMappings/Java.Interop.Tools.TypeNameMappings/JavaNativeTypeManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -717,7 +717,7 @@ internal static bool IsNonStaticInnerClass (TypeDefinition? type, IMetadataResol
717717
if (!type.IsNested)
718718
return false;
719719

720-
if (!type.DeclaringType.IsSubclassOf ("Java.Lang.Object", cache))
720+
if (!type.DeclaringType.HasJavaPeer (cache))
721721
return false;
722722

723723
foreach (var baseType in type.GetBaseTypes (cache)) {

src/Java.Interop/Java.Interop/JavaException.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
namespace Java.Interop
66
{
7-
[JniTypeSignature (JniTypeName)]
7+
[JniTypeSignature (JniTypeName, GenerateJavaPeer=false)]
88
unsafe public class JavaException : Exception, IJavaPeerable
99
{
1010
internal const string JniTypeName = "java/lang/Throwable";

src/Java.Interop/Java.Interop/JavaObject.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
namespace Java.Interop
66
{
7-
[JniTypeSignature ("java/lang/Object")]
7+
[JniTypeSignature ("java/lang/Object", GenerateJavaPeer=false)]
88
unsafe public class JavaObject : IJavaPeerable
99
{
1010
readonly static JniPeerMembers _members = new JniPeerMembers ("java/lang/Object", typeof (JavaObject));

src/Java.Interop/Java.Interop/JavaPrimitiveArrays.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ protected override unsafe void Synchronize (JniReleaseArrayElementsMode releaseM
142142
}
143143
}
144144

145-
[JniTypeSignature ("Z", ArrayRank=1, IsKeyword=true)]
145+
[JniTypeSignature ("Z", ArrayRank=1, IsKeyword=true, GenerateJavaPeer=false)]
146146
public sealed class JavaBooleanArray : JavaPrimitiveArray<Boolean> {
147147

148148
internal static readonly ValueMarshaler ArrayMarshaler = new ValueMarshaler ();
@@ -337,7 +337,7 @@ protected override unsafe void Synchronize (JniReleaseArrayElementsMode releaseM
337337
}
338338
}
339339

340-
[JniTypeSignature ("B", ArrayRank=1, IsKeyword=true)]
340+
[JniTypeSignature ("B", ArrayRank=1, IsKeyword=true, GenerateJavaPeer=false)]
341341
public sealed class JavaSByteArray : JavaPrimitiveArray<SByte> {
342342

343343
internal static readonly ValueMarshaler ArrayMarshaler = new ValueMarshaler ();
@@ -532,7 +532,7 @@ protected override unsafe void Synchronize (JniReleaseArrayElementsMode releaseM
532532
}
533533
}
534534

535-
[JniTypeSignature ("C", ArrayRank=1, IsKeyword=true)]
535+
[JniTypeSignature ("C", ArrayRank=1, IsKeyword=true, GenerateJavaPeer=false)]
536536
public sealed class JavaCharArray : JavaPrimitiveArray<Char> {
537537

538538
internal static readonly ValueMarshaler ArrayMarshaler = new ValueMarshaler ();
@@ -727,7 +727,7 @@ protected override unsafe void Synchronize (JniReleaseArrayElementsMode releaseM
727727
}
728728
}
729729

730-
[JniTypeSignature ("S", ArrayRank=1, IsKeyword=true)]
730+
[JniTypeSignature ("S", ArrayRank=1, IsKeyword=true, GenerateJavaPeer=false)]
731731
public sealed class JavaInt16Array : JavaPrimitiveArray<Int16> {
732732

733733
internal static readonly ValueMarshaler ArrayMarshaler = new ValueMarshaler ();
@@ -922,7 +922,7 @@ protected override unsafe void Synchronize (JniReleaseArrayElementsMode releaseM
922922
}
923923
}
924924

925-
[JniTypeSignature ("I", ArrayRank=1, IsKeyword=true)]
925+
[JniTypeSignature ("I", ArrayRank=1, IsKeyword=true, GenerateJavaPeer=false)]
926926
public sealed class JavaInt32Array : JavaPrimitiveArray<Int32> {
927927

928928
internal static readonly ValueMarshaler ArrayMarshaler = new ValueMarshaler ();
@@ -1117,7 +1117,7 @@ protected override unsafe void Synchronize (JniReleaseArrayElementsMode releaseM
11171117
}
11181118
}
11191119

1120-
[JniTypeSignature ("J", ArrayRank=1, IsKeyword=true)]
1120+
[JniTypeSignature ("J", ArrayRank=1, IsKeyword=true, GenerateJavaPeer=false)]
11211121
public sealed class JavaInt64Array : JavaPrimitiveArray<Int64> {
11221122

11231123
internal static readonly ValueMarshaler ArrayMarshaler = new ValueMarshaler ();
@@ -1312,7 +1312,7 @@ protected override unsafe void Synchronize (JniReleaseArrayElementsMode releaseM
13121312
}
13131313
}
13141314

1315-
[JniTypeSignature ("F", ArrayRank=1, IsKeyword=true)]
1315+
[JniTypeSignature ("F", ArrayRank=1, IsKeyword=true, GenerateJavaPeer=false)]
13161316
public sealed class JavaSingleArray : JavaPrimitiveArray<Single> {
13171317

13181318
internal static readonly ValueMarshaler ArrayMarshaler = new ValueMarshaler ();
@@ -1507,7 +1507,7 @@ protected override unsafe void Synchronize (JniReleaseArrayElementsMode releaseM
15071507
}
15081508
}
15091509

1510-
[JniTypeSignature ("D", ArrayRank=1, IsKeyword=true)]
1510+
[JniTypeSignature ("D", ArrayRank=1, IsKeyword=true, GenerateJavaPeer=false)]
15111511
public sealed class JavaDoubleArray : JavaPrimitiveArray<Double> {
15121512

15131513
internal static readonly ValueMarshaler ArrayMarshaler = new ValueMarshaler ();

src/Java.Interop/Java.Interop/JavaPrimitiveArrays.tt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ namespace Java.Interop {
139139
}
140140
}
141141

142-
[JniTypeSignature ("<#= info.JniType #>", ArrayRank=1, IsKeyword=true)]
142+
[JniTypeSignature ("<#= info.JniType #>", ArrayRank=1, IsKeyword=true, GenerateJavaPeer=false)]
143143
public sealed class Java<#= info.TypeModifier #>Array : JavaPrimitiveArray<<#= info.ManagedType #>> {
144144

145145
internal static readonly ValueMarshaler ArrayMarshaler = new ValueMarshaler ();

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
namespace Java.Interop {
99

10-
[JniTypeSignature (JniTypeName)]
10+
[JniTypeSignature (JniTypeName, GenerateJavaPeer=false)]
1111
sealed class JavaProxyObject : JavaObject, IEquatable<JavaProxyObject>
1212
{
1313
internal const string JniTypeName = "net/dot/jni/internal/JavaProxyObject";

src/Java.Interop/Java.Interop/JavaProxyThrowable.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
namespace Java.Interop {
66

7-
[JniTypeSignature (JniTypeName)]
7+
[JniTypeSignature (JniTypeName, GenerateJavaPeer=false)]
88
sealed class JavaProxyThrowable : JavaException
99
{
1010
new internal const string JniTypeName = "net/dot/jni/internal/JavaProxyThrowable";

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
namespace Java.Interop {
1515

16-
[JniTypeSignature (JniTypeName)]
16+
[JniTypeSignature (JniTypeName, GenerateJavaPeer=false)]
1717
/* static */ sealed class ManagedPeer : JavaObject {
1818

1919
internal const string JniTypeName = "net/dot/jni/ManagedPeer";

tests/Java.Interop-PerformanceTests/Java.Interop/JavaTiming.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
namespace Java.Interop.PerformanceTests
99
{
10-
[JniTypeSignature (JniTypeName)]
10+
[JniTypeSignature (JniTypeName, GenerateJavaPeer=false)]
1111
public class JavaTiming : JavaObject
1212
{
1313
protected const string JniTypeName = "com/xamarin/interop/performance/JavaTiming";

tests/Java.Interop-Tests/Java.Interop-Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
<ProjectReference Include="..\..\src\Java.Interop.GenericMarshaler\Java.Interop.GenericMarshaler.csproj" />
3131
<ProjectReference Include="..\..\src\Java.Runtime.Environment\Java.Runtime.Environment.csproj" />
3232
<ProjectReference Include="..\TestJVM\TestJVM.csproj" />
33+
<ProjectReference Include="..\..\tools\jcw-gen\jcw-gen.csproj" ReferenceOutputAssembly="false" />
3334
</ItemGroup>
3435

3536
<ItemGroup>

tests/Java.Interop-Tests/Java.Interop-Tests.targets

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,47 @@
11
<Project>
22

3+
<ItemGroup>
4+
<_BuildJavaInteropTestsJarInputs Include="$(TargetPath)" />
5+
<_BuildJavaInteropTestsJarInputs Include="$(MSBuildThisFileFullPath)" />
6+
<_BuildJavaInteropTestsJarInputs Include="java\**\*.java" />
7+
</ItemGroup>
8+
9+
<Target Name="_CreateJavaCallableWrappers"
10+
Condition=" '$(TargetPath)' != '' "
11+
AfterTargets="Build"
12+
Inputs="@(_BuildJavaInteropTestsJarInputs)"
13+
Outputs="$(IntermediateOutputPath)java\.stamp">
14+
<RemoveDir Directories="$(IntermediateOutputPath)java" />
15+
<MakeDir Directories="$(IntermediateOutputPath)java" />
16+
<ItemGroup>
17+
<!-- I can't find a good way to trim the trailing `\`, so append with `.` so we can sanely quote for $(_Libpath) -->
18+
<_RefAsmDirs Include="@(ReferencePathWithRefAssemblies->'%(RootDir)%(Directory).'->Distinct())" />
19+
</ItemGroup>
20+
<PropertyGroup>
21+
<_JcwGen>"$(UtilityOutputFullPath)/jcw-gen.dll"</_JcwGen>
22+
<_Target>--codegen-target JavaInterop1</_Target>
23+
<_Output>-o "$(IntermediateOutputPath)/java"</_Output>
24+
<_Libpath>@(_RefAsmDirs->'-L "%(Identity)"', ' ')</_Libpath>
25+
</PropertyGroup>
26+
<Exec Command="$(DotnetToolPath) $(_JcwGen) -v &quot;$(TargetPath)&quot; $(_Target) $(_Output) $(_Libpath)" />
27+
<Touch Files="$(IntermediateOutputPath)java\.stamp" AlwaysCreate="True" />
28+
</Target>
29+
30+
<Target Name="_CollectGeneratdJcwSource">
31+
<ItemGroup>
32+
<_GeneratedJcwSource Include="$(IntermediateOutputPath)java\**\*.java" />
33+
</ItemGroup>
34+
</Target>
35+
336
<Target Name="BuildInteropTestJar"
4-
BeforeTargets="Build"
5-
Inputs="@(JavaInteropTestJar)"
37+
AfterTargets="Build"
38+
DependsOnTargets="_CreateJavaCallableWrappers;_CollectGeneratdJcwSource"
39+
Inputs="@(JavaInteropTestJar);@(_GeneratedJcwSource)"
640
Outputs="$(OutputPath)interop-test.jar">
741
<MakeDir Directories="$(IntermediateOutputPath)it-classes" />
842
<ItemGroup>
943
<_Source Include="@(JavaInteropTestJar->Replace('%5c', '/'))" />
44+
<_Source Include="@(_GeneratedJcwSource->Replace('%5c', '/'))" />
1045
</ItemGroup>
1146
<WriteLinesToFile
1247
File="$(IntermediateOutputPath)_java_sources.txt"

tests/Java.Interop-Tests/Java.Interop/CallNonvirtualBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
namespace Java.InteropTests
66
{
7-
[JniTypeSignature (CallNonvirtualBase.JniTypeName)]
7+
[JniTypeSignature (CallNonvirtualBase.JniTypeName, GenerateJavaPeer=false)]
88
public class CallNonvirtualBase : JavaObject
99
{
1010
internal const string JniTypeName = "net/dot/jni/test/CallNonvirtualBase";

tests/Java.Interop-Tests/Java.Interop/CallNonvirtualDerived.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
namespace Java.InteropTests
66
{
7-
[JniTypeSignature (CallNonvirtualDerived.JniTypeName)]
7+
[JniTypeSignature (CallNonvirtualDerived.JniTypeName, GenerateJavaPeer=false)]
88
public class CallNonvirtualDerived : CallNonvirtualBase
99
{
1010
internal new const string JniTypeName = "net/dot/jni/test/CallNonvirtualDerived";

tests/Java.Interop-Tests/Java.Interop/CallNonvirtualDerived2.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
namespace Java.InteropTests
66
{
7-
[JniTypeSignature (CallNonvirtualDerived2.JniTypeName)]
7+
[JniTypeSignature (CallNonvirtualDerived2.JniTypeName, GenerateJavaPeer=false)]
88
public class CallNonvirtualDerived2 : CallNonvirtualDerived
99
{
1010
internal new const string JniTypeName = "net/dot/jni/test/CallNonvirtualDerived2";

tests/Java.Interop-Tests/Java.Interop/CallVirtualFromConstructorBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
namespace Java.InteropTests {
77

8-
[JniTypeSignature (CallVirtualFromConstructorBase.JniTypeName)]
8+
[JniTypeSignature (CallVirtualFromConstructorBase.JniTypeName, GenerateJavaPeer=false)]
99
public class CallVirtualFromConstructorBase : JavaObject {
1010

1111
internal const string JniTypeName = "net/dot/jni/test/CallVirtualFromConstructorBase";

tests/Java.Interop-Tests/Java.Interop/CallVirtualFromConstructorDerived.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
namespace Java.InteropTests
66
{
7-
[JniTypeSignature (CallVirtualFromConstructorDerived.JniTypeName)]
7+
[JniTypeSignature (CallVirtualFromConstructorDerived.JniTypeName, GenerateJavaPeer=false)]
88
public class CallVirtualFromConstructorDerived : CallVirtualFromConstructorBase {
99
new internal const string JniTypeName = "net/dot/jni/test/CallVirtualFromConstructorDerived";
1010
static readonly JniPeerMembers _members = new JniPeerMembers (JniTypeName, typeof (CallVirtualFromConstructorDerived));

tests/Java.Interop-Tests/Java.Interop/GetThis.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
namespace Java.InteropTests
66
{
7-
[JniTypeSignature (GetThis.JniTypeName)]
7+
[JniTypeSignature (GetThis.JniTypeName, GenerateJavaPeer=false)]
88
public class GetThis : JavaObject
99
{
1010
internal const string JniTypeName = "net/dot/jni/test/GetThis";

tests/Java.Interop-Tests/Java.Interop/JavaManagedGCBridgeTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ static void SetupLinks (JavaObjectArray<CrossReferenceBridge> array, out WeakRef
5252
}
5353
}
5454

55-
[JniTypeSignature (JniTypeName)]
55+
[JniTypeSignature (JniTypeName, GenerateJavaPeer=false)]
5656
public class CrossReferenceBridge : JavaObject {
5757
internal const string JniTypeName = "net/dot/jni/test/CrossReferenceBridge";
5858

tests/Java.Interop-Tests/Java.Interop/JavaObjectTest.cs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -164,11 +164,13 @@ public void Ctor_Exceptions ()
164164
var r = new JniObjectReference ();
165165
Assert.Throws<ArgumentException> (() => new JavaObject (ref r, JniObjectReferenceOptions.CopyAndDispose));
166166

167-
// Note: This may break if/when JavaVM provides "default"
168-
Assert.Throws<NotSupportedException> (() => new JavaObjectWithNoJavaPeer ());
169167
#if __ANDROID__
170168
Assert.Throws<Java.Lang.ClassNotFoundException> (() => new JavaObjectWithMissingJavaPeer ()).Dispose ();
171169
#else // !__ANDROID__
170+
// Note: `JavaObjectWithNoJavaPeer` creation works on Android because tooling provides all
171+
// typemap entries. On desktop, we use the hardcoded dictionary in JavaVMFixture, which
172+
// deliberately *lacks* an entry for `JavaObjectWithNoJavaPeer`.
173+
Assert.Throws<NotSupportedException> (() => new JavaObjectWithNoJavaPeer ());
172174
Assert.Throws<JavaException> (() => new JavaObjectWithMissingJavaPeer ()).Dispose ();
173175
#endif // !__ANDROID__
174176
}
@@ -201,17 +203,21 @@ public void DisposeAccessesThis ()
201203
}
202204
}
203205

206+
#if !__ANDROID__
204207
class JavaObjectWithNoJavaPeer : JavaObject {
205208
}
209+
#endif // !__ANDROID__
206210

207-
[JniTypeSignature (JniTypeName)]
211+
[JniTypeSignature (JniTypeName, GenerateJavaPeer=false)]
208212
class JavaObjectWithMissingJavaPeer : JavaObject {
209213
internal const string JniTypeName = "__this__/__type__/__had__/__better__/__not__/__Exist__";
210214
}
211215

212-
[JniTypeSignature ("java/lang/Object")]
216+
[JniTypeSignature (JniTypeName)]
213217
class JavaDisposedObject : JavaObject {
214218

219+
internal const string JniTypeName = "net/dot/jni/test/JavaDisposedObject";
220+
215221
public Action OnDisposed;
216222
public Action OnFinalized;
217223

@@ -230,8 +236,10 @@ protected override void Dispose (bool disposing)
230236
}
231237
}
232238

233-
[JniTypeSignature ("java/lang/Object")]
239+
[JniTypeSignature (JniTypeName)]
234240
class MyDisposableObject : JavaObject {
241+
internal const string JniTypeName = "net/dot/jni/test/MyDisposableObject";
242+
235243
bool _isDisposed;
236244

237245
public MyDisposableObject ()

tests/Java.Interop-Tests/Java.Interop/JavaVMFixture.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,11 @@ class JavaVMFixtureTypeManager : JniRuntime.JniTypeManager {
3939
[RenameClassDerived.JniTypeName] = typeof (RenameClassDerived),
4040
[CallVirtualFromConstructorBase.JniTypeName] = typeof (CallVirtualFromConstructorBase),
4141
[CallVirtualFromConstructorDerived.JniTypeName] = typeof (CallVirtualFromConstructorDerived),
42+
[CrossReferenceBridge.JniTypeName] = typeof (CrossReferenceBridge),
4243
[GetThis.JniTypeName] = typeof (GetThis),
44+
[JavaDisposedObject.JniTypeName] = typeof (JavaDisposedObject),
45+
[JavaObjectWithMissingJavaPeer.JniTypeName] = typeof (JavaObjectWithMissingJavaPeer),
46+
[MyDisposableObject.JniTypeName] = typeof (JavaDisposedObject),
4347
};
4448

4549
public JavaVMFixtureTypeManager ()

0 commit comments

Comments
 (0)