2

我需要在现有的商业 Java 应用程序上激活 SO_KEEPALIVE,因为我的防火墙在一些不活动后会断开连接。我不拥有源代码,所以我无法更改它(当我拥有源代码时会很容易,只需添加 socket.setKeepAlive(true) )。所以我一直在寻找一些替代方案:

  • 首先,我尝试使用 libkeepalive.so ( http://libkeepalive.sourceforge.net/ ),将其放入 de LD_PRELOAD 似乎适用于 telnet 和 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;在受保护的同步 void create(boolean stream) 方法中,并通过 -Xbootclasspath/p 将其放在 rt.jar 之前

到目前为止,最后一个选项有效,但我有点沮丧,因为我不得不为此更改 JVM!任何人都知道其他/更好的方法来处理这样的问题?为什么没有另一种简单的方法可以在所有(java)应用程序上默认激活 SO_KEEPALIVE?

最后一个问题:为什么 java API 不允许您在 serverSockets 对象上设置 keepAlive?它只适用于 Socket 对象,但实际上它也适用于 serverSockets

4

3 回答 3

2

我遇到了同样的问题,想知道为什么 libkeepalive 不起作用。经过一番调查,我发现 libkeepalive 有一些“限制”(也许有人会称它们为错误)。由于奇怪的许可证(它带有 GPL),我决定重新开始。结果是libdontdie。您可以在那里找到一个与(至少)openjdk7 一起使用的小型 Java 测试程序。

于 2015-03-04T00:06:52.250 回答
1

可以在运行时使用 java 代理 ( http://docs.oracle.com/javase/6/docs/api/java/lang/instrument/package-summary.html ) 和 ASM4 ( http: //asm.ow2.org/)。正如你所知道的目标类和方法,所需要的只是捕获相关方法的返回字节码指令并在它之前注入一个方法调用。

于 2013-04-21T05:45:22.090 回答
0

这是商业闭源软件的问题之一。如果它不起作用,那么您修复它的选项将受到限制。这是使用封闭源代码的成本。

您还没有尝试过一件显而易见的事情。

  • 联系您正在使用的产品的支持热线,请他们为您提供解决方案。产品本身可能已经有一些东西可以解决这个问题;例如一些未记录的配置选项。或者他们可能能够为您的问题开发自定义解决方法。

如果客户支持没有帮助,您有许多潜在的选择:

  • 您可以尝试对产品的相关部分进行逆向工程(例如,它创建套接字的位置),并通过以下方式找出如何设置“keepalive”:

    • 修改他们的一个类,

    • 子类化他们的一个类,或

    • 编写某种使用反射从私有变量等中挖掘出套接字对象的钩子。

    逆向工程可能违反您的许可协议。但是,如果您这样做的原因是为了解决他们的代码中的一个问题,使您无法使用它,那么他们将很难说服法庭您的所作所为应该受到惩罚。如果他们尝试这样做,“舆论法庭”很可能会惩罚他们。

  • 您可以根据您的许可协议和相关的消费者保护法查看您的权利。如果您无法让产品为您工作,该产品是否“适合使用”?

  • 您可以威胁取消您的支持合同并停止使用他们的产品。

  • 实际上可以取消您的支持合同并停止使用他们的产品。(如果你使用不同的产品,更喜欢开源,这样你就不会再次陷入同一个绑定。)


您的解决方案“有效”的问题是:

  • 每次刷新 JVM 时,您可能都必须重复此操作。

  • 它可能会干扰应用程序中的其他事情......或使用修补的 JVM 的其他应用程序。

  • 您不能在不违反 Oracle 许可证的情况下重新分发它……除非您使用的是 OpenJDK。

  • 这可能会让其他需要支持你的东西的人感到紧张。(可以理解)。


最后一个问题:为什么 java API 不允许您在 serverSockets 对象上设置 keepAlive?

您需要询问设计 API 的人。(祝你好运!)

如果您认为可以而且应该这样做,请通过 Java Bugs Database 提交 RFE。或者更好的是,自己实现它作为最新 OpenJDK 代码库的补丁,并贡献补丁。与您未命名的商业产品不同,Java(基本上)是开源的,他们欢迎改进产品的有用补丁。

于 2013-04-21T03:17:29.290 回答