共用方式為


緩解措施:新的 64 位 JIT 編譯程式

從 .NET Framework 4.6 開始,執行階段包含用於即時編譯的新 64 位 JIT 編譯器。 這項變更不會影響使用32位 JIT 編譯程式的編譯。

非預期的行為或例外狀況

在某些情況下,使用新的 64 位 JIT 編譯程式進行編譯會導致運行時間例外狀況,或執行舊版 64 位 JIT 編譯程式所編譯的程式代碼時,不會觀察到的行為。 下列是已知的差異︰

這很重要

所有這些已知問題都已在使用 .NET Framework 4.6.2 發行的新 64 位編譯程式中解決。 大部分也已在 Windows Update 隨附的 .NET Framework 4.6 和 4.6.1 服務版本中解決。 您可以藉由確保您的 Windows 版本是最新的,或升級至 .NET Framework 4.6.2,來消除這些問題。

  • 在某些情況下,已開啟最佳化的發行組建中的 Unboxing 作業可能會擲回 NullReferenceException

  • 在某些情況下,執行大型方法主體中的實際執行程式碼可能會擲回 StackOverflowException

  • 在特定情況下,傳遞至方法的結構會被視為參考型別,而不是 Release 組建中的實值型別。 這個問題的其中一種表現,就是集合中的個別項目會以非預期的順序出現。

  • 在某些情況下,如果啟用最佳化,UInt16 的值在設定高位元時的比較會不正確。

  • 在某些情況下,尤其是初始化陣列值時,使用 OpCodes.Initblk IL 指令初始化記憶體,可能會以不正確的值初始化記憶體。 這會造成未處理的例外狀況或不正確的輸出。

  • 在少數情況下,如果啟用編譯器最佳化,條件式位元測試可能會傳回不正確的 Boolean 值或擲回例外狀況。

  • 某些狀況下,如果使用 if 陳述式在進入 try 區塊之前和自 try 區塊退出時測試某項條件,而且也在 catchfinally 區塊中評估該條件時,新版 64 位元 JIT 編譯器在最佳化程式碼時會將 if 條件自 catchfinally 區塊中移除。 因此,ifcatch 區塊的 finally 陳述式中的程式碼會無條件執行。

已知問題的緩解措施

如果您遇到上述問題,可以採取以下任一種方式來解決︰

  • 升級至 .NET Framework 4.6.2。 隨附於 .NET Framework 4.6.2 中的新版 64 位元編譯器可以解決這些已知問題。

  • 執行 Windows Update,確定您的 Windows 已更新至最新版本。 .NET Framework 4.6 和 4.6.1 的服務更新可解決上述問題中除了 Unboxing 作業之 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_DWORDuseLegacyJit 值加入至登錄的 HKEY_CURRENT_USER\SOFTWARE\Microsoft\.NETFramework 索引鍵。 值為 1 會啟用舊版 64 位元 JIT 編譯器;值為 0 會停用它,並啟用新版 64 位元 JIT 編譯器。

  • 若以每一電腦為基礎,您可以將名為 REG_DWORDuseLegacyJit 值加入至登錄的 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework 索引鍵。 值為 1 會啟用舊版 64 位元 JIT 編譯器;值為 0 會停用它,並啟用新版 64 位元 JIT 編譯器。

您也可以前往 Microsoft Connect 回報錯誤,讓我們知道問題所在。

另請參閱