Need to loosen my bindings

Microsoft .NET’s runtime provides an execution engine for Just-In-Time compiled code, but it also has the clandestine capability to pre-compile code and cache it on disk. This at first seems a little odd, since the point of environments like .NET Framework and Java are supposedly designed to offer machine-independent, ‘virtual’ code. I suppose that .NET’s native image support was introduced to solve some performance pitfalls of using Intermediate Language code, which needs to be compiled dynamically as it runs. Native Images would not suffer from this performance loss, since the compilation has been done in advance.

Native images can become invalid, however, and cause some very strange errors. In one case, one of our programs was crashing at random points in the usage, and in most cases, the program would actually fail to even start, throwing a scary-looking invalid program exception and offering the chance to debug, which presents some users with  and obtuse error message and if a debugger is installed, a yellow arrow pointing at a machine instruction that nobody who has started programming a computer after 1987 really understands.

Theoretically, of course, invalid native images should not occur. But if we understand how these native images are created, it’s possible to see some holes in Microsoft’s design.

For starters, native images are typically created when a program is installed, and the process appears to be automatic — Windows Installer knows that .NET assemblies are contained in an MSI by some hocus-pocus and ngen.exe is invoked to create a cache of native images for all assemblies in the MSI.

If the native images are never modified, there is a possibility that they could become invalid, if, say the .NET Framework environment had changed. If the Framework is patched or re-installed, there could be outdated reference in the native image that would cause the program to crash where it would not if it were properly loaded and JITted in near-real time. Microsoft have thought about this and designed the Framework to examine the .NET Runtime for changes that would cause a problem. If, for instance, mscorwks.dll, mscoree.dll, or other runtime libraries have changed, this will force a new native image generation when a cached assembly tries to load. Likewise, any changes to dependent assemblies, even if they have cached native images, will force a ‘cascading’ recompilation of native images for all dependent assemblies.

It sounds like Microsoft have thought of everything, but, alas, no, there are situations where an invalid native image is sitting on the hard disk, waiting to strike. Microsoft know that when they apply changes to the .NET Framework, such as the updates that may be distributed by Windows Update, that the runtime’s native image cache needs to be updated. So these updates run NGEN.exe /update to refresh the native images so that they are no longer invalid. Sounds all well and good — but there are some situations where multiple automatic updates have resulted in invalid native images that the runtime thinks are still valid, probably because the system really requires a reboot after running the first .NET update, but Automatic Updates silently suppresses it and applies a second .NET update.

If you come across strange behaviour in a managed .NET program, it may be useful to rule out the native image as the cause before accusing your program’s vendor of releasing buggy code! It is possible to determine if the program you are running is the JITted version, or a native image, by using our old friend, the Fusion Log Viewer. Setting this tool up as described in the previous link will create a log entry any time a .NET assembly is loaded by your program. Because Fusion Log Viewer can discriminate between bindings to native assemblies and ones that are purely Intermediate Language, it’s plain to see whether the assemblies are being loaded from cache or compiled dynamically by mscorjit.dll.

If the errant program is loading lots of native-image assemblies, running %systemroot%Microsoft.netframeworkv2.0.50727NGEN.exe /update may just put your program, and possibly many others, back in working order.