我们在沙盒Java Applet中遇到问题,因为SecurityManager执行反向DNS查找。请参阅other question。
但潜在的问题是,反向DNS查找大约需要4.5秒(没有域结果)。问题不是缺失的结果(在这种情况下它会返回IP),这只是需要很长时间的事实。
问题也与SecurityManager无关,它只会成为一个问题,因为Permissions类在运行时会持有一个锁,因此冻结许多其他线程4.5(或更多)秒。
还有一些域没有域名结果(即返回IP),这些域名不需要4.5秒。例如“staminus.net”。
SSCCE:
String host = "random.org";
// "random.org" - IP result, takes 4.5 seconds
// "cdn.knuddelscom.de" - IP result, takes 4.5 seconds
// "staminus.net" - IP result, fast
// "google.com" - domain result: fra15s11-in-f14.1e100.net, fast
InetAddress addr = Inet4Address.getByName(host);
for (int i = 0; i < 100; i++)
{
long start = System.currentTimeMillis();
String hostName = Inet4Address.getByAddress(addr.getAddress()).getHostName();
long end = System.currentTimeMillis();
System.out.println((i + 1) + " RDNS " + host + " ... (" + (end - start) + "ms): " + hostName);
}
(使用Java JDK 1.8.0_40测试)
我使用Sysinternals Process Explorer来制作挂起线程的Windows API调用线程转储,但我不知道它是什么告诉发生了什么:
ntoskrnl.exe!KeSynchronizeExecution+0x2246
ntoskrnl.exe!KeWaitForMultipleObjects+0x135e
ntoskrnl.exe!KeWaitForMultipleObjects+0xdd9
ntoskrnl.exe!KeWaitForSingleObject+0x373
ntoskrnl.exe!KeReleaseSemaphore+0xd33
ntoskrnl.exe!NtSetEvent+0xf99
ntoskrnl.exe!NtSetEvent+0x447
ntoskrnl.exe!RtlEqualUnicodeString+0x9ae
ntoskrnl.exe!setjmpex+0x34a3
ntdll.dll!ZwAlpcSendWaitReceivePort+0xa
RPCRT4.dll!NDRCContextBinding+0x6c8
RPCRT4.dll!NdrClientCall3+0xded
RPCRT4.dll!NdrClientCall3+0xfe
DNSAPI.dll!AddRefQueryBlobEx+0x753
DNSAPI.dll!DnsValidateName_W+0x1312
DNSAPI.dll!DnsQueryEx+0x103
mswsock.dll!Tcpip4_WSHOpenSocket2+0x1578
mswsock.dll!Tcpip4_WSHOpenSocket2+0x141e
mswsock.dll!Tcpip4_WSHOpenSocket2+0x1252
WS2_32.dll!WSALookupServiceNextW+0x1d8
WS2_32.dll!WSALookupServiceNextW+0xa3
WS2_32.dll!GetHostNameW+0x2e44
WS2_32.dll!GetHostNameW+0x1130
WS2_32.dll!getnameinfo+0xaf
net.dll!Java_java_net_Inet6AddressImpl_getHostByAddr+0x124
因为它总是大约4.5秒,所以看起来非常像超时。 因此,这种解释是合乎逻辑的:(R)DNS服务器不回应我们的请求。
我们如何测试?
我们如何解决这个问题?