Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

IL2CPP runtime Error in plugins

Discussion in 'Android' started by mokhabadi, Nov 18, 2020.

  1. mokhabadi

    mokhabadi

    Joined:
    Jul 25, 2018
    Posts:
    27
    hello! i have a project that uses System.Text.Json nuGet package dlls, i put .net2standard dlls in plugin folder. when i build for android with mono it works fine, but when i change to il2cpp it doesn't work. in build it throw a runtime error saying it can't find constructor of jsonserialization class.
    i don't have any clue what is the problem! any help appreciated! Thanks in advance!
     
  2. Tomas1856

    Tomas1856

    Unity Technologies

    Joined:
    Sep 21, 2012
    Posts:
    3,663
    Please post the full error here.
     
  3. mokhabadi

    mokhabadi

    Joined:
    Jul 25, 2018
    Posts:
    27
    Log
    Scene SampleScene is loaded
    UnityEngine.Debug:Log(Object)
    Reporter:_OnLevelWasLoaded(Scene, LoadSceneMode)
    UnityEngine.SceneManagement.SceneManager:Internal_SceneLoaded(Scene, LoadSceneMode)

    Exception
    MissingMethodException: Constructor on type 'System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1[[Sample+req, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]' not found.
    System.RuntimeType.CreateInstanceImpl (System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Object[] args, System.Globalization.CultureInfo culture, System.Object[] activationAttributes, System.Threading.StackCrawlMark& stackMark) (at <00000000000000000000000000000000>:0)
    System.Activator.CreateInstance (System.Type type, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Object[] args, System.Globalization.CultureInfo culture, System.Object[] activationAttributes) (at <00000000000000000000000000000000>:0)
    System.Activator.CreateInstance (System.Type type, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Object[] args, System.Globalization.CultureInfo culture) (at <00000000000000000000000000000000>:0)
    System.Text.Json.Serialization.Converters.ObjectConverterFactory.CreateConverter (System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) (at <00000000000000000000000000000000>:0)
    System.Text.Json.Serialization.JsonConverterFactory.GetConverterInternal (System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) (at <00000000000000000000000000000000>:0)
    System.Text.Json.JsonSerializerOptions.GetConverter (System.Type typeToConvert) (at <00000000000000000000000000000000>:0)
    System.Text.Json.JsonSerializerOptions.DetermineConverter (System.Type parentClassType, System.Type runtimePropertyType, System.Reflection.MemberInfo memberInfo) (at <00000000000000000000000000000000>:0)
    System.Text.Json.JsonClassInfo.GetConverter (System.Type type, System.Type parentClassType, System.Reflection.MemberInfo memberInfo, System.Type& runtimeType, System.Text.Json.JsonSerializerOptions options) (at <00000000000000000000000000000000>:0)
    System.Text.Json.JsonClassInfo..ctor (System.Type type, System.Text.Json.JsonSerializerOptions options) (at <00000000000000000000000000000000>:0)
    System.Text.Json.JsonSerializerOptions.GetOrAddClass (System.Type type) (at <00000000000000000000000000000000>:0)
    System.Text.Json.JsonSerializerOptions.GetOrAddClassForRootType (System.Type type) (at <00000000000000000000000000000000>:0)
    System.Text.Json.MemberAccessor..ctor () (at <00000000000000000000000000000000>:0)
    System.Text.Json.JsonSerializer.ReadCore[TValue] (System.Text.Json.Utf8JsonReader& reader, System.Type returnType, System.Text.Json.JsonSerializerOptions options) (at <00000000000000000000000000000000>:0)
    System.Text.Json.JsonSerializer.Deserialize[TValue] (System.String json, System.Type returnType, System.Text.Json.JsonSerializerOptions options) (at <00000000000000000000000000000000>:0)
    System.Text.Json.JsonSerializer.Deserialize[TValue] (System.String json, System.Text.Json.JsonSerializerOptions options) (at <00000000000000000000000000000000>:0)
    Sample.Start () (at <00000000000000000000000000000000>:0)
     
  4. Tomas1856

    Tomas1856

    Unity Technologies

    Joined:
    Sep 21, 2012
    Posts:
    3,663
    Do you by any chance have Managed Stripping enabled. Or maybe you class "Sample+req" doesn't have a default constructor?
     
  5. mokhabadi

    mokhabadi

    Joined:
    Jul 25, 2018
    Posts:
    27
    I disabled striping. My class doesn't have constructor. But AFAIK c# defines a default constructor if you don't declare any.
     
  6. mokhabadi

    mokhabadi

    Joined:
    Jul 25, 2018
    Posts:
    27
    I don't understand "Sample+req". Could It be a problem that I defined two classes in one file? Tommarow I will put each class in a separate file.
     
  7. Tomas1856

    Tomas1856

    Unity Technologies

    Joined:
    Sep 21, 2012
    Posts:
    3,663
    I think it means you have a nested class req in a class Sample
     
  8. mokhabadi

    mokhabadi

    Joined:
    Jul 25, 2018
    Posts:
    27
    They are not nested, they are just writen in same file. I will post my code tomorrow. But anyway it works fine in editor and in mono build for Android but it doesn't with il2cpp.

    EDIT: yes they were nested! i were careless!
     
    Last edited: Nov 19, 2020
  9. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,773
    Note that it is not possible to disable managed code stripping for an IL2CPP build from the player settings. It will always be enabled. You can however, use link.xml files and preserve attributes to indicate to the managed code stripping system that some types or methods should be kept even when they are using only via reflection. See the documentation for details: https://docs.unity3d.com/Manual/ManagedCodeStripping.html

    Note also that the managed code stripping system will remove the default constructor that C# defines if it is never used. So that might still be an issue.
     
  10. mokhabadi

    mokhabadi

    Joined:
    Jul 25, 2018
    Posts:
    27
    this is my code:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Text.Json;
    3. using UnityEngine.UI;
    4.  
    5. public class Sample : MonoBehaviour
    6. {
    7.     public Text text;
    8.     public TextAsset textAsset;
    9.     private void Start()
    10.     {
    11.         req rq = JsonSerializer.Deserialize<req>(textAsset.text);
    12.         text.text = rq.type;
    13.     }
    14.     class req
    15.     {
    16.         public string type { get; set; }
    17.         public string[] product_ids { get; set; }
    18.         public string[] channels { get; set; }
    19.     }
    20. }
    21.  
    in the text asset there is this content:
    Code (CSharp):
    1. {
    2.     "type": "subscribe",
    3.     "product_ids": [
    4.         "ETH-USD",
    5.         "ETH-EUR"
    6.     ],
    7.     "channels": [
    8.         "level2",
    9.         "heartbeat"
    10.     ]
    11. }
    it is a very simple json parser. i wrote this to test if il2cpp works fine or not. because i read that i must build with it to have x64 build for google play store because it is mandatory.
     
  11. Tomas1856

    Tomas1856

    Unity Technologies

    Joined:
    Sep 21, 2012
    Posts:
    3,663
    Last edited: Nov 19, 2020
  12. mokhabadi

    mokhabadi

    Joined:
    Jul 25, 2018
    Posts:
    27
    Thank you all friends for your help. I will discuss the source of the problem and solution:
    1- as @JoshPeterson said "it is not possible to disable managed code stripping for an IL2CPP build from the player settings". i were careless and misinterpreted "strip engine code" option as "strip code".
    2- the problem was in code striping.
    3- for some nonsense reason, we can't disbale code striping in il2cpp mode.
    4- my exception was very simple:
    Code (CSharp):
    1. Exception
    2. MissingMethodException: Constructor on type 'System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1[[Sample+req, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]' not found.
    it is obvious that problem is in System.Text.Json.Serialization
    5- i created a link.xml file with this content
    Code (CSharp):
    1. <linker>
    2.   <assembly fullname="System.Text.Json"/>
    3. </linker>
    6- problem solved! So far!

    it was a mere 10 line project and my first attempt to test il2cpp. after some investigation and reading https://docs.unity3d.com/Manual/scripting-backends.html I found that I will have some problem with my main project because it is a multiplayer online game and it havily depends on serialization and therefore reflection and generics and sometimes dynamic keyword. and these technics depends on JIT but il2cpp is AOT and i wil have a hard time to migrate from mono to il2cpp.

    Thank you again for your help
     
  13. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,773
    It is not really nonsense. Without managed code stripping, the IL code from base class library assemblies would make the code size of your project massive. That code was all written with a JIT in mind, not an AOT engine. That AOT code generation really leads to large executable size. Since most projects don't use most of the base class libraries code, we can safely remove it.

    That is why code stripping is always enabled with IL2CPP.
     
  14. mokhabadi

    mokhabadi

    Joined:
    Jul 25, 2018
    Posts:
    27
    Anyway It will not do a massive harm if you could disable it and see the results. Maybe it's size would be OK. Also when I disable Stripping in mono my Apk is not that big. Albeit I don't khow if il2cpp without Stripping results with the same size as mono but anyway I believe that having options and choices is not bad in this matter!
    And also there is a solution for disabling Stripping but it is not straightforward. You must add attributes for your assemblies and add a link.xml for third-parties. That's it.
     
  15. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,773
    The binary produced with IL2CPP will be much larger than the binary produced with Mono - we've tried :)

    You can do that same by creating a link.xml with all of the base class library assemblies preserved. This is one of those default behaviors that we chose to give the best overall at the cost of some complexity for cases like this one, unfortunately.
     
  16. mokhabadi

    mokhabadi

    Joined:
    Jul 25, 2018
    Posts:
    27
    Fortunately my problem is solved and I know the solution thanks to your advises! I hope you add 64 bit support to mono if it is possible!