I'm porting a Java game to iOS via ikvm-monotouch and MonoTouch. I've run into an error that is a bit over my head, although I'm not certain if it's an actual bug in MonoTouch so I'm asking here before hitting the bug database.
I'm getting the JIT compilation error below during a method that reflects on the fields of an object. I've (so far) only seen this error while reflecting on an object that implements Cloneable
, although I don't know for sure if that's specifically what is triggering this error.
Unhandled Exception: System.TypeInitializationException: An exception was thrown by the type initializer for ikvm.internal.ClassLiteral`1 ---> System.ExecutionEngineException: Attempting to JIT compile method 'ikvm.internal.ClassLiteral`1<java.lang.Cloneable>:.cctor ()' while running with --aot-only.
--- End of inner exception stack trace ---
at System.Reflection.MonoField.GetValue (System.Object obj) [0x0006a] in /Developer/MonoTouch/Source/mono/mcs/class/corlib/System.Reflection/MonoField.cs:124
at IKVM.Internal.TypeWrapper.LazyInitClass () [0x00063] in /Users/nathan/projects/ikvm-monotouch-git/runtime/TypeWrapper.cs:1841
at IKVM.Internal.TypeWrapper.get_ClassObject () [0x00027] in /Users/nathan/projects/ikvm-monotouch-git/runtime/TypeWrapper.cs:1756
at IKVM.NativeCode.java.lang.Class.getInterfaces (java.lang.Class thisClass) [0x0001c] in /Users/nathan/projects/ikvm-monotouch-git/runtime/openjdk.cs:2556
at java.lang.Class.getInterfaces () [0x00000] in <filename unknown>:0
at java.lang.Class.privateGetPublicFields (Set ) [0x00000] in <filename unknown>:0
at java.lang.Class.privateGetPublicFields (Set ) [0x00000] in <filename unknown>:0
at java.lang.Class.getFields (ikvm.internal.CallerID ) [0x00000] in <filename unknown>:0
Quick link to the ikvm-monotouch TypeWrapper class: https://github.com/samskivert/ikvm-monotouch/blob/master/runtime/TypeWrapper.cs
Line #1841 from TypeWrapper.cs is:
clazz = (java.lang.Class)typeof([email protected]<>).
MakeGenericType(type).GetField("Value").GetValue(null);
so it's either related to:
a) MakeGenericType
in the sense that the AOT compiler does not know, at compile time, that it needs to create a ClassLiteral<Cloneable>
. Since it does not know, it does not compile the required code leading to the ExecutionEngineException
.
You might be able to workaround this by hinting the AOT compiler that the code is needed. E.g. add a, somewhere in your code that will not be linked away or optimized out.
new ClassLiteral<Cloneable> ();
b) GetField("Value")
in the sense that the (managed) linker could have removed this field. However it should have failed with a NullReferenceException
(and not inside the .cctor) so I do not believe it's a linker issue.
OTOH it's very fast and easy to eliminate this possibility by disabling the linker in your project, rebuild and execute on device (if it starts working then it's a linker issue. You'll be able to workaround this by using the [Preserve]
attribute on the Value
field (and re-enable the linker afterward).