Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Bug DataContract serialisation of Dictionary fails in Android IL2CPP

Discussion in 'Android' started by ricardoralha, May 18, 2021.

  1. ricardoralha

    ricardoralha

    Joined:
    May 30, 2019
    Posts:
    3
    I was trying to serialise a Dictionary, when this exception occurred:

    Code (CSharp):
    1. ExecutionEngineException: Attempting to call method ‘System.Runtime.Serialization.XmlObjectSerializerWriteContext::IncrementCollectionCountGeneric<System.Collections.Generic.KeyValuePair`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[WaitingAction, ActionPackage, Version=1.7.0.0, Culture=neutral, PublicKeyToken=null]]>for which no ahead of time (AOT) code was generated.
    2.       at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <00000000000000000000000000000000>:0
    3.       at System.Runtime.Serialization.XmlFormatWriterInterpreter.WriteCollection (System.Runtime.Serialization.CollectionDataContract collectionContract) [0x00000] in <00000000000000000000000000000000>:0
    4.       at System.Runtime.Serialization.DataContractSerializer.InternalWriteObjectContent (System.Runtime.Serialization.XmlWriterDelegator writer
    Keep in mind this only happened in Android IL2CPP, I didn't have any problems in iOS. I was running Unity 2019.2.10, with .NET 4.x API compatibility level. System.Runtime.Serialization is also added to link.xml.

    This appears to be something recurring, as this bug was also reported in this thread (see latest message) but with a KeyValuePair<string, string>.
     
  2. Tomas1856

    Tomas1856

    Unity Technologies

    Joined:
    Sep 21, 2012
    Posts:
    3,875
    Could you please report a bug, it looks like that method was stripped away, also can you show the contents of link.xml? System.Runtime.Serialization is a namespace, maybe you need to add class - System.Runtime.Serialization.XmlObjectSerializerWriteContext ?
     
  3. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,921
    My guess is that this is unrelated to managed code stripping (and therefore link.xml), but rather a more general AOT compilation issue. IL2CPP must see all of the generic types that have value type arguments at compilation time in order to generate code for them.

    In this case, the type looks like: KeyValuePair<string, WaitingAction>

    So you might be able to work around this issue by putting some code like this in your project:

    Code (CSharp):
    1. [Preserve]
    2. static void NeverCalledButUsedAtCompileTime()
    3. {
    4.     var test = KeyValuePair<string, WaitingAction>();
    5. }
    There may be other serialized types that trigger this error though. You could include those in this method as well.

    Otherwise, if this project can work with the latest 2021.2 alpha release of Unity, we now have an option to allow this to work properly without the work around.
     
  4. ricardoralha

    ricardoralha

    Joined:
    May 30, 2019
    Posts:
    3
    Correct me if I'm wrong but adding System.Runtime.Serialization to link.xml only guarantees that the assembly isn't stripped by the strip engine. For IL2CPP, the AOT code still needs to be generated. In this case, a specific method Runtime.Serialization.XmlObjectSerializerWriteContext::IncrementCollectionCountGeneric<string, WaitingAction> needs to be generated from the original generic method.

    @JoshPeterson I tried your solution and it still didn't work. Ideally, we should include in the Preserved method the call to Runtime.Serialization.XmlObjectSerializerWriteContext::IncrementCollectionCountGeneric<string, WaitingAction>, but that seems to be impossible.

    I also tried to include KeyValuePair<string, WaitingAction> as a knownTypes for the DataContractSerializer, with no avail.

    At the moment, the project can't run in the 2021.2 alpha release of Unity, so that isn't an option, unfortunately.

    The solution I have at the moment is to transfer the data I have in the dictionary to two arrays and serialize the arrays.
     
  5. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,921
    I'm not sure why the solution I suggested does not work - sometimes these are subtle issues though, so it may be incorrect. It sounds like your work around might be the best option though.