按照以下说明操作后发生java.net.UnknownHostException:
说明:
为什么会这样?我想这不应该发生。
简单代码:
公共类TestUrlConnection {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run(){
createAndShowGui();
}
});
}
private static void createAndShowGui(){
final JFrame frame = new JFrame("Test URL Connection");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton btOk = new JButton("Perform Test");
btOk.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
try{
String content = readContentFromTestUrl();
if(content!=null)
JOptionPane.showMessageDialog(frame, "OK. URL Connection returned Content.\nContent length = "+content.length());
else
JOptionPane.showMessageDialog(frame, "Content is null, but no exception");
}
catch(IOException exc){
JOptionPane.showMessageDialog(frame, "Exception:\n\n"+stackTraceToString(exc));
}
}
});
frame.setContentPane(btOk);
frame.setMinimumSize(new Dimension(250,100));
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private static String readContentFromTestUrl() throws IOException{
InputStream is = null;
InputStreamReader isr = null;
BufferedReader br = null;
try {
URL url = new URL("http://test.com");
URLConnection urlConnection = url.openConnection();
urlConnection.setUseCaches(false);
is = urlConnection.getInputStream();
isr = new InputStreamReader(is);
br = new BufferedReader(isr);
String inputLine;
String content = "";
while ((inputLine = br.readLine()) != null)
content += inputLine + "\n";
return content;
}
finally{
if(is!=null){try{is.close();}catch(IOException e){e.printStackTrace();}}
if(isr!=null){try{isr.close();}catch(IOException e){e.printStackTrace();}}
if(br!=null){try{br.close();}catch(IOException e){e.printStackTrace();}}
}
}
private static String stackTraceToString(IOException exc){
exc.printStackTrace();
StringWriter sw = new StringWriter();
exc.printStackTrace(new PrintWriter(sw));
String s = sw.toString();
return s.substring(0, s.length()>600 ? 600 : s.length());
}
}
答案 0 :(得分:2)
DNS查询很昂贵且结果变化很少,因此几乎每个网络实施都会缓存DNS查找结果,这样如果您在几秒钟内打开100个连接,则不必执行100个DNS查询,返回相同的IP地址。 / p>
Java实现没有什么不同,它可以缓存正面和负面(失败)查询。
默认情况下,否定结果会缓存10秒,但显然您的测试指出:
所以,会发生的事情是Java缓存test.com是无法解决的。它应该只存在10秒,所以它放在那里有一个时间戳。你改变时钟,这个时间戳而不是在10秒后失效,可能在14天10秒后失效。
您可以看到它正在使用缓存值,因为首次点击该按钮需要花费大量时间,而其他点击几乎是静止的。
一个简单的解决方案,也证明问题出在DNS缓存中,就是将此行添加为主要的第一行:
java.security.Security.setProperty("networkaddress.cache.negative.ttl" , "0");
这告诉java不要缓存负DNS结果,如果你尝试,你会发现它会按预期运行。但是,禁用此类缓存会降低您的性能并导致安全问题,因此如果您突然更改计算机的日期,我建议重新启动JVM(以及大多数其他长时间运行的进程)。