Question

I'm using com.sun.net.httpserver.HttpServer in my project. However, it seems that the server leaks connections when it gets invalid data from the HTTP connection. The bug is this one:

http://bugs.sun.com/view_bug.do;jsessionid=dfe841c3152d878571573bafceb8?bug_id=6946825

Now, this is reported to be fixed in version "7(b94)" - however, we are still using Java 1.6 and it is unlikely that we would want switch Java versions at this point.

So, I am looking for ways to fix this situation. I don't have a lot of time, so I'd prefer quick solutions that work for now, over reimplementing a lot of things for later.

I have a few ideas on how to go about this:

  • Update to a more recent Java - this is something I don't want to do.
  • Find a jar which only contains a more recent version of com.sun.net.httpserver and make sure that jar loads before the system jars.
  • Find a drop-in replacement for com.sun.net.httpserver - I'm open to pointers here.
  • Modify code to work with another embedded HTTP server, hopefully one that isn't too different from the current one. I can rewrite the server setup code, somewhat, but most of the interfaces should stay the same.
  • Decompile the com.sun.net.httpserver.ServerImpl class, fix the offending places, and recompile that single class to a jar of it's own

But, I'm open to good suggestions!

Thank you in advance.


Fix is now implemented and works. I will paste here the relevant bits if anyone else needs these:

final Field httpserverimpl_server = Class.forName("sun.net.httpserver.HttpServerImpl").getDeclaredField("server");
final Field httpsserverimpl_server = Class.forName("sun.net.httpserver.HttpsServerImpl").getDeclaredField("server");
final Field serverimpl_allconnections = Class.forName("sun.net.httpserver.ServerImpl").getDeclaredField("allConnections");
final Field httpconnection_closed = Class.forName("sun.net.httpserver.HttpConnection").getDeclaredField("closed");

httpserverimpl_server.setAccessible(true);
httpsserverimpl_server.setAccessible(true);
serverimpl_allconnections.setAccessible(true);
httpconnection_closed.setAccessible(true);

Object serverimpl = httpserverimpl_server.get(server);
Set allconnections = (Set)serverimpl_allconnections.get(serverimpl);
LinkedList<Object> toRemove = new LinkedList<Object>();
for (Object conn : allconnections) {
    if (httpconnection_closed.getBoolean(conn)) {
        toRemove.add(conn);
    }
}
for (Object conn : toRemove) {
    allconnections.remove(conn);
}
Was it helpful?

Solution

I can understand your reluctance to upgrade to a pre-release build of Java 7.

Here are my suggestions:

  • Get a Java support contract from Oracle and get them to provide you with a patch for Java 6 that fixes the bug.

  • Download the Java 6 sources for the release you are currently using, backport the bug fix from the Java 7 sources and build. Maybe you only need to do a build of certain JAR files.

  • Look at the code and see if you could develop a workaround. For example, you might be able to use reflection to dig out the "list of HttpConnection instances" that the bug report talks about, and periodically remove entries that look like they are dead. (I'd treat this as a last resort.)


(Updated: 2012-05-15)

And, now that Java 7 is well and truly released (we are now at 1.7u4):

  • upgrade to Java 7, and

  • get rid of the nasty reflective hacks that you used as a TEMPORARY workaround.

OTHER TIPS

Could you put a reverse proxy infront of the HTTP server, to make sure you only allow known good requests to come through? Varnish or Squid or Apache?

Or knock something up in Jetty so that it acts as a reverse proxy?

Another approach would be to grab the source code of the fixed version, rename the class and package so that it fits into your project, make the class public, and then use that implementation instead.

Do you have access to 7(b94)? Then you can compare the sources and see whether you can fix it by overriding or providing different accessors.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top