I have used a method waitFor of Process class, to execute some UNIX command. The command is executing successfully but it is returning 2, that according to convention means abnormal termination.
I googled and found that it depends on "source code of the program that is outputting this exit code". So I tried to find the source code for waitFor method, I came to know that it is a native method and defined in ProcessImpl class.
public native int waitFor();
So I searched for native implementation of this method from here. But I did not found the file that provide me the native implementation of waitFor method.
My question is how to find the file in which native implementation of this method is written?
The source code mentioned refers to the source of the program you are executing with your Process object.
In your case, it is the UNIX command you are executing using the Process that is terminating with exit code 2, not the waitFor() method itself.
So to answer your actual question, the answer is: Within the source code of the JDK you are using, for example here is the source for OpenJDK6.
However, if your actual question is "Why is waitFor() returning a non zero exit code", then the answer is: The Process you are executing with Java has returned a non zero exit code, and the Process object is informing you via the return of the waitFor() method
Related
How do I make java quit the program when it is triggered? I have tried pretty much everything I can do, but I just can't make it quit.
You can use System.exit(0); where 0 is the exit code. This works on all platforms (including android).
Here is a link to the official documentation if you require further reading:
Oracle Documentation
public static void exit(int status)
Terminates the currently running Java Virtual Machine. The argument serves as a status code; by convention, a nonzero status code indicates abnormal termination. This method calls the exit method in class Runtime. This method never returns normally.
The call System.exit(n) is effectively equivalent to the call: Runtime.getRuntime().exit(n)
I'm getting IllegalMonitorStateException when I'm trying to create an instance of an object. The code looks like the following:
public int signIn(parameters...)
{
...check some stuff...
new Thread(... just a simple log here...).start();//IllegalMonitorStateException
return result;
}
MORE INFO:
The actual application consists of 2 programs (C++ and java) interacting via JNI). The scenario in which I'm getting exception is as follows.
The c++ program asks java to connect to a server. (this is a non blocking operation)
Java program informs c++ about connection success. (in a new thread so that java can continue doing other tasks)
When receiving connection success, c++ program asks java to login
Exception occurs.
I should note that this exception only happens in this special scenario and if I call login sometime after connection success everything works fine.
What I've tried:
In the beginning informing connection success was not in a new thread, but creating the thread did not solve the problem.
The java login code had some synchronization stuff but removing them and replacing it with a simple log still produces the problem.
EDIT:
Here's the stacktrace:
Phoenix.client.ClientAPI.NativeInterface.NativeAPIEventListener.onConnectingFinished(Native
Method)
Phoenix.client.ClientAPI.NativeInterface.NativeAPIEventListener.access$000(NativeAPIEventListener.java:12)
Phoenix.client.ClientAPI.NativeInterface.NativeAPIEventListener$1.run(NativeAPIEventListener.java:30)
java.lang.Thread.run(Unknown Source)
I created a new thread in C++ code when java code called back into it This broke the jthread:java -> c++ -> java chain into jthread:java -> c++ and cthread:c++ -> java. This solved the problem I was facing. However I ran into a different problem which lead me into reading a bit of JNI documentation. Quoting JNI doc:
The JNI interface pointer (JNIEnv) is valid only in the current
thread. Should another thread need to access the Java VM, it must
first call AttachCurrentThread() to attach itself to the VM and obtain
a JNI interface pointer. Once attached to the VM, a native thread
works just like an ordinary Java thread running inside a native
method. The native thread remains attached to the VM until it calls
DetachCurrentThread() to detach itself.
So I guess I should've called AttachCurrentThread before calling back into java. However this does not exactly fit in the above description since the thread was not a native thread (it was a thread originally created in java code, could I call DetachCurrentThread afterwards?). I did not test this solution since I had to create a new thread other reasons too. But if I get a chance to try this out I'll confirm.
I've created a class which processes files and if it encounters certain specific errors, it outputs relevant error messages to the error stream.
I am working on another class that needs to access these error messages. I'm not sure how to do this. I am a beginner in Java programming. Based on my limited knowledge, I thought that my two options would be to either call the main method of the first class (but I don't know how I would get the error messages in this case) or to execute the compiled class and access the messages through the getErrorStream() method of the Process class. But, I am having trouble with the system deadlocking or possibly not even executing the exec command, so I'm not sure how implement the second case either.
I'm not quite sure what you're asking here, but a potential problem with your code is that you're not reading from the process' stdout. Per the Process API, "failure to promptly ... read the output stream of the subprocess may cause the subprocess to block, and even deadlock." Is this the "trouble" you mentioned?
Edit: So yeah, you can either do what you're doing, but be sure to read both the error stream and the output stream (see my comment), or you could just call the main method directly from your code, in which case the error output will be written to System.err. You could use System.setErr() to install your own stream that would let you get what's written to it, but keep in mind that any error output from your own app--the one that's running the other app--will also show up here. It sounds like spawning a separate process, like you're already doing, is what you want.
You can't build modularity based on many little programs with a main method. You have to make blocks of function as classes that are designed to be called from elsewhere -- and that means returning status information in some programmatic fashion, not just blatting it onto System.err. If it really is an error, throw an exception. If you have to return status, design a data structure to hold the status and return it. But don't go launching new processes all over the place and reading their error streams.
I am calling a .exe file from my java code using :
Runtime r=Runtime.getRuntime();
Process p=null;
p=r.exec("ABCD.exe");
I want the program to wait till the exe completes its job .(This is actually server side code...control passes to Client side after this).The problem now is that UI on client side is populated before the .exe on server side can form the required components.Hence UI formed does not have the correct files.
I have tried the normal p.waitfor() thing but it doesn't seem to work.
Any suggestions?
The short answer is that you want to call Process.waitFor() in your main thread, as you allude to.
However, dealing with Processes is not exactly fire-and-forget, because, as referenced by the class javadocs, you likely need to be reading the process' output. If you don't do this (which in this case will require a separate thread) then in many instances you'll have an effective deadlock - your Java app is waiting for the process to finish, but the process is trying to write output to a full buffer and thus waiting for the Java app to read its output.
If you gave more information about how "it didn't work", that would help with the diagnosis too.
Edit: on a completely separate point, there's no purpose in initialising p to null and then immediately reassigning it. Your second line would be clearer and less confusing as Process p = r.exec("ABCD.exe");.
My Java program uses ProcessBuilder (with redirectErrorStream set true) and has a loop that runs the processes's inputstream's read method, which is blocking. The external program I'm calling then comes to a stop waiting for input and stdin. I now want to kill the process. Is this not done by (in a seperate thread) calling the process's destroy method, and calling the inputstream's close method to stop the read method from blocking anymore, so that my initial thread can end its life?
For some reason process.getInputStream().close() blocks. From the JavaDoc I don't see why this can happen. Furthermore, I don't understand why the javadoc says "The close method of InputStream does nothing." (link to javadoc) Could someone explain this?
Thanks :-)
Regarding the blocking behavior, there is a known issue in Java that can cause deadlock when communicating with another process. I can't tell if this is what you're seeing but it's worth looking into. The document for java.lang.Process says:
Because some native platforms only
provide limited buffer size for
standard input and output streams,
failure to promptly write the input
stream or read the output stream of
the subprocess may cause the
subprocess to block, and even
deadlock.
For some reason
process.getInputStream().close()
blocks. From the JavaDoc I don't see
why this can happen. Furthermore, I
don't understand why the javadoc says
"The close method of InputStream does
nothing." (link to javadoc) Could
someone explain this?
If you look at the Javadoc, you'll see that InputStream an abstract class. Subclasses that extend InputStream are expected to override the close() method (should it be needed). Clearly the InputStream subclass that you're using does something in the close method.
Adding onto what jdigital wrote, check this article. It deals with Runtime.exec() method, and ProcessBuilder was introduced in Java 5, but it seems to me the discussion can be extrapolated to system processes in general.
I think I figured this out. Obviously it is important to call process.getOutputStream().close() before process.getInputStream().close() and process.getErrorStream().close().