2
votes

I need to activate SO_KEEPALIVE on an existing commercial java application because my firewall drops the connections after some inactivity. I do not own the source code so i can't change it (it would be rather easy when i had the source, just adding socket.setKeepAlive(true) ). So i was looking for some alternatives:

  • first i tried to work with libkeepalive.so ( http://libkeepalive.sourceforge.net/ ), putting this in de LD_PRELOAD seems to work for things like telnet & nc, but when i use it with my jrockit jvm, this LD_PRELOAD is totally ignored and every socket object is still being created without SO_KEEPALIVE

  • then i tried to search on the OS level if there was an option to activate this SO_KEEPALIVE per default for all TCP connections: unfortunately on redhat 6 enterprise there isn't such an option, although i found one for freebsd (net.inet.tcp.always_keepalive)

  • patching the linux kernel for adding this feature was a big no for my sysadmin ;)

  • searching for any java command line argument was unsuccessful

  • so last option: patching the existing JVM's java.net.PlainSocketImpl by adding setOption(SocketOptions.SO_KEEPALIVE, Boolean.valueOf(true)); in the protected synchronized void create(boolean stream) method and putting it before rt.jar via -Xbootclasspath/p

This last option works so far, but i'am a bit frustrated because i had to change a JVM for this! Anyone knows other / better ways to deal with such a problem? Why isn't there another simple way to activate SO_KEEPALIVE per default on all (java) applications?

Last question: why doesn't the java API let you set the keepAlive on serverSockets objects? It's only possible on Socket objects but in fact it also works on serverSockets

3
** why doesn't the java API let you set the keepAlive on serverSockets objects? ** maybe you can add that to the java bug list on oracle website for javatgkprog
On my team, we had client-server persistent connection. Standard socket keep-alive did not work reliably, as many NATs and firewalls will drop the connection faster than the socket KA interval. So we just invented our own "PING" message that both endpoints understood in addition to regular protocol commands. Sent every 45 seconds. YMMV.selbie

3 Answers

2
votes

I run over the same problem and wondered why libkeepalive does not work. After some investigation I found, that libkeepalive has some 'limitations' (maybe somebody would call them bugs). Because of the strange license (it comes with GPL), I decided to start over. The result is the libdontdie. You can find a small Java test program there that works with (at least) openjdk7.

1
votes

It is possible to redefine existing bootstrap classes during runtime using a java agent (http://docs.oracle.com/javase/6/docs/api/java/lang/instrument/package-summary.html) and ASM4 (http://asm.ow2.org/). As you know the target class and method, all that is needed is to catch the return bytecode instruction of the relevant method and inject a method call before it.

0
votes

This is one of the problems with commercial closed source software. If it doesn't work, your options are limited for fixing it. This is a COST of using closed source.

There is one obvious thing that you haven't tried yet.

  • Contact the support line for the product you are using and ask them to provide a solution for you. There may already be something in the product itself to solve this; e.g. some undocumented configuration option. Or they may be able to develop a custom workaround for your problem.

If customer support is unhelpful, you have a number of potential options:

  • You could attempt to reverse engineer the relevant part of the product (e.g. the place where it creates sockets), and figure out how to set "keepalive" by:

    • modifying one of their classes,

    • subclassing one of their classes, or

    • writing some kind of hook that uses reflection to dig out the socket objects from private variables, etcetera.

    Reverse engineering could be a violation of your license agreement. However, if the reason you do it is to fix a problem in their code that makes it unusable for you, they would have a hard time convincing a court that what you were doing deserved to be punished. And the "court of public opinion" would most likely punish them if they tried that.

  • You could check your rights under your license agreement and relevant consumer protection law. Is the product "fit for use" if you can't get it to work for you?

  • You could threaten to cancel your support contract and stop using their product.

  • You could actually cancel your support contract and stop using their product. (And if you use a different product, prefer open source so that you don't get into the same bind all over again.)


The problems with your solution that "works" are:

  • You may have to repeat this every time you refresh your JVM.

  • It may interfere with other things in the application ... or other applications that use the patched JVM.

  • You can't redistribute this without violating your Oracle license ... unless you are using OpenJDK.

  • It is likely to make other folks who need to support your stuff nervous. (Understandably).


Last question: why doesn't the java API let you set the keepAlive on serverSockets objects?

You would need to ask the folks who designed the API. (Good luck with that!)

If you believe that this could and should be done, submit an RFE via the Java Bugs Database. Or better still, implement it yourself as patches to the latest OpenJDK codebase, and contribute the patch. Unlike your unnamed commercial product, Java is (basically) Open Source, and they welcome useful patches that improve the product.