从 .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,告诉我们你遇到的问题。