缓解:新的 64 位 JIT 编译器Mitigation: New 64-bit JIT Compiler

自 .NET Framework 4.6 起,运行时包括新版 64 位 JIT 编译器,用于执行实时编译。Starting with the .NET Framework 4.6, the runtime includes a new 64-bit JIT compiler for just-in-time compilation. 此更改不会影响 32 位 JIT 编译器的编译。This change does not affect compilation with the 32-bit JIT compiler.

意外行为或异常Unexpected behavior or exceptions

在某些情况下,使用新版 64 位 JIT 编译器进行编译会导致运行时异常抛出,或导致执行旧版 64 位 JIT 编译器编译的代码时无法观察到的行为发生。In some cases, compilation with the new 64-bit JIT compiler results in a runtime exception or in behavior that is not observed when executing code compiled by the older 64-bit JIT compiler. 已知差异如下:The known differences include the following:

重要

所有这些已知问题已在随 .NET Framework 4.6.2 一起发布的新版 64 位编译器中得到了解决。All of these known issues have been addressed in the new 64-bit compiler released with the .NET Framework 4.6.2. 大多数问题也已在 Windows 更新随附的 .NET Framework 4.6 和 4.6.1 的服务版本中得到解决。Most have also been addressed in service releases of the .NET Framework 4.6 and 4.6.1 that are included with Windows Update. 若要消除这些问题,请确保 Windows 是最新版本,或升级到 .NET Framework 4.6.2。You can eliminate these issues by ensuring that your version of Windows is up to date, or by upgrading to the .NET Framework 4.6.2.

  • 在某些情况下,在启用优化的发布版本中,取消装箱操作可能会引发 NullReferenceExceptionUnder certain conditions, an unboxing operation may throw a NullReferenceException in Release builds with optimization turned on.

  • 在某些情况下,在大型方法主体中执行生产代码可能会引发 StackOverflowExceptionIn some cases, execution of production code in a large method body may throw a StackOverflowException.

  • 在某些情况下,传递给方法的结构在发布版本中被视为引用类型,而不是值类型。Under certain conditions, structures passed to a method are treated as reference types rather than value types in Release builds. 此问题的表现形式之一是,集合中各个项的显示顺序出现异常。One of the manifestations of this issue is that the individual items in a collection appear in an unexpected order.

  • 在某些情况下,如果启用了优化,无法正确比较 UInt16 值与其高位集。Under certain conditions, the comparison of UInt16 values with their high bit set is incorrect if optimization is enabled.

  • 在某些情况下,尤其是在初始化数组值时,通过 OpCodes.Initblk IL 指令执行的内存初始化可能会使用不正确的值初始化内存。Under certain conditions, particularly when initializing array values, memory initialization by the OpCodes.Initblk IL instruction may initialize memory with an incorrect value. 这可能会导致未经处理的异常抛出或输出不正确。This can result either in an unhandled exception or incorrect output.

  • 在某些极少数情况下,如果启用了编译器优化,条件位测试可能会返回错误的 Boolean 值或引发异常。Under certain rare conditions, a conditional bit test can return the incorrect Boolean value or throw an exception if compiler optimizations are enabled.

  • 在某些情况下,如果 if 语句用于在进入 try 块之前和从 try 块中退出之前测试条件,且在 catchfinally 块中计算的条件相同,那么新版 64 位 JIT 编译器会在优化代码时从 catchfinally 块中删除 if 条件。Under certain conditions, if an if statement is used to test for a condition before entering a try block and in the exit from the try block, and the same condition is evaluated in the catch or finally block, the new 64-bit JIT compiler removes the if condition from the catch or finally block when it optimizes code. 因此,catchfinally 块中的 if 语句代码会无条件地执行。As a result, code inside the if statement in the catch or finally block is executed unconditionally.

已知问题的缓解措施Mitigation of known issues

如果遇到上面列出的问题,可以通过执行下列任一操作来解决:If you encounter the issues listed above, you can address them by doing any of the following:

  • 升级到 .NET Framework 4.6.2。Upgrade to the .NET Framework 4.6.2. .NET Framework 4.6.2 随附的新版 64 位编译器解决了上面列出的所有已知问题。The new 64-bit compiler included with the .NET Framework 4.6.2 addresses each of these known issues.

  • 运行 Windows 更新,以确保 Windows 是最新版本。Ensure that your version of Windows is up to date by running Windows Update. .NET Framework 4.6 和 4.6.1 服务更新可解决以上问题,取消装箱操作中的 NullReferenceException 除外。Service updates to the .NET Framework 4.6 and 4.6.1 address each of these issues except the NullReferenceException in an unboxing operation.

  • 使用旧版 64 位 JIT 编译器进行编译。Compile with the older 64-bit JIT compiler. 请参阅其他问题的缓解措施部分,详细了解如何执行此操作。See the Mitigation of other issues section for more information on how to do this.

其他问题的缓解措施Mitigation of other issues

如果遇到的是旧版和新版 64 位 JIT 编译器编译的代码的其他任何行为差异,或是使用新版 64 位 JIT 编译器编译的应用程序的调试和发布版本的其他任何行为差异,可以使用旧版 64 位 JIT 编译器编译应用程序,具体操作如下:If you encounter any other difference in behavior between code compiled with the older 64-bit compiler and the new 64-bit JIT compiler, or between the debug and release versions of your app that are both compiled with the new 64-bit JIT compiler, you can do the following to compile your app with the older 64-bit JIT compiler:

  • 对于每个应用程序,可以将 <useLegacyJit> 元素添加到应用程序的配置文件中。On a per-application basis, you can add the <useLegacyJit> element to your application's configuration file. 下面的代码禁用新版 64 位 JIT 编译器,改用旧版 64 位 JIT 编译器进行编译。The following disables compilation with the new 64-bit JIT compiler and instead uses the legacy 64-bit JIT compiler.

    <?xml version ="1.0"?>  
    <configuration>  
        <runtime>  
           <useLegacyJit enabled="1" />  
        </runtime>  
    </configuration>  
    
  • 对于每个用户,可以将名为 useLegacyJitREG_DWORD 值添加到注册表的 HKEY_CURRENT_USER\SOFTWARE\Microsoft\.NETFramework 密钥中。On a per-user basis, you can add a REG_DWORD value named useLegacyJit to the HKEY_CURRENT_USER\SOFTWARE\Microsoft\.NETFramework key of the registry. 如果值为 1,可以启用旧版 64 位 JIT 编译器;如果值为 0,可以禁用旧版编译器,启用新版 64 位 JIT 编译器。A value of 1 enables the legacy 64-bit JIT compiler; a value of 0 disables it and enables the new 64-bit JIT compiler.

  • 对于每台计算机,可以将名为 useLegacyJitREG_DWORD 值添加到注册表的 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework 密钥中。On a per-machine basis, you can add a REG_DWORD value named useLegacyJit to the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework key of the registry. 如果值为 1,可以启用旧版 64 位 JIT 编译器;如果值为 0,可以禁用旧版编译器,启用新版 64 位 JIT 编译器。A value of 1 enables the legacy 64-bit JIT compiler; a value of 0 disables it and enables the new 64-bit JIT compiler.

还可以在 Microsoft Connect 上报告 bug,告诉我们你遇到的问题。You can also let us know about the problem by reporting a bug on Microsoft Connect.

请参阅See also