RemoteVM is simple utility that allows remote, headless Java VM invocation. It is consisted of two parts, an agent that runs on remote machine accepting connections and spawning new Java VMs on demand and a client launcher application.
High Level Design
The agent is running as a daemon (or on demand started) Java application started from a single jar file. It accepts connections (on default port 8999, configurable through command line parameters), receives list of VM and application arguments needed for starting new Java VM, starts new Java VM and acts as a proxy between client and newly started Java VM. Also, it passes back all stdout from newly started Java VM back to the client.
Newly started Java VM takes over communication with the client. It receives name of main class it needs to invoke, arguments to be passed to it and fixed classpath file names (as seen from the directory the agent is started). Then it receives list of classpath resource names, along with size and date of modification from the client and is responsible of storing resources in local cache. Cache is maintained in same directory the agent is started in and subdirectory called ".remotevm". Further subdirectory is made to reflect main class name and then each remote classpath directory is given separate, unique name that reassembles source directory name as much as possible. Where there is name clash, prefix 1_, 2_ and so on is added.
Newly started VM is then responsible for comparing received lengths and dates with local, cached resource files and request those that are different. After all classpath resources are received, it creates new URLClassLoader, loads main class through it and then invokes its main method passing given arguments. After that moment it will just listen to connection with the agent in order to invoke System.exit(1) if client closes connection to the agent.
The Client - Remote Lancher
Second part of the RemoteVM is the client code - "Remote Launcher". It is designed to sit on the development machine application's classpath. It connects to the remote agent, collects classpath resources (along with modification dates and lengths of files), passes new JVM arguments, application arguments and main class and acts as remote resource server for the newly created remote JVM.
So, remote launcher's jar should be included in "launch configuration" on the client (on development machine) and its main class invoked with all the needed arguments including main class.
When new remote JVM is started it will, through the agent, request this, client side, for classpath resources and the client will serve them back to remote JVM. Also, all output from stdout from remote JVM will be printed back out on the client console.
RemoveVM came to be to help with Raspberry Pi development in headless mode. Raspberry Pi is quite short of resources (memory) and cannot run full blown IDEs like Eclipse. On the other hand development in IDEs is much faster and far more comfortable then what is available on Raspberry Pi. So, the agent with remote launcher bridge the gap between development machine and target system (Raspberry Pi). It is now possible starting remote application directly from the IDE, stop it, change the code and rely on RemoteVM to pass the changes in classpath resource back to the target machine and start the application again.
Aside of Raspberry Pi directly, this method is applicable to any remote, network accesible system where IDE cannot run on it, but due to specific hardware or software differences it is not easy or possible to run application locally on the development machine.
3rd January 2014
New snapshot released (number 5). Fixed Windows path delimiter bug.
1st January 2014
Happy New Year! :) New snapshot released (number 4). Fixed some bugs and updated debug logging.
22nd December 2013
New snapshot released. Added remote VM args, exclude local classpath and fixed logs.
30th November 2013
New snapshot released. Added support for Windows clients.
23th November 2013
Initial, snapshot, version released!
Every kind of help is more than welcome - from coding, designing to testing and using it.