Проблема компиляции JIT в проекте MonoTouch + IKVM
Я портирую Java-игру на iOS через ikvm-monotouch и MonoTouch. Я столкнулся с ошибкой, которая возникла у меня из головы, хотя я не уверен, является ли это реальной ошибкой в MonoTouch, поэтому я спрашиваю здесь, прежде чем обращаться к базе данных ошибок.
Я получаю ошибку компиляции JIT ниже во время метода, который отражает поля объекта. Я (до сих пор) только видел эту ошибку при отражении на объекте, который реализует Cloneable
, хотя я не знаю наверняка, именно это вызывает эту ошибку.
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
Быстрая ссылка на класс TypeWrapper ikvm-monotouch: https://github.com/samskivert/ikvm-monotouch/blob/master/runtime/TypeWrapper.cs
1 ответ
Строка № 1841 из TypeWrapper.cs:
clazz = (java.lang.Class)typeof(ikvm.@internal.ClassLiteral<>).
MakeGenericType(type).GetField("Value").GetValue(null);
так что это либо связано с:
а) MakeGenericType
в том смысле, что компилятор AOT не знает во время компиляции, что ему нужно создать ClassLiteral<Cloneable>
, Поскольку он не знает, он не компилирует требуемый код, приводящий к ExecutionEngineException
,
Вы могли бы обойти это, намекая AOT-компилятору, что код необходим. Например, добавьте, где-то в вашем коде, который не будет связан или оптимизирован.
new ClassLiteral<Cloneable> ();
б) GetField("Value")
в том смысле, что (управляемый) компоновщик мог удалить это поле. Однако он должен был потерпеть неудачу с NullReferenceException
(а не внутри.cctor), поэтому я не верю, что это проблема компоновщика.
ОТО, это очень быстро и легко устранить эту возможность, отключив компоновщик в вашем проекте, перестроить и выполнить на устройстве (если он начинает работать, то это проблема компоновщика. Вы сможете обойти это, используя [Preserve]
атрибут на Value
поле (и включите компоновщик позже).