How can a Java program get its own process ID? - java

How do I get the id of my Java process?
I know there are several platform-dependent hacks, but I would prefer a more generic solution.

There exists no platform-independent way that can be guaranteed to work in all jvm implementations.
ManagementFactory.getRuntimeMXBean().getName() looks like the best (closest) solution, and typically includes the PID. It's short, and probably works in every implementation in wide use.
On linux+windows it returns a value like "12345#hostname" (12345 being the process id). Beware though that according to the docs, there are no guarantees about this value:
Returns the name representing the running Java virtual machine. The
returned name string can be any arbitrary string and a Java virtual
machine implementation can choose to embed platform-specific useful
information in the returned name string. Each running virtual machine
could have a different name.
In Java 9 the new process API can be used:
long pid = ProcessHandle.current().pid();

You could use JNA. Unfortunately there is no common JNA API to get the current process ID yet, but each platform is pretty simple:
Windows
Make sure you have jna-platform.jar then:
int pid = Kernel32.INSTANCE.GetCurrentProcessId();
Unix
Declare:
private interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);
int getpid ();
}
Then:
int pid = CLibrary.INSTANCE.getpid();
Java 9
Under Java 9 the new process API can be used to get the current process ID. First you grab a handle to the current process, then query the PID:
long pid = ProcessHandle.current().pid();

Here's a backdoor method which might not work with all VMs but should work on both linux and windows (original example here):
java.lang.management.RuntimeMXBean runtime =
java.lang.management.ManagementFactory.getRuntimeMXBean();
java.lang.reflect.Field jvm = runtime.getClass().getDeclaredField("jvm");
jvm.setAccessible(true);
sun.management.VMManagement mgmt =
(sun.management.VMManagement) jvm.get(runtime);
java.lang.reflect.Method pid_method =
mgmt.getClass().getDeclaredMethod("getProcessId");
pid_method.setAccessible(true);
int pid = (Integer) pid_method.invoke(mgmt);

Try Sigar . very extensive APIs. Apache 2 license.
private Sigar sigar;
public synchronized Sigar getSigar() {
if (sigar == null) {
sigar = new Sigar();
}
return sigar;
}
public synchronized void forceRelease() {
if (sigar != null) {
sigar.close();
sigar = null;
}
}
public long getPid() {
return getSigar().getPid();
}

The following method tries to extract the PID from java.lang.management.ManagementFactory:
private static String getProcessId(final String fallback) {
// Note: may fail in some JVM implementations
// therefore fallback has to be provided
// something like '<pid>#<hostname>', at least in SUN / Oracle JVMs
final String jvmName = ManagementFactory.getRuntimeMXBean().getName();
final int index = jvmName.indexOf('#');
if (index < 1) {
// part before '#' empty (index = 0) / '#' not found (index = -1)
return fallback;
}
try {
return Long.toString(Long.parseLong(jvmName.substring(0, index)));
} catch (NumberFormatException e) {
// ignore
}
return fallback;
}
Just call getProcessId("<PID>"), for instance.

For older JVM, in linux...
private static String getPid() throws IOException {
byte[] bo = new byte[256];
InputStream is = new FileInputStream("/proc/self/stat");
is.read(bo);
for (int i = 0; i < bo.length; i++) {
if ((bo[i] < '0') || (bo[i] > '9')) {
return new String(bo, 0, i);
}
}
return "-1";
}

Since Java 9 there is a method Process.getPid() which returns the native ID of a process:
public abstract class Process {
...
public long getPid();
}
To get the process ID of the current Java process one can use the ProcessHandle interface:
System.out.println(ProcessHandle.current().pid());

You can check out my project: JavaSysMon on GitHub. It provides process id and a bunch of other stuff (CPU usage, memory usage) cross-platform (presently Windows, Mac OSX, Linux and Solaris)

java.lang.management.ManagementFactory.getRuntimeMXBean().getName().split("#")[0]

In Scala:
import sys.process._
val pid: Long = Seq("sh", "-c", "echo $PPID").!!.trim.toLong
This should give you a workaround on Unix systems until Java 9 will be released.
(I know, the question was about Java, but since there is no equivalent question for Scala, I wanted to leave this for Scala users who might stumble into the same question.)

For completeness there is a wrapper in Spring Boot for the
String jvmName = ManagementFactory.getRuntimeMXBean().getName();
return jvmName.split("#")[0];
solution. If an integer is required, then this can be summed up to the one-liner:
int pid = Integer.parseInt(ManagementFactory.getRuntimeMXBean().getName().split("#")[0]);
If someone uses Spring boot already, she/he might use org.springframework.boot.ApplicationPid
ApplicationPid pid = new ApplicationPid();
pid.toString();
The toString() method prints the pid or '???'.
Caveats using the ManagementFactory are discussed in other answers already.

public static long getPID() {
String processName = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
if (processName != null && processName.length() > 0) {
try {
return Long.parseLong(processName.split("#")[0]);
}
catch (Exception e) {
return 0;
}
}
return 0;
}

I am adding this, in addition to other solutions.
with Java 10, to get process id
final RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
final long pid = runtime.getPid();
out.println("Process ID is '" + pid);

The latest I have found is that there is a system property called sun.java.launcher.pid that is available at least on linux. My plan is to use that and if it is not found to use the JMX bean.

It depends on where you are looking for the information from.
If you are looking for the information from the console you can use the jps command. The command gives output similar to the Unix ps command and comes with the JDK since I believe 1.5
If you are looking from the process the RuntimeMXBean (as said by Wouter Coekaerts) is probably your best choice. The output from getName() on Windows using Sun JDK 1.6 u7 is in the form [PROCESS_ID]#[MACHINE_NAME]. You could however try to execute jps and parse the result from that:
String jps = [JDK HOME] + "\\bin\\jps.exe";
Process p = Runtime.getRuntime().exec(jps);
If run with no options the output should be the process id followed by the name.

This is the code JConsole, and potentially jps and VisualVM uses. It utilizes classes from
sun.jvmstat.monitor.* package, from tool.jar.
package my.code.a003.process;
import sun.jvmstat.monitor.HostIdentifier;
import sun.jvmstat.monitor.MonitorException;
import sun.jvmstat.monitor.MonitoredHost;
import sun.jvmstat.monitor.MonitoredVm;
import sun.jvmstat.monitor.MonitoredVmUtil;
import sun.jvmstat.monitor.VmIdentifier;
public class GetOwnPid {
public static void main(String[] args) {
new GetOwnPid().run();
}
public void run() {
System.out.println(getPid(this.getClass()));
}
public Integer getPid(Class<?> mainClass) {
MonitoredHost monitoredHost;
Set<Integer> activeVmPids;
try {
monitoredHost = MonitoredHost.getMonitoredHost(new HostIdentifier((String) null));
activeVmPids = monitoredHost.activeVms();
MonitoredVm mvm = null;
for (Integer vmPid : activeVmPids) {
try {
mvm = monitoredHost.getMonitoredVm(new VmIdentifier(vmPid.toString()));
String mvmMainClass = MonitoredVmUtil.mainClass(mvm, true);
if (mainClass.getName().equals(mvmMainClass)) {
return vmPid;
}
} finally {
if (mvm != null) {
mvm.detach();
}
}
}
} catch (java.net.URISyntaxException e) {
throw new InternalError(e.getMessage());
} catch (MonitorException e) {
throw new InternalError(e.getMessage());
}
return null;
}
}
There are few catches:
The tool.jar is a library distributed with Oracle JDK but not JRE!
You cannot get tool.jar from Maven repo; configure it with Maven is a bit tricky
The tool.jar probably contains platform dependent (native?) code so it is not easily
distributable
It runs under assumption that all (local) running JVM apps are "monitorable". It looks like
that from Java 6 all apps generally are (unless you actively configure opposite)
It probably works only for Java 6+
Eclipse does not publish main class, so you will not get Eclipse PID easily
Bug in MonitoredVmUtil?
UPDATE: I have just double checked that JPS uses this way, that is Jvmstat library (part of tool.jar). So there is no need to call JPS as external process, call Jvmstat library directly as my example shows. You can aslo get list of all JVMs runnin on localhost this way.
See JPS source code:

I know this is an old thread, but I wanted to call out that API for getting the PID (as well as other manipulation of the Java process at runtime) is being added to the Process class in JDK 9: http://openjdk.java.net/jeps/102

Based on Ashwin Jayaprakash's answer (+1)
about the Apache 2.0 licensed SIGAR, here is how I use it to get only the PID of the current process:
import org.hyperic.sigar.Sigar;
Sigar sigar = new Sigar();
long pid = sigar.getPid();
sigar.close();
Even though it does not work on all platforms, it does work on Linux, Windows, OS X and various Unix platforms as listed here.

You can try getpid() in JNR-Posix.
It has a Windows POSIX wrapper that calls getpid() off of libc.

I found a solution that may be a bit of an edge case and I didn't try it on other OS than Windows 10, but I think it's worth noticing.
If you find yourself working with J2V8 and nodejs, you can run a simple javascript function returning you the pid of the java process.
Here is an example:
public static void main(String[] args) {
NodeJS nodeJS = NodeJS.createNodeJS();
int pid = nodeJS.getRuntime().executeIntegerScript("process.pid;\n");
System.out.println(pid);
nodeJS.release();
}

Here is my solution:
public static boolean isPIDInUse(int pid) {
try {
String s = null;
int java_pid;
RuntimeMXBean rt = ManagementFactory.getRuntimeMXBean();
java_pid = Integer.parseInt(rt.getName().substring(0, rt.getName().indexOf("#")));
if (java_pid == pid) {
System.out.println("In Use\n");
return true;
}
} catch (Exception e) {
System.out.println("Exception: " + e.getMessage());
}
return false;
}

This is what I used when I had similar requirement. This determines the PID of the Java process correctly. Let your java code spawn a server on a pre-defined port number and then execute OS commands to find out the PID listening on the port. For Linux
netstat -tupln | grep portNumber

Related

Pinning .jar files to the taskbar in windows 7

My question is an extension on another question already answered, https://superuser.com/questions/257467/windows-7-how-to-pin-a-jar-to-the-taskbar
Is there a way to pin a jar to the taskbar, and have the window generated by the jar register as a different process, thus creating a different icon in the task bar? because as it stands, using any of the methods listed in the answer to the above question, you end up with a shortcut that can be pinned. but it is just a shortcut and only that, not the program itself. Im willing to try anything at this point as it is beginning to be very bothersome. not only does it look unprofessional, it uses up unnecessary screen real estate. As I know someone is going to ask what else I've tried, here's a bit of code i tried to run in c# to launch the jar, but of course, it does the same thing, registering the new process as a new process. (should have thought that one through.)
string strCmdText;
strCmdText = "-jar ImgurDownloader.jar";
Process process = new Process();
process.StartInfo.Arguments = strCmdText;
process.StartInfo.FileName = "javaw";
process.StartInfo.UseShellExecute = false;
process.Start();
so then I tried this:
string strCmdText;
strCmdText = "-jar ImgurDownloader.jar";
Process process = Process.GetCurrentProcess();
process.StartInfo.Arguments = strCmdText;
process.StartInfo.FileName = "javaw";
process.StartInfo.UseShellExecute = false;
process.Start();
and yet still, even if i try and replace the current process, it comes across as a new process, and thus a second icon in the taskbar. Please excuse my possibly short tone, the frustration is starting to kick in after a couple weeks.
Edit: have also tried setting the UAMID (User Application Model ID) using the JNA library to access shel32.dll's functions. The following is the code in the jar
public static void setCurrentProcessExplicitAppUserModelID(final String appID) {
if (SetCurrentProcessExplicitAppUserModelID(new WString(appID)).longValue() != 0)
throw new RuntimeException("unable to set current process explicit AppUserModelID to: " + appID);
}
public static String getCurrentProcessExplicitAppUserModelID() {
final PointerByReference r = new PointerByReference();
if (GetCurrentProcessExplicitAppUserModelID(r).longValue() == 0) {
final Pointer p = r.getValue();
return p.getString(0, true); // here we leak native memory by
// lazyness
}
return "N/A";
}
private static native NativeLong GetCurrentProcessExplicitAppUserModelID(PointerByReference appID);
private static native NativeLong SetCurrentProcessExplicitAppUserModelID(WString appID);
static {
Native.register("shell32");
}
then just call the set method. Tested with the get method, however,
NOTE: getCurrentProcessExplicitAppUserModelID is a lazy method and breaks things later on if used.
then in the C# Wrapper,
[DllImport("shell32.dll")]
public static extern int SetCurrentProcessExplicitAppUserModelID([MarshalAs(UnmanagedType.LPWStr)] string AppID);
static void Main()
{
int der = SetCurrentProcessExplicitAppUserModelID("MAndWorks.ImgurDownloader.ImgurDownloader.2.0.0.0");
string strCmdText;
Console.WriteLine(der);
strCmdText = "-jar ImgurDownloader.jar";
Process process = new Process();
process.StartInfo.Arguments = strCmdText;
process.StartInfo.FileName = "javaw";
process.StartInfo.UseShellExecute = false;
process.Start();
process.WaitForExit();
Console.WriteLine("AWFURA");
}

Detecting 32/64 -bit Java from within C on windows

I would like to find out if the Java runtime installed on a user's machine supports 32 and 64-bit, and I would like to do this from within C. I had thought that something like the following would do the trick:
Detect 64-bit java:
int f=0
char *path = (char*) malloc(32768);
char out[1035];
FILE *fp;
if(f) fprintf(f,"Checking if 64-bit Java is available via the java command\n");
java64ok = 1;
strcpy(path,"java -d64 -version 2>&1");
fp = _popen(path, "r");
if (fp == NULL) {
if(f) fprintf(f,"Failed to run command\n" );
}
if(fgets(out, sizeof(out), fp) != NULL){
if(strncmp(out,"Error",5)==0){
java64ok = 0;
}
while (fgets(out, sizeof(out), fp) != NULL) {}
}
if (feof(fp)){
pclose( fp );
}
else{
if(f) fprintf(f, "Error: Failed to read the pipe to the end.\n");
}
Detect 32-bit Java:
if(f) fprintf(f,"Checking if 32-bit Java is available via the java command\n");
java32ok = 1;
strcpy(path,"java -d32 -version 2>&1");
fp = _popen(path, "r");
if (fp == NULL) {
if(f) fprintf(f,"Failed to run command\n" );
}
if(fgets(out, sizeof(out), fp) != NULL){
if(strncmp(out,"Error",5)==0){
java32ok = 0;
}
while (fgets(out, sizeof(out), fp) != NULL) {}
}
if (feof(fp)){
pclose( fp );
}
else{
if(f) fprintf(f, "Error: Failed to read the pipe to the end.\n");
}
Unfortunately, this appears that if the user is running a 64-bit system only the 32 bit java is detected if the C code is compiled as a 32 bit executable, and only the 64-bit Java is detected if the program is compiled as a 64-bit program.
With reasonable reliability, you can check %SYSTEMROOT%\SysWOW64\java.exe (which is where 32 bit java.exe resides on a 64 bit machine), and %SYSTEMROOT%\System32\java.exe (which is where 64 bit java resides on a 64 bit machine and also where 32 bit java resides on a 32 bit machine.)
Use the Windows API function GetEnvironmentVariable to deduce %SYSTEMROOT%, or, to get started, hardcode to "C:\Windows", escaping \ as necessary.
How you detect the version externally is platform dependant. I sugges you run a short Java program to tell you.
public class Bitness {
public static void main(String... ignored) {
System.out.println(is64Bit() ? "64" : "32");
}
private static boolean is64Bit0() {
String systemProp;
systemProp = System.getProperty("com.ibm.vm.bitmode");
if (systemProp != null) {
return "64".equals(systemProp);
}
systemProp = System.getProperty("sun.arch.data.model");
if (systemProp != null) {
return "64".equals(systemProp);
}
systemProp = System.getProperty("java.vm.version");
return systemProp != null && systemProp.contains("_64");
}
}
This way you can run java -cp {whatever} Bitness and it will tell you.
the suggestion of Bathsheba is quite solid, though depending on how the PATH variable is defined on a system, it might be possible that another java.exe binary is found before %SYSTEMROOT%\, so there is a chance that a different java version is used.
My suggestion would be to first parse PATH environment variable and find the first hit for java. Second step would be to look at the COFF header of the java.exe file.
With the ImageNtHeader function, you can query the NT header and this contains the field FileHeader, which is a IMAGE_FILE_HEADER.
Here's some example on how you would implement this:
https://stackoverflow.com/a/4316804/435583
Hope this helps you out.
Cheers

How to get jboss7 version in java programatically through? [duplicate]

This question already has answers here:
How do I programmatically obtain the version in JBoss AS 5.1?
(2 answers)
Closed 8 years ago.
i have use j boss 4.2.2 to latest version.i have use java development kit 1.5 to 1.7 latest version all j boss version in get all java development kit. how to get j boss version in java code through.
With 5 there is a properties file: /org/jboss/version.properties where the keys version.major and version.minor looks for your case. Sust load the file to Properties and read. See link below:
http://grepcode.com/file/repository.jboss.org/nexus/content/repositories/releases/org.jboss.jbossas/jboss-as-main/5.0.0.CR2/org/jboss/version.properties
This file has been kept also in jboss6.1
http://grepcode.com/file/repository.jboss.org/nexus/content/repositories/releases/org.jboss.jbossas/jboss-as-main/6.1.0.Final/org/jboss/version.properties?av=f
I realized you asked for jboss7.... but I leave the work I did in case can be useful (it is anyway an approach valid for 5 and 6 versions)
For jboss7 I found two ways:
WAY 1
Checking out the code from github I cannot find anymore this Versoin.properties in the sources.
But I could find a Version.class which stores the version and release code name as properties; you can use Version.AS_VERSION to get what you want as you can see from the source code:
public class Version {
public static final String AS_VERSION;
public static final String AS_RELEASE_CODENAME;
public static final int MANAGEMENT_MAJOR_VERSION = 1;
public static final int MANAGEMENT_MINOR_VERSION = 4;
public static final int MANAGEMENT_MICRO_VERSION = 0;
static {
InputStream stream = Version.class.getClassLoader().getResourceAsStream("META-INF/MANIFEST.MF");
Manifest manifest = null;
try {
if (stream != null)
manifest = new Manifest(stream);
} catch (Exception e) {
}
String version = null, code = version;
if (manifest != null) {
version = manifest.getMainAttributes().getValue("JBossAS-Release- Version");
code = manifest.getMainAttributes().getValue("JBossAS-Release-Codename");
}
if (version == null) {
version = "Unknown";
}
if (code == null) {
code = "Unknown";
}
AS_VERSION = version;
AS_RELEASE_CODENAME = code;
}
}
WAY2
Another option that I found googling but I didn't verify personally is going through JMX (perhaps you prefer this approach):
ModelControllerClient client = ModelControllerClient.Factory.create(InetAddress.getByName("localhost"), 9999);
ModelNode op = new ModelNode();
op.get(ClientConstants.OP).set("read-resource");
ModelNode returnVal = client.execute(op);
logger.info("release-version: " + returnVal.get("result").get("release-version").asString());
logger.info("release-codename: " + returnVal.get("result").get("release-codename").asString());
And from the jboss-admin command line interface, you can get the info from these commands:
/:read-attribute(name=release-version)
/:read-attribute(name=release-codename)
NOTE:
The source code are now under git clone https://github.com/wildfly/wildfly.git (the jboss website still send to an outdated link)
Try this tutorial: https://community.jboss.org/thread/176932?start=0&tstart=0
or this: How do I programmatically obtain the version in JBoss AS 5.1?

JNetPcap in eclipse does not print error... Ubuntu 12.04

Have some problems with JNetPcap.
I uses Ubuntu 12.04, and trying to make packet snipper that based in java language.
What I did is below.
I have downloaded JNetPcap 1.3.0.
And as tutorial said built a java project.
http://jnetpcap.com/examples/dumper <- this is the link.
I typed just like that link and I got my first problem.
PcapHandler Class is deprecated. So I find the document and replace it with ByteBufferHandler.
Now I compile this project and got an unsatifiedLinked Error.
I have tried with static block to load that library.
After some attempts I copied "libjnetpcap.so" to /usr/lib/
now I remove unsatisfiedLinked Error. but somehow it stops in 1st Error check.
It prints "1st error check : ", then exit automatically.
public static void main(String[] args) {
List<PcapIf> alldevs = new ArrayList<PcapIf>();
StringBuilder errbuff = new StringBuilder();
int r = Pcap.findAllDevs(alldevs, errbuff);
//============1st check
if(r == Pcap.NOT_OK || alldevs.isEmpty()){
System.err.printf("1st error check : %s\n", errbuff.toString());
return;
}
PcapIf device = alldevs.get(1);
//===================== END
int snaplen = 64 * 1024;
int flags = Pcap.MODE_PROMISCUOUS;
int timeout = 10 * 1000;
Pcap pcap = Pcap.openLive(device.getName(),snaplen, flags, timeout, errbuff);
//============2nd check
if(pcap == null){
System.err.printf("2nd error check : %s\n", errbuff.toString());
return;
}
//===================== END
String ofile = "/home/juneyoungoh/tmp_capture_file.cap";
final PcapDumper dumper = pcap.dumpOpen(ofile);
ByteBufferHandler<PcapDumper> handler = new ByteBufferHandler<PcapDumper>() {
#Override
public void nextPacket(PcapHeader arg0, ByteBuffer arg1, PcapDumper arg2) {
dumper.dump(arg0, arg1);
}
};
pcap.loop(10,handler, dumper);
File file = new File(ofile);
System.out.printf("%s file has %d bytes in it!\n", ofile, file.length());
dumper.close();
pcap.close();
if(file.exists()){
file.delete();
}
}
if is there any good reference or wonderful idea, please share.
Thanks.
On Linux, a program will probably have to run as root, or with sufficient privileges granted in some other fashion, in order to be able to open any devices, and, currently, pcap_findalldevs(), which is presumably what the Pcap.findAllDevs method uses, tries to open each of the devices it finds, and only returns the devices it can open.
So you'll have to run your Java program as root, or will somehow have to arrange that it have sufficient privileges (CAP_NET_RAW and CAP_NET_ADMIN) to get a list of network adapters and open those adapters.

Execute a Java program from our Java program

I used
Runtime.getRuntime().exec("_____")
but it throws a IOException as below:
java.io.IOException: CreateProcess: c:/ error=5
at java.lang.Win32Process.create(Native Method)
at java.lang.Win32Process.<init>(Win32Process.java:63)
at java.lang.Runtime.execInternal(Native Method
I don't know whether I have the problem with specifying the path or something else. Can anyone please help me with the code.
You're trying to execute "C:/". You'll want to execute something like:
"javaw.exe d:\\somejavaprogram\\program.jar"
Notice the path separators.
I'm assuming this is for an ad-hoc project, rather than something large. However, for best practice running external programs from code:
Don't hardcode the executable location, unless you're certain it will never change
Look up directories like %windir% using System.getenv
Don't assume programs like javaw.exe are in the search path: check them first, or allow the user to specify a location
Make sure you're taking spaces into account: "cmd /c start " + myProg will not work if myProg is "my program.jar".
You can either launch another JVM (as described in detail in other answers).
But that is not a solution i would prefer.
Reasons are:
calling a native program from java is "dirty" (and sometimes crashes your own VM)
you need to know the path to the external JVM (modern JVMs don't set JAVA_HOME anymore)
you have no control on the other program
Main reason to do it anyway is, that the other application has no control over your part of the program either. And more importantly there's no trouble with unresponsive system threads like the AWT-Thread if the other application doesn't know its threading 101.
But! You can achieve more control and similar behaviour by using an elementary plugin technique. I.e. just call "a known interface method" the other application has to implement. (in this case the "main" method).
Only it's not quite as easy as it sounds to pull this off.
you have to dynamically include required jars at runtime (or include them in the classpath for your application)
you have to put the plugin in a sandbox that prevents compromising critical classes to the other application
And this calls for a customized classloader. But be warned - there are some well hidden pitfalls in implementing that. On the other hand it's a great exercise.
So, take your pick: either quick and dirty or hard but rewarding.
java.io.IOException: CreateProcess: c:/ error=5
at java.lang.Win32Process.create(Native Method)
at java.lang.Win32Process.<init>(Win32Process.java:63)
at java.lang.Runtime.execInternal(Native Method)
If I recall correctly, error code 5 means access denied. This could be because your path is incorrect (trying to execute "c:/") or you are bumping against your OS security (in which case, look at the permissions).
If you are having trouble locating the Java executable, you can usually find it using system properties:
public class LaunchJre {
private static boolean isWindows() {
String os = System.getProperty("os.name");
if (os == null) {
throw new IllegalStateException("os.name");
}
os = os.toLowerCase();
return os.startsWith("windows");
}
public static File getJreExecutable() throws FileNotFoundException {
String jreDirectory = System.getProperty("java.home");
if (jreDirectory == null) {
throw new IllegalStateException("java.home");
}
File exe;
if (isWindows()) {
exe = new File(jreDirectory, "bin/java.exe");
} else {
exe = new File(jreDirectory, "bin/java");
}
if (!exe.isFile()) {
throw new FileNotFoundException(exe.toString());
}
return exe;
}
public static int launch(List<String> cmdarray) throws IOException,
InterruptedException {
byte[] buffer = new byte[1024];
ProcessBuilder processBuilder = new ProcessBuilder(cmdarray);
processBuilder.redirectErrorStream(true);
Process process = processBuilder.start();
InputStream in = process.getInputStream();
while (true) {
int r = in.read(buffer);
if (r <= 0) {
break;
}
System.out.write(buffer, 0, r);
}
return process.waitFor();
}
public static void main(String[] args) {
try {
Runtime.getRuntime().exec("c:/");
List<String> cmdarray = new ArrayList<String>();
cmdarray.add(getJreExecutable().toString());
cmdarray.add("-version");
int retValue = launch(cmdarray);
if (retValue != 0) {
System.err.println("Error code " + retValue);
}
System.out.println("OK");
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
(Tested Windows XP, Sun JRE 1.6; Ubuntu 8.04, OpenJDK JRE 1.6)
This is the equivalent of running:
java -version
You may also want to look at the "java.library.path" system property (and "path.separator") when trying to locate the executable.
How about just calling the main from your java program?
Test.main(null);
This worked fine for me
Is there any reason you can't just call it directly in your Java code?
If there is a reason I've not tried it for executing a Java Program but you could try Jakarta Commons Exec works well for executing most programs.
I had to do this recently.
Here is how I did it, picking up only the relevant parts:
private static final String[] straJavaArgs =
{
"?i/j2re/bin/java",
"-ms64m",
"-mx64m",
"-Djava.ext.dirs=?i/lib;?i/jar/lib;?i/jar"
};
// ...
// AppDesc appToRun;
List<String> params = new ArrayList<String>();
// Java exe and parameters
params.addAll(ExpandStrings(straJavaArgs));
// Common VM arguments
params.addAll(Arrays.asList(AppDesc.GetCommonVMArgs()));
// Specific VM arguments
params.addAll(ExpandStrings(appToRun.GetVMArgs()));
// The program to run
params.add(appToRun.GetClass());
// Its arguments
params.addAll(ExpandStrings(appToRun.GetProgramArgs()));
// The common arguments
params.addAll(ExpandStrings(AppDesc.GetCommonProgramArgs()));
ProcessBuilder processBuilder = new ProcessBuilder(params);
process = processBuilder.start();
return CaptureProcessOutput(); // Uses a StreamGobbler class
protected ArrayList<String> ExpandStrings(String[] stra)
{
ArrayList<String> alResult = new ArrayList<String>();
for (int i = 0; i < stra.length; i++)
{
// Super flexible, eh? Ad hoc for the current task, at least...
alResult.add(stra[i]
.replaceAll("\\?i", strInstallDir)
.replaceAll("\\?c", strConfigDir)
);
}
return alResult;
}
public enum AppDesc
{
// Enumerate the applications to run, with their parameters
}
Incomplete, if you need more details, just ask.
public class Test {
public static void main(String[] args) throws Exception {
Process p = Runtime.getRuntime().exec("\"c:/program files/windows/notepad.exe\"");
p.waitFor();
}
}
The above works quite well, instead of passing \"c:/program files/windows/notepad.exe\" as the arguments for the executable, use the path to your program, I'm not sure if this solution is JVM version dependent, or if it can use relative paths.
You must pass the path of your executable at the exec method. Are you really trying to execute the "-" process?
Also, have a look at this for some useful tips.
Put ant lib in you classpath ( project lib ) and run this code :
import org.apache.tools.ant.taskdefs.Execute;
Execute exe = new Execute();
exe.setCommandline(new String[]{"java", "-version"});
exe.execute();
I can't remember the exact code that I used to get this to work, but you have to pass "java.exe" (or the equivalent) as the executable, and then the class or jar to run as the parameter, with the correct working directory. So it's not as simple as just calling one method.
I had a similiar problem. I needed to run a section of Java code in a seperate VM as it invoked native code via JNI that occasionally blew up taking out the entire VM.
I cheated a little though. I initially used Runtime to invoke a simple batch command file and put the work-in-progress java command in there. This enabled me to tweak it as needed and to run the command in a DOS prompt for easy testing. Once it was finished I simply copied the result into the Runtime invocation.
First you compile the prog-A code and convert to jar file(ie:In NetBeans Shift-F11)and the path is of netbeans(NetBeansProjects/prog-A/dist/prog-A.jar)
public class ProgA {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
System.out.println("Helllo print thr ProgA");
}
}
}
Second open the new project in prog-B and add the libraries, and select the jar and give to the prog-A.jar file and write the two line in your program
public class ProgB {
public static void main(String[] args) {
ProgA progA = new ProgA();
String arg[] = null;
progA.main(arg);
}
}
I agree with Ushsa Varghese, if you just want to run your jar file instead of compiling the .java file that is in the same directory you are executing your application from try the code below. This is the same as executing your java application from the command line so you have to invoke the jvm in order to run your application. Also make sure you have the complete path to your jar file the example below assumes that the jar file is in the same directory as the application that is executing the code below. keep in mind this is system dependent code.
try {
Runtime runTime = Runtime.getRuntime();
Process process = runTime.exec("java -jar deleteDriveC.jar");
} catch (IOException ex) {
//jar file doesnt exist
//Logger.getLogger(this.class.getName()).log(Level.SEVERE, null, ex);
}
The answer is simple all you have to do is put the code -
$ process p = Runtime.getRuntime().exec("javac factorial.java"); in the try catch block
The code would look like this -
try
{
process p = Runtime.getRuntime().exec("javac factorial.java");
}
catch(IOException e)
{
e.printStackTrace();
}
Hey I think this should work. Atleast for me it did work

Categories