4

I have a java application which start an another java application (third party) in background, so before launching third party background application I want to check whether that application is already running or not(don't want to wait for termination of that application).
I am using the following code for launching the third party java application :

String path = new java.io.File("do123-child.cmd").getCanonicalPath();
Runtime.getRuntime().exec(path);

Note : file "do123-child.cmd" call a ".bat" file to run that application.

To check whether a given application is running or not I am using following code [ Ref link ]:

boolean result = false;
try {
    String line;
    Process p = Runtime.getRuntime().exec("tasklist.exe");
    BufferedReader input =
            new BufferedReader(new InputStreamReader(p.getInputStream()));
    while ((line = input.readLine()) != null) {
        if(line.startsWith("myApp.exe")){
            result = true;
            break;
        }
     }
     input.close();
} catch (Exception err) {
     err.printStackTrace();
}
return result;

I want to know whether is there any another way to do this without iterating the all processes currently running ? Like :

Process p = Runtime.getRuntime().exec("tasklist /FI \"IMAGENAME eq myApp.exe\" /NH");
int exitVal = p.exitValue();
//if above code throw "java.lang.IllegalThreadStateException" means application is running.

but above code return 0 for all application.

Thanks in advance.

Community
  • 1
  • 1
BhushanK
  • 1,205
  • 6
  • 23
  • 39
  • @MichaelLaffargue : In the given link (by you) code wait for the termination of the process/application, but in my scenario I don't want to wait for the termination of the application, I just want to know whether application is running or not. – BhushanK Jun 04 '15 at 09:00
  • My Bad @Bhushan. `tasklist` is the way to go on Windows (unless you want to use [JNA](https://github.com/twall/jna) ) – Michael Laffargue Jun 04 '15 at 09:12
  • @MichaelLaffargue : Actually I don't want to use `JNA` as my application is for both windows and MAC , above code will work for both just I have to change command `"tasklist.exe"` to mac specific, means command will get decided as per the OS type but logic would be similar (yet haven't tried this code on MAC). – BhushanK Jun 04 '15 at 09:21

1 Answers1

6

You could use jps to inspect the Java applications running. jps is bundled with the JRE.

jps -l
19109 sun.tools.jps.Jps
15031 org.jboss.Main
14040 
14716

You could scrape the list from this program using Runtime.getRuntime().exec() and reading the input stream, then search the package names for a match within Java.

Since you want to avoid iterating all the results, you could grep the result using findstr to return the basic p.exitValue() result you are looking for:

Process p = Runtime.getRuntime().exec("jps -l | findstr /R /C:\"com.myapp.MyApp\"");
int exitVal = p.exitValue(); // Returns 0 if running, 1 if not

Of course findstr is Windows-specific, so you'll need to use grep instead on the Mac:

Process p = Runtime.getRuntime().exec("jps -l | grep \"com.myapp.MyApp\"");
int exitVal = p.exitValue(); // Returns 0 if running, 1 if not

The jps tool uses an internal API (MonitoredHost) to obtain this information, so you could do this entirely within Java as well:

String processName = "com.myapp.MyApp";

boolean running = false;
HostIdentifier hostIdentifier = new HostIdentifier("local://localhost");

MonitoredHost monitoredHost;
monitoredHost = MonitoredHost.getMonitoredHost(hostIdentifier);

Set activeVms = monitoredHost.activeVms();
for (Object activeVmId : activeVms) {
    VmIdentifier vmIdentifier = new VmIdentifier("//" + String.valueOf(activeVmId) + "?mode=r");
        MonitoredVm monitoredVm = monitoredHost.getMonitoredVm(vmIdentifier);
    if (monitoredVm != null) {
        String mainClass = MonitoredVmUtil.mainClass(monitoredVm, true);
        if (mainClass.toLowerCase().equals(processName.toLowerCase())) {
            running = true;
            break;
        }
    }
}

System.out.print(running);
Community
  • 1
  • 1
seanhodges
  • 17,426
  • 15
  • 71
  • 93
  • Only working with JVM process no? Which is what the OP want, just to perfect my knowledge. – Michael Laffargue Jun 04 '15 at 09:38
  • Yes, this only works with JVM processes. If you want to monitor a non-Java application then you'll need to use a different solution. – seanhodges Jun 04 '15 at 09:49
  • @seanhodges : I am confused on `String processName = "com.myapp.MyApp";` whether `"com.myapp.MyApp"` is ImageName or Class name ? If it is class name then how can i come to know the class name of the another java application(third party) ? – BhushanK Jun 05 '15 at 05:17
  • 1
    That's an easy one. My example above shows "org.jboss.Main", which indicates a JBoss instance. If the package name is not obvious then run `jps -l` with the application closed and then open - the new process will be missing in the first listing but visible in the second. – seanhodges Jun 05 '15 at 09:20