How to Have 2 Jvms Talk to One Another

How to have 2 JVMs talk to one another

Multiple options for IPC:

Socket-Based (Bare-Bones) Networking

  • not necessarily hard, but:
    • might be verbose for not much,
    • might offer more surface for bugs, as you write more code.
  • you could rely on existing frameworks, like Netty

RMI

  • Technically, that's also network communication, but that's transparent for you.

Fully-fledged Message Passing Architectures

  • usually built on either RMI or network communications as well, but with support for complicated conversations and workflows
  • might be too heavy-weight for something simple
  • frameworks like ActiveMQ or JBoss Messaging

Java Management Extensions (JMX)

  • more meant for JVM management and monitoring, but could help to implement what you want if you mostly want to have one process query another for data, or send it some request for an action, if they aren't too complex
  • also works over RMI (amongst other possible protocols)
  • not so simple to wrap your head around at first, but actually rather simple to use

File-sharing / File-locking

  • that's what you're doing right now
  • it's doable, but comes with a lot of problems to handle

Signals

  • You can simply send signals to your other project
  • However, it's fairly limited and requires you to implement a translation layer (it is doable, though, but a rather crazy idea to toy with than anything serious.

Without more details, a bare-bone network-based IPC approach seems the best, as it's the:

  • most extensible (in terms of adding new features and workflows to your
  • most lightweight (in terms of memory footprint for your app)
  • most simple (in terms of design)
  • most educative (in terms of learning how to implement IPC). (as you mentioned "socket is hard" in a comment, and it really is not and should be something you work on)

That being said, based on your example (simply requesting the other process to do an action), JMX could also be good enough for you.

Running multiple JVMs

How do you run multiple JVMs on a single machine?

Just launch multiple java processes.

How do you call methods in a different JVM?

Use any type of RPC framework (RMI, EJB, web service, etc.).

All ways of JVM to JVM communication

See inter-process communication.

Shared Memory between two JVMs

Solution 1:

The best solution in my opinion is to use memory mapped files. This allows you to share a region of memory between any number of process, including other non java programs. You can't place java objects into a memory mapped file, unless you serialize them. The following example shows that you can communicate between two different process, but you would need to make it much more sophisticated to allow better communication between the processes. I suggest you look at Java's NIO package, specifically the classes and methods used in the below examples.

Server:

public class Server {

public static void main( String[] args ) throws Throwable {
File f = new File( FILE_NAME );

FileChannel channel = FileChannel.open( f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE );

MappedByteBuffer b = channel.map( MapMode.READ_WRITE, 0, 4096 );
CharBuffer charBuf = b.asCharBuffer();

char[] string = "Hello client\0".toCharArray();
charBuf.put( string );

System.out.println( "Waiting for client." );
while( charBuf.get( 0 ) != '\0' );
System.out.println( "Finished waiting." );
}
}

Client:

public class Client {

public static void main( String[] args ) throws Throwable {
File f = new File( FILE_NAME );
FileChannel channel = FileChannel.open( f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE );

MappedByteBuffer b = channel.map( MapMode.READ_WRITE, 0, 4096 );
CharBuffer charBuf = b.asCharBuffer();

// Prints 'Hello server'
char c;
while( ( c = charBuf.get() ) != 0 ) {
System.out.print( c );
}
System.out.println();

charBuf.put( 0, '\0' );
}

}

Solution 2:

Another solution is to use Java Sockets to communicate back and forth between processes. This has the added benefit of allowing communication over a network very easily. It could be argued that this is slower than using memory mapped files, but I do not have any benchmarks to back that statement up. I won't post code to implementing this solution, as it can become very complicated to implement a reliable network protocol and is fairly application specific. There are many good networking sites that can be found with quick searches.


Now the above examples are if you want to share memory between two different process. If you just want to read/write to arbitrary memory in the current process, there are some warnings you should know first. This goes against the entire principle of the JVM and you really really should not do this in production code. You violate all safety and can very easily crash the JVM if you are not very careful.

That being said, it is quite fun to experiment with. To read/write to arbitrary memory in the current process you can use the sun.misc.Unsafe class. This is provided on all JVMs that I am aware of and have used. An example on how to use the class can be found here.

Communication between local JVMs

I'd use KryoNet with local sockets since it specialises heavily in serialisation and is quite lightweight (you also get Remote Method Invocation! I'm using it right now), but disable the socket disconnection timeout.

RMI basically works on the principle that you have a remote type and that the remote type implements an interface. This interface is shared. On your local machine, you bind the interface via the RMI library to code 'injected' in-memory from the RMI library, the result being that you have something that satisfies the interface but is able to communicate with the remote object.

Let two long running processes talk to each other by text files

You can get this to work, provided you are careful with file handling and you don't have a high update rate e.g. 10 updates per second.

Note: you could do it with file renaming instead of locks.

What would be a better solution?

Just about anything, SO is not for recommending things, but in this case I could recommend just about anything without more specific requirements. I could for example recommend my library Chronicle Queue because I wrote it and I sure it could do what you want, however there are many possible alternatives.

I am sending about one line of text every minute.

So you can write a temporary file for each message, rename it when finished. The consumer can have a directory watcher so it knows as soon as you have done this. The consumer could delete the file when done. This has an overhead but it would be less than 10 ms.

If you want to keep a record of all messages, the producer can also write to a log file.



Related Topics



Leave a reply



Submit