Skip to content

Commit 40b75e9

Browse files
radekdoulikjonpryor
authored andcommitted
[Java.Interop.Tools.JavaCallableWrappers] Add TypeNameMapGenerator.Dispose() (#91)
When the [`<GenerateJavaStubs/>` task in `xamarin-android`][0] uses `Java.Interop.Tools.JavaCallableWrappers.TypeNameMapGenerator` and calls `TypeNameMapGenerator.WriteJavaToManaged()`, a `NullReferenceException` is thrown: Error executing task GenerateJavaStubs: System.NullReferenceException: Object reference not set to an instance of an object at Java.Interop.Tools.Cecil.DirectoryAssemblyResolver.Resolve (Mono.Cecil.AssemblyNameReference reference, Mono.Cecil.ReaderParameters parameters) [0x00028] in <3f2ebd7ea1fd47bd954f448c66f03323>:0 at Java.Interop.Tools.Cecil.DirectoryAssemblyResolver.Resolve (Mono.Cecil.AssemblyNameReference reference) [0x00001] in <3f2ebd7ea1fd47bd954f448c66f03323>:0 at Mono.Cecil.MetadataResolver.Resolve (Mono.Cecil.TypeReference type) [0x0004e] in <4f9b8c8361824d0ca9025449919e12be>:0 at Mono.Cecil.ModuleDefinition.Resolve (Mono.Cecil.TypeReference type) [0x00007] in <4f9b8c8361824d0ca9025449919e12be>:0 at Mono.Cecil.TypeReference.Resolve () [0x00014] in <4f9b8c8361824d0ca9025449919e12be>:0 at Java.Interop.Tools.Cecil.TypeDefinitionRocks.GetBaseType (Mono.Cecil.TypeDefinition type) [0x00014] in <3f2ebd7ea1fd47bd954f448c66f03323>:0 at Java.Interop.Tools.Cecil.TypeDefinitionRocks+<GetTypeAndBaseTypes>c__Iterator0.MoveNext () [0x00048] in <3f2ebd7ea1fd47bd954f448c66f03323>:0 at System.Linq.Enumerable.Any[TSource] (System.Collections.Generic.IEnumerable`1[T] source, System.Func`2[T,TResult] predicate) [0x00048] in <51a1d86c1edf494cacaba8bbf8d1334e>:0 at Java.Interop.Tools.Cecil.TypeDefinitionRocks.ImplementsInterface (Mono.Cecil.TypeDefinition type, System.String interfaceName) [0x00014] in <3f2ebd7ea1fd47bd954f448c66f03323>:0 at Java.Interop.Tools.TypeNameMappings.JniType.ToJniName (Mono.Cecil.TypeDefinition type, Java.Interop.ExportParameterKind exportKind) [0x00049] in <3076bd81225243d6b1a7e6e2e66cb5f7>:0 at Java.Interop.Tools.TypeNameMappings.JniType.ToJniName (Mono.Cecil.TypeDefinition type) [0x00001] in <3076bd81225243d6b1a7e6e2e66cb5f7>:0 at Java.Interop.Tools.JavaCallableWrappers.TypeNameMapGenerator.GetTypeMapping (System.Func`2[T,TResult] skipType, System.Func`2[T,TResult] key, System.Func`2[T,TResult] value) [0x00047] in <3076bd81225243d6b1a7e6e2e66cb5f7>:0 at Java.Interop.Tools.JavaCallableWrappers.TypeNameMapGenerator.WriteJavaToManaged (System.IO.Stream output) [0x00012] in <3076bd81225243d6b1a7e6e2e66cb5f7>:0 at Xamarin.Android.Tasks.GenerateJavaStubs.UpdateWhenChanged (System.String path, System.Action`1[T] generator) [0x00014] in <d1b286cda0c74ed8bdaf1b21993bd410>:0 at Xamarin.Android.Tasks.GenerateJavaStubs.WriteTypeMappings (System.Collections.Generic.List`1[T] types) [0x00078] in <d1b286cda0c74ed8bdaf1b21993bd410>:0 at Xamarin.Android.Tasks.GenerateJavaStubs.Run (Java.Interop.Tools.Cecil.DirectoryAssemblyResolver res) [0x00153] in <d1b286cda0c74ed8bdaf1b21993bd410>:0 at Xamarin.Android.Tasks.GenerateJavaStubs.Execute () [0x001f2] in <d1b286cda0c74ed8bdaf1b21993bd410>:0 The underlying problem is that because the `TypeNameMapGenerator(IEnumerable<string>, Action<string, string>)` constructor disposes of the intermediate `DirectoryAssemblyResolver` isntance [^1], when e.g. `TypeNameMapGenerator.WriteJavaToManaged()` is later called, `DirectoryAssemblyResolver.Resolve()` will implicitly be called (because `DirectoryAssemblyResolver.Load()` sets `ReaderParameters.AssemblyResolver` to `this`), which attempts to access `DirectoryAssemblyResolver.cache`, which is `null`, resulting in the aforementioned `NullReferenceException`. To fix this, update `TypeNameMapGenerator` to: 1. Hold the `DirectoryAssemblyResolver` as a member, instead of retaining it as a local variable 2. Implement `IDisposable` 3. Have `TypeNameMapGenerator.Dispose()` dispose of the `DirectoryAssemblyResolver` instance, if present. [0]: https://github.com/xamarin/xamarin-android/blob/16d65fa/src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs#L267-L274 [^1]: `Dispose()` location: at Java.Interop.Tools.Cecil.DirectoryAssemblyResolver.Dispose (System.Boolean disposing) [0x00000] in <3f2ebd7ea1fd47bd954f448c66f03323>:0 at Java.Interop.Tools.Cecil.DirectoryAssemblyResolver.Dispose () [0x00000] in <3f2ebd7ea1fd47bd954f448c66f03323>:0 at Java.Interop.Tools.JavaCallableWrappers.TypeNameMapGenerator..ctor (System.Collections.Generic.IEnumerable`1[T] assemblies, System.Action`2[T1,T2] logMessage) [0x00000] in <3076bd81225243d6b1a7e6e2e66cb5f7>:0 at Xamarin.Android.Tasks.GenerateJavaStubs.WriteTypeMappings (System.Collections.Generic.List`1[T] types) [0x00000] in <d1b286cda0c74ed8bdaf1b21993bd410>:0 at Xamarin.Android.Tasks.GenerateJavaStubs.Run (Java.Interop.Tools.Cecil.DirectoryAssemblyResolver res) [0x00000] in <d1b286cda0c74ed8bdaf1b21993bd410>:0 at Xamarin.Android.Tasks.GenerateJavaStubs.Execute () [0x00000] in <d1b286cda0c74ed8bdaf1b21993bd410>:0
1 parent f153b7a commit 40b75e9

File tree

1 file changed

+29
-14
lines changed

1 file changed

+29
-14
lines changed

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

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,11 @@ namespace Java.Interop.Tools.JavaCallableWrappers {
5454
* The rows MUST be sorted so that strcmp(3) can be used to compare keys
5555
* values between rows
5656
*/
57-
public class TypeNameMapGenerator {
57+
public class TypeNameMapGenerator : IDisposable {
5858

5959
Action<string, object[]> Log;
6060
List<TypeDefinition> Types;
61+
DirectoryAssemblyResolver Resolver;
6162

6263
public TypeNameMapGenerator (IEnumerable<string> assemblies, Action<string, object []> logMessage)
6364
{
@@ -70,20 +71,19 @@ public TypeNameMapGenerator (IEnumerable<string> assemblies, Action<string, obje
7071
var Assemblies = assemblies.ToList ();
7172
var rp = new ReaderParameters (ReadingMode.Immediate);
7273

73-
using (var resolver = new DirectoryAssemblyResolver (Log, loadDebugSymbols: true, loadReaderParameters: rp)) {
74-
foreach (var assembly in Assemblies) {
75-
var directory = Path.GetDirectoryName (assembly);
76-
if (string.IsNullOrEmpty (directory))
77-
continue;
78-
if (!resolver.SearchDirectories.Contains (directory))
79-
resolver.SearchDirectories.Add (directory);
80-
}
81-
foreach (var assembly in Assemblies) {
82-
resolver.Load (Path.GetFullPath (assembly));
83-
}
84-
85-
Types = JavaTypeScanner.GetJavaTypes (Assemblies, resolver, logMessage);
74+
Resolver = new DirectoryAssemblyResolver (Log, loadDebugSymbols: true, loadReaderParameters: rp);
75+
foreach (var assembly in Assemblies) {
76+
var directory = Path.GetDirectoryName (assembly);
77+
if (string.IsNullOrEmpty (directory))
78+
continue;
79+
if (!Resolver.SearchDirectories.Contains (directory))
80+
Resolver.SearchDirectories.Add (directory);
8681
}
82+
foreach (var assembly in Assemblies) {
83+
Resolver.Load (Path.GetFullPath (assembly));
84+
}
85+
86+
Types = JavaTypeScanner.GetJavaTypes (Assemblies, Resolver, logMessage);
8787
}
8888

8989
public TypeNameMapGenerator (IEnumerable<TypeDefinition> types, Action<string, object[]> logMessage)
@@ -97,6 +97,21 @@ public TypeNameMapGenerator (IEnumerable<TypeDefinition> types, Action<string, o
9797
Types = types.ToList ();
9898
}
9999

100+
public void Dispose ()
101+
{
102+
Dispose (true);
103+
GC.SuppressFinalize (this);
104+
}
105+
106+
protected virtual void Dispose (bool disposing)
107+
{
108+
if (!disposing || Resolver == null)
109+
return;
110+
111+
Resolver.Dispose ();
112+
Resolver = null;
113+
}
114+
100115
void LogWarning (string format, params object[] args)
101116
{
102117
Log (format, args);

0 commit comments

Comments
 (0)