从 .NET Framework 4.6 开始,运行时包含用于实时编译的新 64 位 JIT 编译器。 此更改不会影响使用 32 位 JIT 编译器的编译。
意外行为或异常
在某些情况下,使用新的 64 位 JIT 编译器进行编译会导致运行时异常或执行由旧 64 位 JIT 编译器编译的代码时不观察到的行为。 已知差异如下:
重要
所有这些已知问题已在 .NET Framework 4.6.2 发布的新 64 位编译器中得到解决。 大多数也已在 Windows 更新随附的 .NET Framework 4.6 和 4.6.1 的服务版本中得到解决。 你可以通过确保 Windows 版本是最新的,或通过升级到 .NET Framework 4.6.2 来消除这些问题。
在某些情况下,在启用优化的发布版本中,取消装箱操作可能会引发 NullReferenceException。
在某些情况下,在大型方法主体中执行生产代码可能会引发 StackOverflowException。
在某些情况下,传递给方法的结构被视为引用类型,而不是发布版本中的值类型。 此问题的表现形式之一是,集合中各个项的显示顺序出现异常。
在某些情况下,如果启用了优化,无法正确比较 UInt16 值与其高位集。
在某些情况下,尤其是在初始化数组值时,通过 OpCodes.Initblk IL 指令执行的内存初始化可能会使用不正确的值初始化内存。 这可能会导致未经处理的异常抛出或输出不正确。
在某些极少数情况下,如果启用了编译器优化,条件位测试可能会返回错误的 Boolean 值或引发异常。
在某些情况下,如果
if
语句用于在进入try
块之前和从try
块中退出之前测试条件,且在catch
或finally
块中计算的条件相同,那么新版 64 位实时编译器会在优化代码时从if
或catch
块中删除finally
条件。 因此,if
或catch
块中的finally
语句代码会无条件地执行。
缓解已知问题
如果遇到上面列出的问题,可以通过执行下列任一操作来解决:
升级到 .NET Framework 4.6.2。 .NET Framework 4.6.2 随附的新版 64 位编译器解决了上面列出的所有已知问题。
运行 Windows 更新,以确保 Windows 是最新版本。 .NET Framework 4.6 和 4.6.1 服务更新可解决以上问题,取消装箱操作中的 NullReferenceException 除外。
使用旧版 64 位 JIT 编译器进行编译。 请参阅其他问题的缓解措施部分,详细了解如何执行此操作。
缓解其他问题
如果遇到的是旧版和新版 64 位 JIT 编译器编译的代码的其他任何行为差异,或是使用新版 64 位 JIT 编译器编译的应用程序的调试和发布版本的其他任何行为差异,可以使用旧版 64 位 JIT 编译器编译应用程序,具体操作如下:
根据应用程序,您可以将 <useLegacyJit> 元素添加到应用程序的配置文件中。 下面的代码禁用新版 64 位 JIT 编译器,改用旧版 64 位 JIT 编译器进行编译。
<?xml version ="1.0"?> <configuration> <runtime> <useLegacyJit enabled="1" /> </runtime> </configuration>
对于每个用户,可以将名为
REG_DWORD
的useLegacyJit
值添加到注册表的HKEY_CURRENT_USER\SOFTWARE\Microsoft\.NETFramework
密钥中。 如果值为 1,可以启用旧版 64 位 JIT 编译器;如果值为 0,可以禁用旧版编译器,启用新版 64 位 JIT 编译器。对于每台计算机,可以将名为
REG_DWORD
的useLegacyJit
值添加到注册表的HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework
密钥中。 如果值为 1,可以启用旧版 64 位 JIT 编译器;如果值为 0,可以禁用旧版编译器,启用新版 64 位 JIT 编译器。
还可以在 Microsoft Connect 上报告 bug,告诉我们你遇到的问题。