Est-il possible de redémarrer la JVM? En tant que dans ne pas quitter réellement, mais fermez et rechargez toutes les classes, et exécutez principal du haut?
Votre meilleur choix est probablement d'exécuter l'interpréteur Java dans une boucle et de quitter. Par exemple:
#!/bin/sh
while true
do
Java MainClass
done
Si vous souhaitez avoir la possibilité de redémarrer ou d’arrêter complètement, vous pouvez tester l’état de sortie:
#!/bin/sh
STATUS=0
while [ $STATUS -eq 0 ]
do
Java MainClass
STATUS=$?
done
Dans le programme Java, vous pouvez utiliser System.exit (0) pour indiquer que vous souhaitez "redémarrer" et System.exit (1) pour indiquer que vous souhaitez vous arrêter et rester arrêté.
La machine virtuelle Java d'IBM dispose d'une fonctionnalité appelée "réinitialisable" qui vous permet de faire efficacement ce que vous demandez.
À part la machine virtuelle IBM, je ne pense pas que ce soit possible.
Pas un vrai "redémarrage" mais:
Vous pouvez créer votre propre chargeur de classes et charger toutes vos classes (sauf un bootstrap) avec. Ensuite, lorsque vous souhaitez "redémarrer", assurez-vous de procéder comme suit:
Cette procédure est utilisée (dans une certaine mesure) lors de la "permutation à chaud" d'applications Web dans des serveurs Web.
Notez cependant que les membres de classe statiques et les objets "globaux" de la machine virtuelle Java (ceux auxquels accède une racine de GC qui n'est pas sous votre contrôle) resteront. Par exemple, Locale.setLocale () affecte un membre statique à Locale. Comme la classe Locale est chargée par le chargeur de classes du système, elle ne sera pas "redémarrée". Cela signifie que l'ancien objet Locale utilisé dans Locale.setLocale () sera disponible après s'il n'a pas été explicitement nettoyé.
Une autre voie à suivre est l'instrumentation des classes. Cependant, comme je ne connais que très peu de choses, j’hésite à donner des conseils.
Explication sur le déploiement à chaud avec quelques exemples
Si vous travaillez sur un serveur d'applications, ils sont généralement dotés de mécanismes de déploiement à chaud intégrés qui rechargent toutes les classes de votre application (application Web, application d'entreprise) lorsque vous la redéployez.
Sinon, vous devrez chercher des solutions commerciales. Java Rebel ( http://www.zeroturnaround.com/javarebel/ ) est l'une de ces options.
Autant que je sache, il n'y a pas de telle façon.
Notez que s’il existait un moyen de le faire, cela dépendrait beaucoup du code chargé actuel pour libérer correctement toutes les ressources conservées afin de permettre un redémarrage en douceur (pensez aux fichiers, aux connexions socket/tcp/http/database, aux threads, etc.). ).
Certaines applications, telles que Jboss AS, capturent Ctrl + C sur la console et fournissent un arrêt en douceur, fermant toutes les ressources, mais il s'agit d'un code spécifique à l'application et non d'une fonctionnalité JVM.
C'est facile en JavaX: vous pouvez utiliser les fonctions standard nohupJavax () ou restart () .
Eh bien, j'ai actuellement cela, cela fonctionne parfaitement et complètement indépendant du système d'exploitation. La seule chose qui doit fonctionner: exécuter le processus Java sans chemin/etc, mais je pense que cela peut aussi être corrigé.
Les petits morceaux de code proviennent tous de stackoverflow sauf RunnableWithObject et restartMinecraft () :)
Vous devez l'appeler comme ceci:
restartMinecraft(getCommandLineArgs());
Donc, ce qu'il fait, en gros, c'est:
Et oui, il est directement tiré de mon projet minecraft :)
Le code:
Méthode Tools.isProcessExited ():
public static boolean isProcessExited(Process p) {
try {
p.exitValue();
} catch (IllegalThreadStateException e) {
return false;
}
return true;
}
Méthode Tools.restartMinecraft ():
public static void restartMinecraft(String args) throws IOException, InterruptedException {
//Here you can do shutdown code etc
Process p = Runtime.getRuntime().exec(args);
RunnableWithObject<Process> inputStreamPrinter = new RunnableWithObject<Process>() {
@Override
public void run() {
// TODO Auto-generated method stub
while (!Tools.isProcessExited(data)) {
try {
while (data.getInputStream().available() > 0) {
System.out.print((char) data.getInputStream().read());
}
} catch (IOException e) {
}
}
}
};
RunnableWithObject<Process> errorStreamPrinter = new RunnableWithObject<Process>() {
@Override
public void run() {
// TODO Auto-generated method stub
while (!Tools.isProcessExited(data)) {
try {
while (data.getErrorStream().available() > 0) {
System.err.print((char) data.getErrorStream().read());
}
} catch (IOException e) {
}
}
}
};
inputStreamPrinter.data = p;
errorStreamPrinter.data = p;
new Thread(inputStreamPrinter).start();
new Thread(errorStreamPrinter).start();
p.waitFor();
System.out.println("Minecraft exited. (" + p.exitValue() + ")");
System.exit(p.exitValue());
}
Méthode Tools.getCommandLineArgs ():
public static String getCommandLineArgs() {
String cmdline = "";
List<String> l = ManagementFactory.getRuntimeMXBean().getInputArguments();
cmdline += "Java ";
for (int i = 0; i < l.size(); i++) {
cmdline += l.get(i) + " ";
}
cmdline += "-cp " + System.getProperty("Java.class.path") + " " + System.getProperty("Sun.Java.command");
return cmdline;
}
Aaaaet enfin la classe RunnableWithObject:
package generic.minecraft.infinityclient;
public abstract class RunnableWithObject<T> implements Runnable {
public T data;
}
Bonne chance :)
Je fais quelque chose de similaire en utilisant JMX, je «déchargerai» un module en utilisant JMX, puis je le «rechargerai». En coulisse, je suis sûr qu'ils utilisent un chargeur de classe différent.