New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception during deserialization #5855

Closed
KyleGobel opened this Issue May 25, 2018 · 7 comments

Comments

Projects
None yet
2 participants
@KyleGobel

KyleGobel commented May 25, 2018

Hey,

Just wanted to give this a shot on a fairly simple CLI app. When attempting to run I get this error:

Followed one of your examples and ran

dotnet publish -r win-x64 -c Release

When attempting to run my app I get:

(Line: 1, Col: 1, Idx: 0) - (Line: 1, Col: 1, Idx: 0): Exception during deserialization

I'm not really sure where this message is coming from. Any pointers debugging this? There is a little json deserialization going in there, does this essentially mean one of my the dependencies i'm using is doing something unsupported?

@MichalStrehovsky

This comment has been minimized.

Member

MichalStrehovsky commented May 25, 2018

To troubleshoot this further:

  1. Open the compiled executable with Visual Studio debugger (File -> Open -> Project/Solution, navigate to the compiled EXE and open it).
  2. Open the Breakpoints window (Debug -> Windows -> Breakpoints)
  3. In the Breakpoints window click New -> Function breakpoint
  4. In the new window: Function name = RhpThrowEx, Language = C++

You just created a breakpoint on all managed exception.

Hit F5 to run your app and try to debug. Let us know what you find.

@KyleGobel

This comment has been minimized.

KyleGobel commented May 25, 2018

Ok I did that. First thing it told me is couldn't find ExceptionHandling.asm.

I downloaded the current master at src/Native/Runtime/amd64/ExceptionHandling.asm and pointed it there.

VS gave me a warning that it's not the module it was built with or w/e, but it does break in this assembly file. I have no clue what's going on from here. Hitting continue I hit this breakpoint about 5 times.

I'm guessing this info isn't all that helpful to you. Should I be expecting something different or some messages anywhere (or should I be inspecting some values)

@MichalStrehovsky

This comment has been minimized.

Member

MichalStrehovsky commented May 25, 2018

Is there anything interesting in the callstack at the time the exceptions are thrown?

@KyleGobel

This comment has been minimized.

KyleGobel commented May 26, 2018

So essentially this is what's failing (was able to narrow it down to minimal code)

class Program
{
    static int Main(string[] args)
    {
        var instance = Activator.CreateInstance(typeof(Example));
        return 0;
    }

    class Example
    {
    }
}

Output:

Unhandled Exception: System.MissingMethodException: No parameterless constructor defined for this object.
@MichalStrehovsky

This comment has been minimized.

Member

MichalStrehovsky commented May 28, 2018

Unhandled Exception: System.MissingMethodException: No parameterless constructor defined for this object.

You'll typically see this if reflection is trying to access a method that was otherwise unused in the program.

The CoreRT compiler starts compiling your Main, then continues to compile everything referenced from Main that was not compiled yet, then references from those methods etc. until there's nothing left to compile. You would see that the CreateInstance call in your sample program would "fix itself", if you add a new Example(); line into Main and recompile. We do this because compiling everything in the framework and all NuGet packages your app might references would take a long time and produce tens of megabytes of code.

The other alternative to fix this is with "RD.XML" - this is a separate file added as a compiler input that tells the compiler what other things to compile, on top of the above algorithm. You can add this file to your project like this.

To keep things simple, you can have a line like this in it to compile everything in an assembly with the specified name.

@KyleGobel

This comment has been minimized.

KyleGobel commented May 28, 2018

Ahhh, that makes a lot of sense.

Essentially the compiler has no idea about these types so doesn't include them unless you specifically tell it to (If I'm thinking about this correctly).

Thanks for helping me here.

Is there anything that can or will ever be done in the future with Reflection stuff that will make this more 'automatic'? Or will this always be a part of any native compilation stuff?

@MichalStrehovsky

This comment has been minimized.

Member

MichalStrehovsky commented May 28, 2018

Is there anything that can or will ever be done in the future with Reflection stuff that will make this more 'automatic'?

We know how to do this for simple things like your example - we have a component in the closed source .NET Native compiler that can analyze patterns like this, determine what the program will be reflecting on at compile time, and use that information to pregenerate the necessary things. The problem gets harder as you're trying to fix it in a general purpose way. The general problem was actually proved to be unsolvable in 1936 (you can't write a program that will take another program as input and predict what the input program will do at runtime, in general).

There are only two really general purpose solutions I can think of:

  • Always compile everything. This obviously means slower compilation times and bigger executable sizes.
  • Carry around information that will let you interpret, or JIT compile things that didn't get compiled ahead of time.

What works great for ahead of time compiled .NET is "ahead of time reflection". Many of the things people try to solve with reflection at runtime could be solved at compile time. E.g. for the serialization sample, you could imagine a component that generates code to serialize and deserialize classes at the time of build. This would make things faster, and ahead of time compilation friendlier.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment