Sun Java HTTPServer 有一个错误,如何修复?
我在我的项目中使用 com.sun.net.httpserver.HttpServer 。然而,当服务器从 HTTP 连接获取无效数据时,它似乎会泄漏连接。该错误是这样的:
https://bugs.java.com/ bugdatabase/view_bug;jsessionid=dfe841c3152d878571573bafceb8?bug_id=6946825
现在,据报道该问题已在版本“7(b94)”中得到修复 - 然而,我们仍在使用 Java 1.6,并且我们不太可能想要切换 Java此时的版本。
因此,我正在寻找解决这种情况的方法。我没有太多时间,所以我更喜欢现在有效的快速解决方案,而不是稍后重新实现很多东西。
我对如何解决这个问题有一些想法:
- 更新到更新的 Java - 这是我不想做的事情。
- 找到一个仅包含较新版本的 com.sun.net.httpserver 的 jar,并确保该 jar 在系统 jar 之前加载。
- 找到 com.sun.net.httpserver 的直接替代品 - 我愿意在这里接受指点。
- 修改代码以与另一个嵌入式 HTTP 服务器一起使用,希望该服务器与当前服务器没有太大不同。我可以在某种程度上重写服务器设置代码,但大多数界面应该保持不变。
- 反编译 com.sun.net.httpserver.ServerImpl 类,修复有问题的地方,然后将该单个类重新编译为它自己的 jar
但是,我愿意接受好的建议!
先感谢您。
修复现已实施并有效。如果其他人需要这些,我将在此处粘贴相关内容:
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);
}
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:
https://bugs.java.com/bugdatabase/view_bug;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);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您能否在 HTTP 服务器前面放置一个反向代理,以确保只允许已知的良好请求通过? Varnish、Squid 还是 Apache?
或者在 Jetty 中敲出一些东西,使其充当反向代理?
另一种方法是获取 固定版本的源代码,重命名类和包以使其适合您的项目,将类公开,然后改用该实现。
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.
我可以理解您不愿意升级到 Java 7 的预发布版本。
以下是我的建议:
从 Oracle 获取 Java 支持合同,让他们为您提供修复该错误的 Java 6 补丁。< /p>
下载您当前使用的版本的 Java 6 源代码,从 Java 7 源代码反向移植错误修复并构建。也许您只需要构建某些 JAR 文件。
查看代码,看看是否可以制定解决方法。例如,您可以使用反射来挖掘错误报告中提到的“HttpConnection 实例列表”,并定期删除看起来像是已死的条目。 (我将此视为最后的手段。)
(更新:2012-05-15)
现在 Java 7 已经真正发布(我们现在处于 1.7u4):
升级到 Java 7,并且
摆脱您用作临时解决方法的讨厌的反射黑客。
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.
您可以访问 7(b94) 吗?然后您可以比较源代码,看看是否可以通过覆盖或提供不同的访问器来修复它。
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.