3

I have a java program that is quite large and we want to make it so the user can quit the app and login as another user. To do this we would like to shut down the app and restart it so it presents the login dialog to the user. The problem is that the application is quite large and is poorly written. It has a lot of static variables that hold some sort of state info. Ideally I would like to rewrite the app to handle a situation where these can all be cleared out, but in reality we need to provide this functionality asap.

What I was thinking would be the easiest would be to simply stop the app and start a new vm. However, it seems surprisingly difficult to stop and application and start the same app while shutting down the current one. Does anyone have experience doing this?

EDIT: we are pursuing using Runtime.exec to call the same app again, but exec() wants to block so we have to jump through hoops to get it to work on every platform (Windows, Mac, Linux). I would prefer a platform independent way of doing it.

Nemi
  • 3,011
  • 1
  • 26
  • 24
  • possible duplicate of [restart a java application.](http://stackoverflow.com/questions/4159802/restart-a-java-application) – Grzegorz Oledzki Jan 10 '11 at 18:01
  • That question has an answer using `ProcessBuilder`, which is recommended in the documentation for `Runtime.exex(cmdarray, envp, dir)`. "ProcessBuilder.start() is now the preferred way to start a process with a modified environment." – Victor Zamanian Jan 10 '11 at 18:13
  • That's supposed to read "Runtime.exec(...)" (not "exex"). – Victor Zamanian Jan 15 '11 at 01:30
  • I really like the way JBoss handles this. I'm not sure how it's done in Windows, but in *nix you start your application inside a while loop which checks the exit code of your application. In JBoss, if you tell it to exit with code 10, this script will restart it. – Eldelshell Mar 10 '11 at 10:00

4 Answers4

2

If you can modify the code, maybe you can exit the program and use the Runtime class (java.lang.Runtime) to start the same program again (with the same arguments?) using the exec() method.

http://download.oracle.com/javase/6/docs/api/java/lang/Runtime.html

Edit: That is to say, you first run the new process, and then exit the program. The other way would of course be much more difficult or impossible(?). :)

Victor Zamanian
  • 3,100
  • 24
  • 31
  • 1
    We are using Runtime exec, but are having issues with it being platform independent. – Nemi Jan 10 '11 at 17:58
1

If you truly want to stop the JVM and restart it, then you'll have to write some wrapper script (shell script or batch file, depending on your OS) that does it. You could use a special return code from System.exit() to indicate that the application should be restarted.

And that's probably the best way to do it. You could play some classloader tricks, in which your create a custom classloader that to load the application's classes. However, there are a lot of ways for this to go wrong: for example the application code might call System.exit() in some hidden place, or it might contain code that retains internal references in classes loaded by the bootstrap classloader.

Anon
  • 2,654
  • 16
  • 10
0

Static members are associated with the classloader:classname. You can create your own classloader and instantiate your app via that. Then when you want to restart, throw away the classloader and create a new one. This is how app engines like JBoss are able to reload applications on the fly.

Chris Nava
  • 6,614
  • 3
  • 25
  • 31
  • I thought of this, and I think it is a great idea, but would require a lot of reworking and testing to make sure the app runs correctly. Also, I have read that the jvm can still have problems garbage collection ClassLoaders for some reason, which is why JBoss will often give you a out of permgen space error after a while when restarting this way. – Nemi Jan 10 '11 at 18:33
  • if your _entire_ app is run under a separate classloader, you won't have the sorts of issues jboss has (where classes from one classloader "leak" into another). you can run into issues, though, if your sub-classloader has threads which don't want to exit. as long as all threads exit, you can safely discard the sub-classloader and restart. – jtahlborn Jan 10 '11 at 18:48
0

You can use Runtime or ProcessBuilder to relaunch your application but you probably have to modify your application a little bit as I'm pretty sure you don't have a way to retrieve the java executable full path from within the JVM.

I suggest you to implement a launcher (as an executable or a script) and use the java return code to know if you need to exit or if you need to exit or restart.

gabuzo
  • 7,378
  • 4
  • 28
  • 36