默认情况下启用 AES-NI 内在函数?

Posted

技术标签:

【中文标题】默认情况下启用 AES-NI 内在函数?【英文标题】:AES-NI intrinsics enabled by default? 【发布时间】:2014-05-28 07:23:04 【问题描述】:

Oracle 在 AES-NI 方面对 Java 8 有这样的看法:

添加了硬件内部函数以使用高级加密标准 (AES)。 UseAES 和 UseAESIntrinsics 标志可用于启用 英特尔硬件的基于硬件的 AES 内在函数。硬件 必须是 2010 年或更新的 Westmere 硬件。例如,要启用 硬件 AES,使用以下标志:

-XX:+UseAES -XX:+UseAESIntrinsics

要禁用硬件 AES,请使用以下标志:

-XX:-UseAES -XX:-UseAESIntrinsics

但它并不表示默认情况下是否启用 AES 内在函数(对于支持它的处理器)。所以问题很简单:如果处理器支持 AES-NI,是否使用 AES 内部函数?

额外问题:有什么方法可以测试是否使用了 AES-NI?我想您可以根据性能进行猜测,但这不是最佳或确定的测试方式。


对于不熟悉 AES-NI 内在函数的读者:它使用 AES-NI 指令集将字节码替换为预编译的机器代码。这是由 JVM 发生的,因此它不会出现在 Java 运行时的 API 或字节码中。

【问题讨论】:

【参考方案1】:

该标志默认为true,如果检测失败将设置为false,因此您可以简单地使用+PrintFlagsFinal来查看是否使用:

我的笔记本电脑没有 AES-NI:

C:\>"C:\Program Files\Java\jdk1.7.0_51\bin\java" -XX:+PrintFlagsFinal -version | find "UseAES"
     bool UseAES                                    = false           product
     bool UseAESIntrinsics                          = false           product
java version "1.7.0_51"
Java(TM) SE Runtime Environment (build 1.7.0_51-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.51-b03, mixed mode)

在桌面上相同使用 AES-NI:

C:\>"C:\Program Files\Java\jdk7\bin\java" -XX:+PrintFlagsFinal -version | find "AES"
     bool UseAES                                    = true            product
     bool UseAESIntrinsics                          = true            product

java version "1.7.0_51"
Java(TM) SE Runtime Environment (build 1.7.0_51-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.51-b03, mixed mode)

C:\>"C:\Program Files (x86)\Java\jre7\bin\java" -XX:+PrintFlagsFinal -version | find "AES"
     bool UseAES                                    = true            product
     bool UseAESIntrinsics                          = true            product

java version "1.7.0_51"
Java(TM) SE Runtime Environment (build 1.7.0_51-b13)
Java HotSpot(TM) Client VM (build 24.51-b03, mixed mode, sharing)

因此,它适用于最新 Java 7 的 x64 和 i686 (WOW64)。该功能由 https://bugs.openjdk.java.net/browse/JDK-7184394 引入并向后移植到 7u40 和 7u45。


重要提示:AES-NI 可能仅在服务器虚拟机上可用。

Oracle 在a bug report was filed 之后确认了这一点。当他们创建引入它的 Java 8 的功能列表时,这条重要的信息丢失了(后来它也被向后移植到 7)。可以通过在javajavaw 命令行上提供-server 选项来显式选择服务器VM。

【讨论】:

【参考方案2】:

不能评论(愚蠢的 SO 规定需要超过 50 个学分!)。 This mailthread from openjdk 说,默认情况下启用所有 AES 内在函数。虽然我不确定有多少 Oracle 核心 VM 代码与 openjdk 共享。 如果您阅读了整个线程,他们还会讨论 32 位 VM 上的挑战,这可能解释了您在第二次测试运行时遇到的问题。

关于您的测试(抱歉,无法评论),您不认为 CPU 的差异会产生很大的不同吗? Core i7 是四核的,通常具有更好的时钟速度。那不会有所作为吗?我猜想从 21s(core i5、32bitVM、AES-NI off)到​​ 8s(core i7、64bitVM、AES-NI off)的转变是 i5 和 i7 之间的区别。 从8s到3s的提升,虽然不是7倍,但确实值得一试! :) 关于检测机制 - 似乎没有直接的方法。如果您启用了这些标志,并且如果它找不到 AES 支持 - as per this bug report,JVM 会抛出警告“AES 内在函数在此 CPU 上不可用”。

【讨论】:

AES CBC 本质上是严格线性的,所以多核无关紧要(当然我使用任务调度程序运行或启用 top)。此外,在 i5 上,我可以清楚地看到在性能方面没有区别,启用或禁用。最后,似乎在错误报告中修复了对额外 CPU 指令的旧检查。我没有看到任何结论性的东西来解释为什么不支持旧 CPU。随着 7 倍的增长:即在 i5 32 位和更新的 i7 位上运行的 Java 8。相同的类字节仍然有巨大的增长:) 哦,对于普通应用程序,i7 的执行速度似乎是 i5 的 2 倍左右(我专门测试过 C++ 编译),这要快得多,但差距远没有 7 倍.请注意,经过优化的 64 位应用程序可能会获得额外的加速。我猜那些较新的 CPU 确实会有所作为。 好的。说得通。在我自己的测试中,AES 标志似乎没有得到尊重。无论我启用或禁用标志,执行时间都是相同的。因此,如果我们需要 CPU 支持带来的实际差异,我们可能需要相同的 CPU——一个禁用 AES-NI,另一个启用。这里的一个人有一些有趣的结果(不是 java),内核禁用了 AES-NI:ask.fedoraproject.org/en/question/29298/… 他的结果非常接近你的结果(很多情况下是 7 倍) 我还注意到 java 8 在加密库中带来了一些改进。对于小型测试(1k、2k 缓冲 AES-256 加密),执行时间是 java 7 的 2 倍。 有一个错误报告指出 AES init 使用相同的密钥 - 如果使用相同的密钥,则无需重新计算 AES 的密钥计划。但我认为之前集成了一个 - 但是它可以解释小缓冲区的速度差异 - 你可以使用Cipher.getInstance() 看看是否使用相同的实例是否会有所不同。

以上是关于默认情况下启用 AES-NI 内在函数?的主要内容,如果未能解决你的问题,请参考以下文章

默认情况下启用 UnsafeHeaderParsing 是不是可以接受?

默认情况下在我的 android 应用中启用所有通知设置

默认情况下启用自动修复。使用单字符串形式

如何在启用默认 EBS 加密的情况下使用 Beanstalk?

Nodejs API:默认情况下似乎启用了 CORS

无法写入核心转储。默认情况下,在 Windows 的客户端版本上不启用小型转储