我需要在现有的商业Java应用程序上激活SO_KEEPALIVE,因为我的防火墙会在一些不活动后丢弃连接。我不拥有源代码,所以我无法改变它(当我有源代码时,只需添加socket.setKeepAlive(true))就会很容易。所以我正在寻找一些替代方案:
首先我尝试使用libkeepalive.so(http://libkeepalive.sourceforge.net/),将其放入de LD_PRELOAD似乎适用于telnet和amp; nc,但是当我将它与我的jrockit jvm一起使用时,这个LD_PRELOAD被完全忽略,并且每个套接字对象仍在创建而没有SO_KEEPALIVE
然后我尝试在操作系统级别搜索,如果有一个选项可以为所有TCP连接默认激活此SO_KEEPALIVE:不幸的是,在redhat 6企业中没有这样的选项,尽管我发现了一个对于freebsd(net.inet.tcp.always_keepalive)
修补linux内核以添加此功能对我的系统管理员来说是一个很大的问题;)
搜索任何java命令行参数都不成功
最后一个选项:通过添加setOption(SocketOptions.SO_KEEPALIVE,Boolean.valueOf(true))修补现有JVM的java.net.PlainSocketImpl;在protected synchronized void create(boolean stream)方法中,并通过-Xbootclasspath / p将其放在rt.jar之前
这最后一个选项到目前为止工作,但我有点沮丧,因为我不得不为此改变一个JVM!谁知道其他/更好的方法来处理这样的问题?为什么还没有另一种简单的方法可以在所有(java)应用程序上默认激活SO_KEEPALIVE?
最后一个问题:为什么java API不允许你在serverSockets对象上设置keepAlive?它只适用于Socket对象,但实际上它也适用于serverSockets
答案 0 :(得分:1)
可以使用java代理(http://docs.oracle.com/javase/6/docs/api/java/lang/instrument/package-summary.html)和ASM4(http://asm.ow2.org/)在运行时重新定义现有的引导类。 如您所知,目标类和方法,只需捕获相关方法的返回字节码指令并在其之前注入方法调用。
答案 1 :(得分:1)
我遇到了同样的问题,并想知道为什么libkeepalive不起作用。经过一些调查我发现,libkeepalive有一些“限制”(也许有人会称它们为bug)。 由于奇怪的许可证(它附带GPL),我决定重新开始。结果是libdontdie。 您可以在那里找到一个与(至少)openjdk7一起使用的小型Java测试程序。
答案 2 :(得分:0)
这是商业闭源软件的问题之一。如果它不起作用,您的选项仅限于修复它。这是使用封闭源的成本。
有一个显而易见的事情你尚未尝试过。
如果客户支持无益,那么您有很多可能的选择:
您可以尝试对产品的相关部分进行反向工程(例如,创建套接字的位置),并弄清楚如何设置“keepalive”:
修改其中一个类
继承其中一个类,或
编写某种使用反射的钩子从私有变量中挖出套接字对象,等等。
逆向工程可能违反了您的许可协议。但是,如果你这样做的原因是为了解决他们的代码中的问题而使你无法使用它们,他们就很难说服法庭你所做的事情应该受到惩罚。而“舆论法庭”很可能会惩罚他们如果他们这样做了。
您可以根据许可协议和相关的消费者保护法检查您的权利。如果您不能让它适合您,该产品是否“适合使用”?
您可能会威胁取消支持合同并停止使用其产品。
您可以实际取消您的支持合同并停止使用其产品。 (如果你使用不同的产品,更喜欢开源,这样你就不会再次进入同一个绑定。)
您的解决方案“有效”的问题是:
每次刷新JVM时都可能需要重复此操作。
它可能会干扰应用程序中的其他内容......或使用修补后的JVM的其他应用程序。
除非您使用的是OpenJDK,否则不能在不违反Oracle许可的情况下重新发布此内容。
这可能会让其他需要支持你的东西的人感到紧张。 (可以理解)。
最后一个问题:为什么java API不允许你在serverSockets对象上设置keepAlive?
您需要询问设计API的人。 (祝你好运!)
如果您认为可以而且应该这样做,请通过Java Bugs数据库提交RFE。或者更好的是,自己实现它作为最新OpenJDK代码库的补丁,并贡献补丁。与您未命名的商业产品不同,Java(基本上)是开源的,它们欢迎有用的补丁来改进产品。