缓解:新的 64 位 JIT 编译器

自 .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 块中退出之前测试条件,且在 catchfinally 块中计算的条件相同,那么新版 64 位实时编译器会在优化代码时从 catchfinally 块中删除 if 条件。 因此,catchfinally 块中的 if 语句代码会无条件地执行。

已知问题的缓解措施

如果遇到上面列出的问题,可以通过执行下列任一操作来解决:

  • 升级到 .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>  
    
  • 对于每个用户,可以将名为 useLegacyJitREG_DWORD 值添加到注册表的 HKEY_CURRENT_USER\SOFTWARE\Microsoft\.NETFramework 密钥中。 如果值为 1,可以启用旧版 64 位 JIT 编译器;如果值为 0,可以禁用旧版编译器,启用新版 64 位 JIT 编译器。

  • 对于每台计算机,可以将名为 useLegacyJitREG_DWORD 值添加到注册表的 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework 密钥中。 如果值为 1,可以启用旧版 64 位 JIT 编译器;如果值为 0,可以禁用旧版编译器,启用新版 64 位 JIT 编译器。

还可以在 Microsoft Connect 上报告 bug,告诉我们你遇到的问题。

请参阅