本文介绍了服务响应时间慢:Java SecureRandom和/ dev / random – java程序员分享,有助于帮助完成毕业设计以及求职,是一篇很好的资料。
对技术面试,学习经验等有一些体会,在此分享。
我正在尝试调试Tomcat上部署的应用程序提供的一些慢速响应。
现在,我主要关注SecureRandom
和/dev/random
(其他一些可能的原因已被调查并排除)。
模式如下:
服务调用涉及加密和解密(AES / ECB / PKCS5Padding)。
SecureRandom初始化/重新填充是否有可能导致这种情况?
(尽管在catalina.log中写了一个日志,上面写着"Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [28,760] milliseconds."
)
另外,为了检查是否正在使用/dev/random
或/dev/urandom
,我使用了this question的测试。令我惊讶的是,与链接问题中发生的情况不同,我没有看到它们中的任何一个。
这些是strace
日志的最后几行:
3561 lstat("/usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/jsse.jar", {st_mode=S_IFREG|0644, st_size=258525, ...}) = 0 3561 open("/usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/jsse.jar", O_RDONLY) = 6 3561 stat("/dev/random", {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 8), ...}) = 0 3561 stat("/dev/urandom", {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 9), ...}) = 0 3561 open("/dev/random", O_RDONLY) = 7 3561 open("/dev/urandom", O_RDONLY) = 8 3561 unlink("/tmp/hsperfdata_xxxx/3560") = 0
那么,什么用于播种SecureRandom?
fyi,java -version
java version "1.6.0_32" OpenJDK Runtime Environment (IcedTea6 1.13.4) (rhel-7.1.13.4.el6_5-x86_64) OpenJDK 64-Bit Server VM (build 23.25-b01, mixed mode)
参考方案
我无法检查您的OpenJDK具体版本,但可以检查jdk6-b33。
SecureRandom使用SeedGenerator获取种子字节
public byte[] engineGenerateSeed(int numBytes) { byte[] b = new byte[numBytes]; SeedGenerator.generateSeed(b); return b; }
SeedGenerator从SunEntries获取seedSource
(字符串)
String egdSource = SunEntries.getSeedSource();
SunEntries
尝试首先从系统属性java.security.egd
获取源,如果找不到,则尝试从securerandom.source
属性文件获取java.security
属性,如果找不到该属性,则返回空白字符串。
// name of the *System* property, takes precedence over PROP_RNDSOURCE private final static String PROP_EGD = "java.security.egd"; // name of the *Security* property private final static String PROP_RNDSOURCE = "securerandom.source"; final static String URL_DEV_RANDOM = "file:/dev/random"; final static String URL_DEV_URANDOM = "file:/dev/urandom"; private static final String seedSource; static { seedSource = AccessController.doPrivileged( new PrivilegedAction<String>() { public String run() { String egdSource = System.getProperty(PROP_EGD, ""); if (egdSource.length() != 0) { return egdSource; } egdSource = Security.getProperty(PROP_RNDSOURCE); if (egdSource == null) { return ""; } return egdSource; } }); }
SeedGenerator
检查此值以初始化实例
// Static instance is created at link time private static SeedGenerator instance; private static final Debug debug = Debug.getInstance("provider"); final static String URL_DEV_RANDOM = SunEntries.URL_DEV_RANDOM; final static String URL_DEV_URANDOM = SunEntries.URL_DEV_URANDOM; // Static initializer to hook in selected or best performing generator static { String egdSource = SunEntries.getSeedSource(); // Try the URL specifying the source // e.g. file:/dev/random // // The URL file:/dev/random or file:/dev/urandom is used to indicate // the SeedGenerator using OS support, if available. // On Windows, the causes MS CryptoAPI to be used. // On Solaris and Linux, this is the identical to using // URLSeedGenerator to read from /dev/random if (egdSource.equals(URL_DEV_RANDOM) || egdSource.equals(URL_DEV_URANDOM)) { try { instance = new NativeSeedGenerator(); if (debug != null) { debug.println("Using operating system seed generator"); } } catch (IOException e) { if (debug != null) { debug.println("Failed to use operating system seed " + "generator: " + e.toString()); } } } else if (egdSource.length() != 0) { try { instance = new URLSeedGenerator(egdSource); if (debug != null) { debug.println("Using URL seed generator reading from " + egdSource); } } catch (IOException e) { if (debug != null) debug.println("Failed to create seed generator with " + egdSource + ": " + e.toString()); } } // Fall back to ThreadedSeedGenerator if (instance == null) { if (debug != null) { debug.println("Using default threaded seed generator"); } instance = new ThreadedSeedGenerator(); } }
如果来源是
final static String URL_DEV_RANDOM = "file:/dev/random";
要么
final static String URL_DEV_URANDOM = "file:/dev/urandom"
在Windows上使用NativeSeedGenerator
尝试在Linux上使用本机CryptoAPI
该类只是扩展了SeedGenerator.URLSeedGenerator
package sun.security.provider; import java.io.IOException; /** * Native seed generator for Unix systems. Inherit everything from * URLSeedGenerator. * */ class NativeSeedGenerator extends SeedGenerator.URLSeedGenerator { NativeSeedGenerator() throws IOException { super(); } }
并调用默认情况下加载/dev/random
的超类构造函数
URLSeedGenerator() throws IOException { this(SeedGenerator.URL_DEV_RANDOM); }
因此,在没有在系统属性/dev/random
或安全属性文件的java.security.egd
属性中未设置其他值之前,OpenJDK默认使用securerandom.source
。
如果要使用strace
查看读取结果,可以更改命令行并添加trace=open,read
表达式
sudo strace -o a.strace -f -e trace=open,read java class
您会看到类似的内容(我使用Oracle JDK 6进行了测试)
13225 open("/dev/random", O_RDONLY) = 8 13225 read(8, "@", 1) = 1 13225 read(3, "PK34n RyzB36320267325u4 u4 ", 30) = 30 .... ....
如果您在启动过程中遇到延迟,请参阅“Tomcat Wiki”部分中有关加快启动速度的建议,使用/ dev / urandom之类的非阻塞熵源
更多信息:https://wiki.apache.org/tomcat/HowTo/FasterStartUp#Entropy_Source
希望这可以帮助。
Java-搜索字符串数组中的字符串 – java
在Java中,我们是否有任何方法可以发现特定字符串是字符串数组的一部分。我可以避免出现一个循环。例如String [] array = {"AA","BB","CC" }; string x = "BB" 我想要一个if (some condition to tell wheth…
产生6位数的随机数 – java
我只想生成6位数的随机数,范围应从000000到999999。new Random().nextInt(999999)返回我的电话号码,但不是6位数字。 参考方案 就这么简单,您可以使用您的代码,并在此处做一件事String.format("%06d", number); 这将以字符串格式返回您的数字,因此“0”将为“000000”。这是…
Java Scanner读取文件的奇怪行为 – java
因此,在使用Scanner类从文件读取内容时,我遇到了一个有趣的问题。基本上,我试图从目录中读取解析应用程序生成的多个输出文件,以计算一些准确性指标。基本上,我的代码只是遍历目录中的每个文件,并使用扫描仪将其打开以处理内容。无论出于何种原因,扫描程序都不会读取其中的一些文件(所有UTF-8编码)。即使文件不是空的,scanner.hasNextLine()在…
Java Globbing模式以匹配目录和文件 – java
我正在使用递归函数遍历根目录下的文件。我只想提取*.txt文件,但不想排除目录。现在,我的代码如下所示:val stream = Files.newDirectoryStream(head, "*.txt") 但是这样做将不会匹配任何目录,并且返回的iterator()是False。我使用的是Mac,所以我不想包含的噪音文件是.DS_ST…
直接读取Zip文件中的文件-Java – java
我的情况是我有一个包含一些文件(txt,png,…)的zip文件,我想直接按它们的名称读取它,我已经测试了以下代码,但没有结果(NullPointerExcepion):InputStream in = Main.class.getResourceAsStream("/resouces/zipfile/test.txt"); Buff…
最新评论