我在运行OSX10.9.4、1.7GHz i7、8GB内存的Macbook Air上运行以下Java程序。我已经安装了Java密码扩展(JCE)。
import javax.crypto.Mac;
public class Main {
public static void main(String[] args) throws Exception {
Mac.getInstance("HmacSHA1");
}
}运行这个简单的程序会导致运行时间超过5秒!
$ javac -version
javac 1.7.0_45
$ javac Main.java
$ java -version
java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)
$ time java Main
real 0m5.326s
user 0m0.390s
sys 0m0.033s我已经做了大量的搜索,但在解决方法或解释方面没有找到多少东西。
/dev/random和/dev/urandom在OSX上是相同的。以前有人听说过这个问题吗?或者知道我怎么调试发生什么事了?当你的单元测试到现在为止都是瞬间的时候,对你的单元测试采取5秒的惩罚是非常令人沮丧的。
编辑:,这是程序内部的时间和安全提供者的列表:
import java.security.Provider;
import java.security.Security;
import javax.crypto.Mac;
public class Main {
public static void main(String[] args) throws Exception {
for (Provider p: Security.getProviders()) {
System.out.println(p.getName() + " " + p.getVersion() + " " + p.getInfo());
}
long start = System.currentTimeMillis();
Mac.getInstance("HmacSHA1");
System.out.println(System.currentTimeMillis() - start + "ms");
}
}
$ java Main
SUN 1.7 SUN (DSA key/parameter generation; DSA signing; SHA-1, MD5 digests; SecureRandom; X.509 certificates; JKS keystore; PKIX CertPathValidator; PKIX CertPathBuilder; LDAP, Collection CertStores, JavaPolicy Policy; JavaLoginConfig Configuration)
SunRsaSign 1.7 Sun RSA signature provider
SunEC 1.7 Sun Elliptic Curve provider (EC, ECDSA, ECDH)
SunJSSE 1.7 Sun JSSE provider(PKCS12, SunX509 key/trust factories, SSLv3, TLSv1)
SunJCE 1.7 SunJCE Provider (implements RSA, DES, Triple DES, AES, Blowfish, ARCFOUR, RC2, PBE, Diffie-Hellman, HMAC)
SunJGSS 1.7 Sun (Kerberos v5, SPNEGO)
SunSASL 1.7 Sun SASL provider(implements client mechanisms for: DIGEST-MD5, GSSAPI, EXTERNAL, PLAIN, CRAM-MD5, NTLM; server mechanisms for: DIGEST-MD5, GSSAPI, CRAM-MD5, NTLM)
XMLDSig 1.0 XMLDSig (DOM XMLSignatureFactory; DOM KeyInfoFactory)
SunPCSC 1.7 Sun PC/SC provider
Apple 1.1 Apple Provider
5224ms编辑2:
想出了如何在代码上运行HPROF。
$ java -agentlib:hprof=cpu=times Main
$ cat java.hprof.txt
...
TRACE 308670:
java.net.InetAddress$1.lookupAllHostAddr(InetAddress.java:Unknown line)
java.net.InetAddress.getAddressesFromNameService(InetAddress.java:Unknown line)
java.net.InetAddress.getLocalHost(InetAddress.java:Unknown line)
javax.crypto.JarVerifier.getSystemEntropy(JarVerifier.java:Unknown line)
...
CPU TIME (ms) BEGIN (total = 6680) Sat Aug 16 05:59:39 2014
rank self accum count trace method
1 74.87% 74.87% 1 308670 java.net.InetAddress$1.lookupAllHostAddr
...因此,由于某种原因,JarVerifier试图从系统中获取熵,这导致程序在InetAddress$1.lookupAllHostAddr中花费了5秒。
编辑3:
将Java更新为"1.7.0_67“并不能解决这个问题。
发布于 2014-08-16 21:36:32
我找到了解决办法。从编辑2中可以看出,Mac.getInstance()似乎调用了javax.crypto.JarVerifier.getSystemEntropy(),后者最终调用了java.net.InetAddress.getLocalHost()。根据这篇文章的说法,Java7改变了InetAddress查找本地主机的方式。由于某种原因,这会导致我的机器产生lookupAllHostAddr,这需要花费大约5秒的时间来完成。
本文中的一个注释列出了对我有用的解决方案,即将我的主机名添加到/etc/hosts中。以下内容如下:
127.0.0.1 localhost
255.255.255.255 broadcasthost
::1 localhost
fe80::1%lo0 localhost更改为
127.0.0.1 localhost <replace-me>.local
255.255.255.255 broadcasthost
::1 localhost
fe80::1%lo0 localhost在对主机文件进行更改之后,我的时间又回到了合理的200 my。
$ time java Main
real 0m0.242s
user 0m0.379s
sys 0m0.034shttps://stackoverflow.com/questions/25321187
复制相似问题