United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-6469803 : Socket creation on Windows takes a long time if web proxy does not have a DNS entry

Details
Type:
Bug
Submit Date:
2006-09-12
Status:
Closed
Updated Date:
2011-03-07
Project Name:
JDK
Resolved Date:
2011-03-07
Component:
core-libs
OS:
windows_xp
Sub-Component:
java.net
CPU:
x86
Priority:
P2
Resolution:
Fixed
Affected Versions:
5.0u8
Fixed Versions:

Related Reports
Backport:
Backport:
Backport:
Relates:
Relates:
Relates:

Sub Tasks

Description
When creating URLs in an applet I experience 5 second delays.  This is because the JVM is attempting to do a DNS lookup of my webproxy but my webproxy doesn't have a DNS entry.  This is a fairly typical setup for corporate web proxies.

The problem is in sun.net.www.HttpClient.priviledgedOpenServer() which makes a call to InetSocketAddress.getHostName().

This is a new issue that has appered in 1.5.0.  I can't see any reason why the JVM would need to resolve the name of the proxy.  So I think this is a bug.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Configure your web browser to use an HTTP proxy which you specify by ip and port (not by hostname).
2. Host the applet below on a webside accessed through the web proxy.
3. Arrange some method of detecting network lookups.
4. Load the applet in the browser

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I'd expect the URL connections to be instantanious.  I'd expect no name lookups to take place.
ACTUAL -
Name lookups of the web proxy take place.  On an incorrectly configured system this causes the URL connection to take 4 seconds or longer.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.applet.Applet;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;

public class Minimal extends Applet {

	public void start()
	{
		try {
			for (int i = 0; i < 5; i++) {
	
				long time_start = System.currentTimeMillis();
				URLConnection uc;
				URL url = new URL("http://foo.com");
				uc = url.openConnection();
				uc.connect();
				long time_end = System.currentTimeMillis();
				System.out.println("Time to open socket (ms): "	+ (time_end - time_start));
			}
		} catch (IOException e) {
			System.out.println(e);
		}
	}
	
}

This issue is separate to 5092063 even though it looks similar.  I have
recently tested the 1.5.0_08 JVM and the issue is still there.

The good news is, thanks to SUN's open source code policy, I can tell
you exactly where the bug is:  It is in sun/net/www/HttpClient.java in
the privilegedOpenServer() method.  In here there is a call to
server.getHostName() which forces the InetSocketAddr object to resolve
its name (if it hasn't done so already).

Backtracking a little...  The problem is when someone is using a java
applet to connect through a web proxy.  On some networks the proxy has
been specified by ip address but does not resolve into a host name (I
reproduce this by using a Perl proxy for an ipaddress which doesn't have
a DNS record on our LAN).  I suspect the issue exists on many platforms
but it is particularly accute on windows since when a DNS lookup fails
windows attempts to lookup via NetBIOS (or something simlar) which
results in a failed lookup taking 4.5 seconds!

The problem is that with the new Proxy code in 1.5, the
priviledgedOpenServer() method is called whenever an applet makes a
connection.  It isn't possible to bypass this call or bypass / alter the
Proxy code without generating security exceptions.

There are two obvious fixes that could be applied:

1. Fix priviledgedOpenSever() so that it doesn't call getHostName().  I
see no reason why it should resolve the name, it seems like a bug to me.
If the proxy is specified by ip address then ip addresses only should be
used for connecting to the proxy.

2. Fix the ProxySelector stuff so that it returns the same
InetSocketAddress object each time it is queried.  I couldn't find the
source for this since some of it is native, but it appears that each
time you query the ProxySelector for the proxy details it returns a new
InetSocketAddress object.  InetSocketAddress objects cache their name if
you attempt to look it up, so if the ProxySelector returned the same
object each time then the lookup failure would only need to be performed
once (I still can't see any reason why it should be performed at all,
but this would at least be an acceptable workaround).

                                    

Comments
EVALUATION

Yes, this is similar to 5092063 where a reverse lookup is triggered and can take a long time if the entry is not in the DNS maps.
We need to apply a similar fix (i.e. avoid calling getHostName() unless the reverse lookup is actually necessary).
                                     
2006-09-12
SUGGESTED FIX

Up to, and including, jdk 6 there is no method to extract the hostname from a InetSocketAddress without triggering a reverse lookup. However it is possible to use the following code instead of calling getHostName():

// Use getAddress().toString() to avoid reverse lookup
String s = server.getAddress().toString();
int pos = s.indexOf('/');
if (pos == 0) {
	// extract the IP litteral
	s = s.substring(1);
} else {
	// extract the hostname
	s = s.substring(0, pos);
}

this will give you the hostname if the address was resolved or, the IP litteral if it was not.
A better solution will require a new public API in InetSocketAddress and will have to wait until jdk 7.
                                     
2006-09-13
WORK AROUND

A workaround that will always fix the timeout issues is to make sure the proxy servers are in the DNS tables.
                                     
2006-09-13



Hardware and Software, Engineered to Work Together