- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
假设你做简单的事情:
public class Main {
public static void main(String[] args) {
long started = System.currentTimeMillis();
try {
new URL(args[0]).openConnection();
} catch (Exception ignore) {
}
System.out.println(System.currentTimeMillis() - started);
}
}
现在用 http://localhost 运行它作为 args[0]
完成需要 ~100 毫秒
。
现在尝试 https://localhost
它需要 5000+ 毫秒
。
现在在 linux 或 docker 中运行相同的东西:
~100 毫秒
~350 毫秒
这是为什么?为什么平台之间会有如此巨大的差异?你能做些什么?
对于长时间运行的应用程序服务器和具有自己的长而繁重的初始化序列的应用程序,这 5 秒可能无关紧要。
但是,有很多应用程序最初的 5 秒“挂起”很重要,可能会变得令人沮丧......
最佳答案
(注意:另请参阅此答案末尾的最新更新)
解释
这是默认的原因 SecureRandom
供应商。
在 Windows 上,有 2 个 SecureRandom
提供者可用:
- provider=SUN, type=SecureRandom, algorithm=SHA1PRNG
- provider=SunMSCAPI, type=SecureRandom, algorithm=Windows-PRNG
在 Linux 上(使用 Oracle JDK 8u162 在 Alpine docker 中测试):
- provider=SUN, type=SecureRandom, algorithm=NativePRNG
- provider=SUN, type=SecureRandom, algorithm=SHA1PRNG
- provider=SUN, type=SecureRandom, algorithm=NativePRNGBlocking
- provider=SUN, type=SecureRandom, algorithm=NativePRNGNonBlocking
这些在 jre/lib/security/java.security
中指定文件。
security.provider.1=sun.security.provider.Sun
...
security.provider.10=sun.security.mscapi.SunMSCAPI
默认情况下,第一个 SecureRandom
使用提供者。在 Windows 上,默认值为 sun.security.provider.Sun
,当 JVM 使用 -Djava.security.debug="provider,engine=SecureRandom"
运行时,此实现报告如下:
Provider: SecureRandom.SHA1PRNG algorithm from: SUN
provider: Failed to use operating system seed generator: java.io.IOException: Required native CryptoAPI features not available on this machine
provider: Using default threaded seed generator
而且默认的线程种子生成器非常慢。
您需要使用 SunMSCAPI
供应商。
方案一:配置
重新排序配置中的供应商:
编辑 jre/lib/security/java.security
:
security.provider.1=sun.security.mscapi.SunMSCAPI
...
security.provider.10=sun.security.provider.Sun
我不知道这可以通过系统属性来完成。
或者也许是,使用 -Djava.security.properties
(未经测试,see this)
解决方案 2:程序化
以编程方式重新排序提供者:
Optional.ofNullable(Security.getProvider("SunMSCAPI")).ifPresent(p->{
Security.removeProvider(p.getName());
Security.insertProviderAt(p, 1);
});
JVM 现在报告以下 ( -Djava.security.debug="provider,engine=SecureRandom"
):
Provider: SecureRandom.Windows-PRNG algorithm from: SunMSCAPI
解决方案 3:程序化 v2
灵感来自 this idea , 下面的一段代码只插入一个 SecureRandom
服务,从现有动态配置 SunMSCAPI
提供者没有明确依赖 sun.*
类。这也避免了与 SunMSCAPI
的所有服务不加区别地确定优先级相关的潜在风险。供应商。
public interface WindowsPRNG {
static void init() {
String provider = "SunMSCAPI"; // original provider
String type = "SecureRandom"; // service type
String alg = "Windows-PRNG"; // algorithm
String name = String.format("%s.%s", provider, type); // our provider name
if (Security.getProvider(name) != null) return; // already registered
Optional.ofNullable(Security.getProvider(provider)) // only on Windows
.ifPresent(p-> Optional.ofNullable(p.getService(type, alg)) // should exist but who knows?
.ifPresent(svc-> Security.insertProviderAt( // insert our provider with single SecureRandom service
new Provider(name, p.getVersion(), null) {{
setProperty(String.format("%s.%s", type, alg), svc.getClassName());
}}, 1)));
}
}
性能
<140 msec
(而不是 5000+ msec
)
详情
有人调用new SecureRandom()
当你使用 URL.openConnection("https://...")
时调用堆栈的某个地方
它调用getPrngAlgorithm()
(参见 SecureRandom:880)
这首先返回 SecureRandom
它找到的提供商。
出于测试目的,请调用 URL.openConnection()
可以替换为:
new SecureRandom().generateSeed(20);
免责声明
我不知道提供商重新排序会导致任何负面影响。然而,可能有一些,特别是考虑到默认提供者选择算法。
无论如何,至少在理论上,从功能的角度来看,这对应用程序应该是透明的。
更新 2019-01-08
Windows 10(版本 1803):无法再在任何最新的 JDK 上重现此问题(从旧的 oracle 1.7.0_72 到 openjdk“12-ea”2019-03-19 都进行了测试)。
看起来这是 Windows 问题,已在最新的操作系统更新中修复。在最近的 JRE 版本中也可能发生也可能没有发生相关更新。但是,即使我最老的 JDK 7 update 72 安装也确实受到了影响,而且绝对没有以任何方式修补,我也无法重现原始问题。
使用此解决方案时仍有微小的性能提升(平均约 350 毫秒),但默认行为不再遭受无法忍受的 5 秒以上惩罚。
关于java - SecureRandom 初始化缓慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49322948/
我是 Spring 新手,这就是我想要做的事情: 我正在使用一个基于 Maven 的库,它有自己的 Spring 上下文和 Autowiring 字段。 它的bean配置文件是src/test/res
我在我的测试脚本中有以下列表初始化: newSequenceCore=["ls", "ns", "*", "cm", "*", "ov", "ov", "ov", "ov", "kd"] (代表要在控
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Class construction with initial values 当我查看 http://en.
我得到了成员变量“objectCount”的限定错误。编译器还返回“ISO C++ 禁止非常量静态成员的类内初始化”。这是主类: #include #include "Tree.h" using n
我有如下所示的a.h class A { public: void doSomething()=0; }; 然后我有如下所示的b.h #include "a.h" class b: publi
我需要解析 Firebase DataSnapshot (一个 JSON 对象)转换成一个数据类,其属性包括 enum 和 list。所以我更喜欢通过传递 DataSnapshot 来手动解析它进入二
我使用 JQuery 一段时间了,我总是使用以下代码来初始化我的 javascript: $(document).ready( function() { // Initalisation logic
这里是 Objective-C 菜鸟。 为什么会这样: NSString *myString = [NSString alloc]; [myString initWithFormat:@"%f", s
我无法让核心数据支持的 NSArrayController 在我的代码中正常工作。下面是我的代码: pageArrayController = [[NSArrayController alloc] i
我对这一切都很陌生,并且无法将其安装到我的后端代码中。它去哪里?在我的页脚下面有我所有的 JS? 比如,这是什么意思: Popup initialization code should be exec
这可能是一个简单的问题,但是嘿,我是初学者。 所以我创建了一个程序来计算一些东西,它目前正在控制台中运行。我决定向其中添加一个用户界面,因此我使用 NetBeans IDE 中的内置功能创建了一个 J
我有 2 个 Controller ,TEST1Controller 和 TEST2Controller 在TEST2Controller中,我有一个initialize()函数设置属性值。 如果我尝
据我所知, dependentObservable 在声明时会进行计算。但如果某些值尚不存在怎么办? 例如: var viewModel ={}; var dependentObservable1 =
我正在阅读 POODR 这本书,它使用旧语法进行默认值初始化。我想用新语法实现相同的功能。 class Gear attr_reader :chainring, :cog, :wheel de
我按照 polymer 教程的说明进行操作: https://www.polymer-project.org/3.0/start/install-3-0 (我跳过了可选部分) 但是,在我执行命令“po
很抱歉问到一个非常新手的Kotlin问题,但是我正在努力理解与构造函数和初始化有关的一些东西。 我有这个类和构造函数: class TestCaseBuilder constructor(
假设我们有一个包含 30 列和 30 行的网格。 生命游戏规则简而言之: 一个小区有八个相邻小区 当一个细胞拥有三个存活的相邻细胞时,该细胞就会存活 如果一个细胞恰好有两个或三个活的相邻细胞,那么它就
我是 MQTT 和 Android 开放附件“AOA” 的新手。在阅读教程时,我意识到,在尝试写入 ByteArrayOutputStream 类型的变量之前,应该写入 0 或 0x00首先到该变量。
我有 2 个 Controller ,TEST1Controller 和 TEST2Controller 在TEST2Controller中,我有一个initialize()函数设置属性值。 如果我尝
我有一个inotify /内核问题。我正在使用“inotify” Python项目进行观察,但是,我的问题仍然是固有的关于inotify内核实现的核心。 Python inotify项目处理递归ino
我是一名优秀的程序员,十分优秀!