Skip to content
This repository was archived by the owner on Oct 6, 2023. It is now read-only.

Fix AOT compilation errors

Kalle Jillheden edited this page Jan 5, 2020 · 7 revisions

The problem

"In computer science, reflection is the ability of a process to examine, introspect, and modify its own structure and behavior."

From: https://en.wikipedia.org/wiki/Reflection_(computer_programming)

Newtonsoft.Json contains a lot of clever uses of reflection to figure out the schema of the objects it's working with, but also to create new instances of those types dynamically (i.e. not knowing at compile time which types to instantiate).

Upon compilation the Mono & IL2CPP compilers do their best to figure out which types you are going to use, and IL2CPP even discards the rest (called bytecode stripping). Here lies the issue; for the compilers cannot see the what code is referenced using reflection.

This can lead to errors in the format of:

Newtonsoft.Json.JsonSerializationException : Unable to find a constructor to use for type MyCSharpType. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute. Path 'TheProperty'.

Second example:

ExecutionEngineException: Attempting to call method 'Newtonsoft.Json.Utilities.CollectionWrapper`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]::.ctor' for which no ahead of time (AOT) code was generated.

-or, in other (less verbose) words:

Attempting to call constructor of type Newtonsoft.Json.Utilities.CollectionWrapper<int> for which no ahead of time (AOT) code was generated.

The alternatives

There are three main solutions available here. There's no one-shoe-fits-all, so to give a short overview here's a table describing the differences.

Practically speaking you will most probably be using multiple solutions, but I encourage as best practice to use the AotHelper and link.xml solutions more than the Preserve attribute for the reason that you can bundle up the configs into a single file, making it easier to get an overview of your configuration.

Ensure no stripping for ... : force compilation using the AotHelper disable bytecode stripping using a link.xml file disable bytecode stripping using the Preserve attribute
non-generic class
generic class
generic variants (ex: List<MyClass>) that's only referenced via reflection
entire assembly
members (methods, fields, properties) [1]
inaccessible types (ex: private or internal classes/members)
read-only code (ex: precompiled DLLs, or C# source code from UPM packages)

| Extra | intellisense support | ✔ | ❌ | ✔ errors when misconfigured, i.e. known to be correctly configured without doing a full rebuild using IL2CPP | ✔ | ❌ | ✔ configs for multiple types can be placed in a single file | ✔ | ✔ | ❌ does not need to reference UnityEngine.dll | ✔ | ✔ | ❌

Clone this wiki locally