java - मैं जावा एप्लिकेशन को पुनरारंभ कैसे कर सकता हूं?




restart application-restart (9)

असल में, आप नहीं कर सकते हैं। कम से कम एक विश्वसनीय तरीके से नहीं।

जावा प्रोग्राम को पुनरारंभ करने के लिए, आपको JVM को पुनरारंभ करने की आवश्यकता है। JVM को पुनरारंभ करने के लिए आपको आवश्यकता है

  1. इस्तेमाल किया गया java लॉन्चर का पता लगाएं। आप System.getProperty("java.home") साथ प्रयास कर सकते हैं लेकिन इस बात की कोई गारंटी नहीं है कि यह वास्तव में लॉन्चर को इंगित करेगा जिसका उपयोग आपके एप्लिकेशन को लॉन्च करने के लिए किया गया था। (लौटाया गया मूल्य -Djava.home को एप्लिकेशन लॉन्च करने के लिए इंगित नहीं कर सकता है या इसे -Djava.home द्वारा ओवरराइड किया जा सकता था।)

  2. आप शायद मूल स्मृति सेटिंग्स आदि ( -Xms , -Xms , ...) का सम्मान करना चाहते हैं, इसलिए आपको यह पता लगाना होगा कि कौन सी सेटिंग्स पहले जेवीएम शुरू करने के लिए उपयोग की जाती हैं। आप ManagementFactory.getRuntimeMXBean().getInputArguments() का उपयोग करने का प्रयास कर सकते हैं लेकिन इस बात की कोई गारंटी नहीं है कि यह उपयोग की गई सेटिंग्स को प्रतिबिंबित करेगा। यह उस विधि के दस्तावेज़ीकरण में भी लिखा गया है:

    आम तौर पर, 'जावा' कमांड के लिए सभी कमांड लाइन विकल्प जावा वर्चुअल मशीन को पास नहीं किए जाते हैं। इस प्रकार, लौटाए गए इनपुट तर्कों में सभी कमांड-लाइन विकल्प शामिल नहीं हो सकते हैं।

  3. यदि आपका प्रोग्राम Standard.in से इनपुट पढ़ता है तो मूल stdin पुनरारंभ में खो जाएगा।

  4. इनमें से कई चाल और हैक्स SecurityManager प्रबंधक की उपस्थिति में असफल हो जाएंगे।

दूसरी तरफ: आपको इसकी आवश्यकता नहीं है।

मैं आपको अपने आवेदन को डिजाइन करने की सलाह देता हूं ताकि प्रत्येक चीज को साफ करना आसान हो और इसके बाद आपके "मुख्य" वर्ग का एक नया उदाहरण बन जाए।

कई अनुप्रयोगों को कुछ भी करने के लिए डिज़ाइन नहीं किया गया है लेकिन मुख्य विधि में एक उदाहरण बनाते हैं:

public class MainClass {
    ...
    public static void main(String[] args) {
        new MainClass().launch();
    }
    ...
}

इस पैटर्न का उपयोग करके, ऐसा कुछ करना आसान होना चाहिए जैसे:

public class MainClass {
    ...
    public static void main(String[] args) {
        boolean restart;
        do {
            restart = new MainClass().launch();
        } while (restart);
    }
    ...
}

और launch() सही होने दें अगर केवल तभी आवेदन बंद हो जाए, जिस पर इसे पुनरारंभ करने की आवश्यकता हो।

मैं जावा एडब्ल्यूटी एप्लिकेशन को पुनरारंभ कैसे कर सकता हूं? मेरे पास एक बटन है जिसमें मैंने एक ईवेंट हैंडलर संलग्न किया है। एप्लिकेशन को पुनरारंभ करने के लिए मुझे किस कोड का उपयोग करना चाहिए?

मैं वही काम करना चाहता हूं जो Application.Restart() एक सी # अनुप्रयोग में करते हैं।


कड़ाई से बोलते हुए, जावा प्रोग्राम ऐसा करने के बाद खुद को पुनरारंभ नहीं कर सकता है, इसलिए इसे जेवीएम को मारना चाहिए जिसमें यह चल रहा है और फिर इसे फिर से शुरू करें, लेकिन एक बार जब JVM चल रहा है (मारे गए) तो कोई कार्रवाई नहीं की जा सकती है।

आप फिर से एडब्ल्यूटी घटकों को लोड, पैक और शुरू करने के लिए कस्टम क्लासलोडर्स के साथ कुछ चाल कर सकते हैं, लेकिन इससे जीयूआई इवेंट लूप के संबंध में बहुत सारे सिरदर्द हो सकते हैं।

एप्लिकेशन लॉन्च होने के तरीके के आधार पर, आप एक रैपर स्क्रिप्ट में JVM प्रारंभ कर सकते हैं जिसमें एक डू / लूप लूप होता है, जो जारी रहता है जबकि JVM किसी विशेष कोड से बाहर निकलता है, तो एडब्ल्यूटी ऐप को System.exit(RESTART_CODE) को कॉल करना होगा । उदाहरण के लिए, छद्म छद्म कोड में:

DO
  # Launch the awt program
  EXIT_CODE = # Get the exit code of the last process
WHILE (EXIT_CODE == RESTART_CODE)

एडब्ल्यूटी ऐप को "सामान्य" समाप्ति पर RESTART_CODE के अलावा किसी अन्य चीज़ के साथ JVM से बाहर निकलना चाहिए, जिसे पुनरारंभ करने की आवश्यकता नहीं है।


जब मैं इस प्रश्न में आया तो मैं खुद विषय का शोध कर रहा था।

इस तथ्य के बावजूद कि उत्तर पहले से ही स्वीकार कर लिया गया है, मैं अभी भी पूर्णता के लिए वैकल्पिक दृष्टिकोण प्रदान करना चाहता हूं। विशेष रूप से, अपाचे एंट एक बहुत ही लचीला समाधान के रूप में कार्य करता है।

असल में, सब कुछ एक जावा स्क्रिप्ट फ़ाइल के साथ एक चींटी स्क्रिप्ट फ़ाइल में उबाल जाता है ( here और here देखें) जावा कोड से आवेदित ( here देखें)। यह जावा कोड, जो एक विधि लॉन्च हो सकता है, उस एप्लिकेशन का एक हिस्सा हो सकता है जिसे पुनरारंभ करने की आवश्यकता है। एप्लिकेशन को अपाचे एंटी लाइब्रेरी (जार) पर निर्भरता की आवश्यकता है।

जब भी एप्लिकेशन को पुनरारंभ करने की आवश्यकता होती है, तो उसे विधि लॉन्च करना चाहिए और वीएम से बाहर निकलना चाहिए। चींटी जावा कार्य में विकल्प कांटा और स्पॉन सही होना चाहिए।

यहां एक चींटी स्क्रिप्ट का एक उदाहरण दिया गया है:

<project name="applaucher" default="launch" basedir=".">
<target name="launch">
    <java classname="package.MasinClass" fork="true" spawn="true">
        <jvmarg value="-splash:splash.jpg"/>
        <jvmarg value="-D other VM params"/>
        <classpath>
            <pathelement location="lib-1.jar" />
            ...
            <pathelement location="lib-n.jar" />
        </classpath>
    </java>
</target>
</project>

लॉन्च विधि के लिए कोड इस तरह कुछ दिख सकता है:

public final void launch(final String antScriptFile) {
 /* configure Ant and execute the task */
   final File buildFile = new File(antScriptFile);
   final Project p = new Project();
   p.setUserProperty("ant.file", buildFile.getAbsolutePath());

   final DefaultLogger consoleLogger = new DefaultLogger();
   consoleLogger.setErrorPrintStream(System.err);
   consoleLogger.setOutputPrintStream(System.out);
   consoleLogger.setMessageOutputLevel(Project.MSG_INFO);
   p.addBuildListener(consoleLogger);

   try {
       p.fireBuildStarted();
       p.init();
       final ProjectHelper helper = ProjectHelper.getProjectHelper();
       p.addReference("ant.projectHelper", helper);
       helper.parse(p, buildFile);
       p.executeTarget(p.getDefaultTarget());
       p.fireBuildFinished(null);
   } catch (final BuildException e) {
       p.fireBuildFinished(e);
   }

   /* exit the current VM */
   System.exit(0);

}

यहां एक बहुत ही सुविधाजनक बात यह है कि प्रारंभिक एप्लिकेशन के साथ-साथ पुनरारंभ करने के लिए उसी स्क्रिप्ट का उपयोग किया जाता है।


पुराना सवाल और वह सब। लेकिन यह एक और तरीका है जो कुछ फायदे प्रदान करता है।

विंडोज़ पर, आप कार्य शेड्यूलर से अपने ऐप को फिर से शुरू करने के लिए कह सकते हैं। ऐप को पुनरारंभ करने से पहले विशिष्ट समय का इंतजार करने का इसका लाभ है। आप कार्य प्रबंधक पर जा सकते हैं और कार्य को हटा सकते हैं और यह दोहराना बंद कर देता है।

SimpleDateFormat hhmm = new SimpleDateFormat("kk:mm");    
Calendar aCal = Calendar.getInstance(); 
aCal.add(Calendar.SECOND, 65);
String nextMinute = hhmm.format(aCal.getTime()); //Task Scheduler Doesn't accept seconds and won't do current minute.
String[] create = {"c:\\windows\\system32\\schtasks.exe", "/CREATE", "/F", "/TN", "RestartMyProg", "/SC", "ONCE", "/ST", nextMinute, "/TR", "java -jar c:\\my\\dev\\RestartTest.jar"};  
Process proc = Runtime.getRuntime().exec(create, null, null);
System.out.println("Exit Now");
try {Thread.sleep(1000);} catch (Exception e){} // just so you can see it better
System.exit(0);

बेशक जावा एप्लिकेशन को पुनरारंभ करना संभव है।

निम्न विधि जावा अनुप्रयोग को पुनरारंभ करने का एक तरीका दिखाती है:

public void restartApplication()
{
  final String javaBin = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java";
  final File currentJar = new File(MyClassInTheJar.class.getProtectionDomain().getCodeSource().getLocation().toURI());

  /* is it a jar file? */
  if(!currentJar.getName().endsWith(".jar"))
    return;

  /* Build command: java -jar application.jar */
  final ArrayList<String> command = new ArrayList<String>();
  command.add(javaBin);
  command.add("-jar");
  command.add(currentJar.getPath());

  final ProcessBuilder builder = new ProcessBuilder(command);
  builder.start();
  System.exit(0);
}

असल में यह निम्नलिखित करता है:

  1. जावा निष्पादन योग्य खोजें (मैंने यहां जावा बाइनरी का उपयोग किया है, लेकिन यह आपकी आवश्यकताओं पर निर्भर करता है)
  2. आवेदन ढूंढें (मेरे मामले में एक जार, MyClassInTheJar क्लास का उपयोग करके जार स्थान ढूंढने के लिए)
  3. जार को पुनरारंभ करने के लिए एक कमांड बनाएं (इस मामले में जावा बाइनरी का उपयोग करके)
  4. इसे निष्पादित करो! (और इस प्रकार वर्तमान एप्लिकेशन को समाप्त करना और इसे फिर से शुरू करना)

यदि आपको वास्तव में अपने ऐप को पुनरारंभ करने की आवश्यकता है, तो आप इसे शुरू करने के लिए एक अलग ऐप लिख सकते हैं ...

यह पृष्ठ विभिन्न परिदृश्यों के लिए कई अलग-अलग उदाहरण प्रदान करता है:

http://www.rgagnon.com/javadetails/java-0014.html


योड के ' improved ' उत्तर के समान, लेकिन आगे के सुधार (कार्यात्मक, पठनीयता और परीक्षण दोनों) के साथ। अब चलाने के लिए सुरक्षित है, और कार्यक्रम तर्कों की मात्रा के रूप में कई बार पुनरारंभ होता है।

  • JAVA_TOOL_OPTIONS विकल्पों का कोई संचय नहीं।
  • स्वचालित रूप से मुख्य वर्ग पाता है।
  • वर्तमान stdout / stderr विरासत।
public static void main(String[] args) throws Exception {
    if (args.length == 0)
        return;
    else
        args = Arrays.copyOf(args, args.length - 1);

    List<String> command = new ArrayList<>(32);
    appendJavaExecutable(command);
    appendVMArgs(command);
    appendClassPath(command);
    appendEntryPoint(command);
    appendArgs(command, args);

    System.out.println(command);
    try {
        new ProcessBuilder(command).inheritIO().start();
    } catch (IOException ex) {
        ex.printStackTrace();
    }
}

private static void appendJavaExecutable(List<String> cmd) {
    cmd.add(System.getProperty("java.home") + File.separator + "bin" + File.separator + "java");
}

private static void appendVMArgs(Collection<String> cmd) {
    Collection<String> vmArguments = ManagementFactory.getRuntimeMXBean().getInputArguments();

    String javaToolOptions = System.getenv("JAVA_TOOL_OPTIONS");
    if (javaToolOptions != null) {
        Collection<String> javaToolOptionsList = Arrays.asList(javaToolOptions.split(" "));
        vmArguments = new ArrayList<>(vmArguments);
        vmArguments.removeAll(javaToolOptionsList);
    }

    cmd.addAll(vmArguments);
}

private static void appendClassPath(List<String> cmd) {
    cmd.add("-cp");
    cmd.add(ManagementFactory.getRuntimeMXBean().getClassPath());
}

    private static void appendEntryPoint(List<String> cmd) {
    StackTraceElement[] stackTrace          = new Throwable().getStackTrace();
    StackTraceElement   stackTraceElement   = stackTrace[stackTrace.length - 1];
    String              fullyQualifiedClass = stackTraceElement.getClassName();
    String              entryMethod         = stackTraceElement.getMethodName();
    if (!entryMethod.equals("main"))
        throw new AssertionError("Entry point is not a 'main()': " + fullyQualifiedClass + '.' + entryMethod);

    cmd.add(fullyQualifiedClass);
}

private static void appendArgs(List<String> cmd, String[] args) {
    cmd.addAll(Arrays.asList(args));
}

V1.1 बगफिक्स: JAVA_TOOL_OPTIONS सेट नहीं होने पर शून्य सूचक

उदाहरण:

$ java -cp Temp.jar Temp a b c d e
[/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java, -cp, Temp.jar, Temp, a, b, c, d]
[/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java, -cp, Temp.jar, Temp, a, b, c]
[/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java, -cp, Temp.jar, Temp, a, b]
[/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java, -cp, Temp.jar, Temp, a]
[/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java, -cp, Temp.jar, Temp]
$

विंडोज

public void restartApp(){

    // This launches a new instance of application dirctly, 
    // remember to add some sleep to the start of the cmd file to make sure current instance is
    // completely terminated, otherwise 2 instances of the application can overlap causing strange
    // things:)

    new ProcessBuilder("cmd","/c start /min c:/path/to/script/that/launches/my/application.cmd ^& exit").start();
    System.exit(0);
}

/ मिनट को कम से कम विंडो में स्क्रिप्ट शुरू करने के लिए

^ और समाप्त होने के बाद cmd विंडो बंद करने के लिए बाहर निकलें

एक नमूना cmd स्क्रिप्ट हो सकता है

@echo off
rem add some sleep (e.g. 10 seconds) to allow the preceding application instance to release any open resources (like ports) and exit gracefully, otherwise the new instance could fail to start
sleep 10   
set path=C:\someFolder\application_lib\libs;%path%
java -jar application.jar

10 सेकंड के लिए 10 नींद सो जाओ


import java.io.File;
import java.io.IOException;
import java.lang.management.ManagementFactory;

public class Main {
    public static void main(String[] args) throws IOException, InterruptedException {
        StringBuilder cmd = new StringBuilder();
        cmd.append(System.getProperty("java.home") + File.separator + "bin" + File.separator + "java ");
        for (String jvmArg : ManagementFactory.getRuntimeMXBean().getInputArguments()) {
            cmd.append(jvmArg + " ");
        }
        cmd.append("-cp ").append(ManagementFactory.getRuntimeMXBean().getClassPath()).append(" ");
        cmd.append(Main.class.getName()).append(" ");
        for (String arg : args) {
            cmd.append(arg).append(" ");
        }
        Runtime.getRuntime().exec(cmd.toString());
        System.exit(0);
    }
}

उन सभी को समर्पित जो कहते हैं कि यह असंभव है।

यह प्रोग्राम मूल कमांडलाइन को पुनर्निर्माण के लिए उपलब्ध सभी जानकारी एकत्र करता है। फिर, यह इसे लॉन्च करता है और चूंकि यह एक ही कमांड है, इसलिए आपका एप्लिकेशन दूसरी बार शुरू होता है। फिर हम मूल कार्यक्रम से बाहर निकलते हैं, बाल कार्यक्रम चल रहा है (यहां तक ​​कि लिनक्स के नीचे भी) और वही काम करता है।

चेतावनी : यदि आप इसे चलाते हैं, तो ध्यान रखें कि यह कभी भी नई प्रक्रियाओं को समाप्त नहीं करता है, जो कि कांटा बम के समान होता है।







application-restart