I've been working on in a swing application. I've a JFrame having some buttons and fields.
On some button click event,I'm opening an exe from my current directory. Everything works fine.
try {
Runtime.getRuntime().exec(System.getProperty("user.dir") +
"\\Upgrade\\Upgrade.exe");
} catch (IOException ex) {
ex.printStacktrace();
}
this.dispose(); // disposing my current java file.
But what i need is to exit the java code after opening the exe file.
Anyone help to deal this.?
Can you try making it a process, then waiting for that process to finish before exiting, like so:
class SO {
public static void main(String args[]) {
try {
Process proc = Runtime.getRuntime().exec("your command");
proc.waitFor(); //Wait for it to finish
System.exit(0);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Executing an application from java using Runtime.exec() is a source of well known problems. Like waiting for a Process to finish, but not consuming the data from the stream buffers is a sure way for you application to hang.
I would suggest you use a library like Apache Common Exec to handle this.
I worked on a project a while back where we used Runtime.exec() to launch a process that would eventually extract files over existing files. All worked well except on one machine used for staging - it would just hang. It turned out on that staging machine, someone had set the date/time back so it looked liked the new files being extracted where older than the existing one, causing the external process to generate a warning message for each, overflowing the error buffer - which our application was not consuming!
Related
I have created a simple java program to open an excel file and write data to it, once the data is written I then proceed to open the file to view the spreadsheet:
String[] cmdarray=new String[]{"cmd.exe","/c","C:\\Users\\Jason\\Documents\\*******\\********\\******.xls"};
Runtime runTime = Runtime.getRuntime();
Process process = runTime.exec(cmdarray);
as part of the learning curve I then try to close the file 10 secs later with:
process.destroy();
but this isn't closing the window.
Can anyone point out where I am going wrong? Thank you.
private static void OpenExcel() throws IOException {
//Find the File and open it
String[] cmdarray=new String[]{"cmd.exe","/c","C:\\Users\\Jason\\Documents\\*********\\*********\\********.xls"};
Runtime runTime = Runtime.getRuntime();
Process process = runTime.exec(cmdarray);
try{
//Delay
TimeUnit.SECONDS.sleep(10);
}catch (InterruptedException e) {
e.printStackTrace();
//Handle exception
}
//Close Excel
System.out.println("Closing Excel");
process.destroy();
}
}
One of the reason could be well-known JDK bug:
The fundamental problem here is that, unlike Unix, Windows does that
maintain parent-child relationships between processes. A process can
kill its own immediate children, but unless you make other
arrangements to obtain the information, can't kill any
'grand-children' because it has no way of finding them.
You can try with direct execution of Excel, not via cmd:
Runtime.getRuntime().exec("C:\\full\\path\\to\\excel.exe C:\\file.xls");
I've been experiencing a similar problem to (Too many open file handles) when I try to run a program on a Grid Computer. The option of increasing the operating system limit for the total number of open files on this resource is unavailable.
I tried to catch and handle the exception, but catching the exception does not seem to happen. The exception seems to report itself as a FileNotFoundException. One of the places the exception is thrown is in the method shown below:
public static void saveImage(BufferedImage bi, String format, File aFile) {
try {
if (bi != null) {
try {
//System.out.println("ImageIO.write(BufferedImage,String,File)");
System.err.println("Not really an error, just a statement to help with debugging");
ImageIO.write(bi, format, aFile);
} catch (FileNotFoundException e) {
System.err.println("Trying to handle " + e.getLocalizedMessage());
System.err.println("Wait for 2 seconds then trying again to saveImage.");
//e.printStackTrace(System.err);
// This can happen because of too many open files.
// Try waiting for 2 seconds and then repeating...
try {
synchronized (bi) {
bi.wait(2000L);
}
} catch (InterruptedException ex) {
Logger.getLogger(Generic_Visualisation.class.getName()).log(Level.SEVERE, null, ex);
}
saveImage(
bi,
format,
aFile);
} finally {
// There is nothing to go in here as ImageIO deals with the stream.
}
}
} catch (IOException e) {
Generic_Log.logger.log(
Generic_Log.Generic_DefaultLogLevel, //Level.ALL,
e.getMessage());
String methodName = "saveImage(BufferedImage,String,File)";
System.err.println(e.getMessage());
System.err.println("Generic_Visualisation." + methodName);
e.printStackTrace(System.err);
System.exit(Generic_ErrorAndExceptionHandler.IOException);
}
}
Here is a snippet from System.err reported one time when the problem occurs:
Not really an error, just a statement to help with debugging
java.io.FileNotFoundException: /data/scratch/lcg/neiss140/home_cream_292126297/CREAM292126297/genesis/GENESIS_DemographicModel/0_99/0/data/Demographics/0_9999/0_99/39/E02002367/E02002367_Population_Male_End_of_Year_Comparison_2002.PNG (Too many open files)
at java.io.RandomAccessFile.open(Native Method)
at java.io.RandomAccessFile.(RandomAccessFile.java:216)
at javax.imageio.stream.FileImageOutputStream.(FileImageOutputStream.java:53)
at com.sun.imageio.spi.FileImageOutputStreamSpi.createOutputStreamInstance(FileImageOutputStreamSpi.java:37)
at javax.imageio.ImageIO.createImageOutputStream(ImageIO.java:393)
at javax.imageio.ImageIO.write(ImageIO.java:1514)
at uk.ac.leeds.ccg.andyt.generic.visualisation.Generic_Visualisation.saveImage(Generic_Visualisation.java:90)
at uk.ac.leeds.ccg.andyt.generic.visualisation.Generic_Visualisation$ImageSaver.run(Generic_Visualisation.java:210)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:439)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
I have some ideas for working around this issue, but does anyone know what is wrong?
(I tried to post a version of this question as an answer to this question, but this was deleted by a moderator.)
Firstly, the write method will actually throw an IIOException not a FileNotFoundException if it fails to open the output stream; see the source - line 1532. That explains why your recovery code never runs.
Second, your recovery strategy is a bit dubious. You have no guarantee that whatever is using all of those file handles is going to release them in 2 seconds. Indeed, in the worst case, they may never be released.
But the most important thing is that you are focussing on the wrong part of the problem. Rather than trying to come up with a recovery mechanism, you should focus on the problem of why the application has so many file descriptors open. This smells like a resource leak. I recommend that you run FindBugs over your codebase to see if it can identify the leaky code. Everywhere your code opens an external Stream, it should have a matching close() call in a finally block to ensures that the stream is always closed; e.g.
OutputStream os = new FileOutputStream(...)
try {
// do stuff
} finally {
os.close();
}
or
// Java 7 form ...
try (OutputStream os = new FileOutputStream(...)) {
// do stuff
}
The resource I am running this on has only 1024 file handlers and changing that is another issue. The program is a simulation and it writes out a large number of output files at the same time as it reads in another lot of input data. That work is threaded using an ExecutorService. The program runs to completion on another computer that has a higher file hander limit, but I want to get it to work on the resource where I am limited to having less file handlers.
So it seems like you are saying that you need to have that number of files open.
It strikes me that the root problem is in your application's architecture. It sounds like you simply have too many simulation tasks running at the same time. I suggest that you reduce the executor's thread pool size to a few less than the max number of open file descriptors.
The problem is that your current strategy could lead to a form of deadlock ... where existing tasks can't make progress until new tasks start running, but the new tasks can't start until existing tasks release file descriptors.
I'm thinking you need a different approach to handling the input and output. Either buffer the complete input and/or output files in memory (etcetera) or implement some kind of multiplexor so that all active files doesn't need to be open at the same time.
I have an application that I developed/tested under 32bit Win (XP and Win7) and eclipse (indigo). I deploy the application using File->Export->Runnable Jar (with "package required libraries into generated JAR"). From there I wrap it into an executable.
I recently noticed that my application can not be closed (by neither the "top right X" nor alt+F4) in 64bit Win7 (32bit Win works fine). I started playing arround in 64bit Win7 and found out, that when started from eclipse, I can close the application. After I exported it into a runnable jar, I can not close it. Every other part of my application works fine (also under 64bit Win7).
I have a shutdown hook running like this:
// initialize JFrame frame;
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
closeApplication();
}
});
frame.setVisible(true);
public void closeApplication() {
while (ConnectionManager.isConnected())
try {
ThreadManager.addMeasRequestPriority(eMeasRequest.DISCONNECT);
Thread.sleep(100);
} catch (InterruptedException e) {}
ConfigurationManager.saveToXML(new File("ressources/settings/startup.xml"));
System.exit(0);
}
I noticed that the GUI is disconnecting, but nothing more (but this means, that closeApplication() is entered). The problem is that I don't have the System.out when I am not running it in eclipse, so I can not see if there is any exception or what is going on. Do you have an idea how I could find the problem (or already know the problem)?
Possible candidates:
System.exit(0) has a different behaviour under 64bit (why would that be and is there an alternative?)
I can not create/write to the given file startup.xml (how can I check that?)
A tiny dwarf inside my 64bit Win7 laptop short circuits some stuff on the motherboard with his iron hammer and thus prevents the application from closing (how could I remove him?)
other
I would appreciate it if you could either tell me, whats going on here or how you would proceed to find out more.
EDIT: Thanks for your fast replies. I have found out, that I get the following exception:
java.io.FileNotFoundException: ressources\settings\startupPlot0.apph (Access denied)
at java.io.FileOutputStream.open(Native Method)
...
But how can this be? This file definitely exists and is written to in non-64bit Win. Also, there are other files in the same directory that are written to just before the exception occurs on that file. They work (I just checked them). The only difference: For the other files, I use a new OutputStreamWriter(new FileOutputStream(File file)) for the other files and a new DataOutputStream(new FileOutputStream(File file)) for this one.
I can verify that system.exit(0) works on 64 bit systems. If I had to guess, My answer would be that you are not disconnecting and you're throwing your Interupted Exception.
My recomendations: Put a system.out.print statement in your catch statement to see if you are catching.. If you are, you know you're problem, if not, you're not disconnecting and sitting in the while loop.
edit: try
FileOutputStream fos = new FileOutputStream("t.tmp"); // t.tmp is the directory&file name
ObjectOutputStream oos = new ObjectOutputStream(fos);
You can use the following to make sure you always call System.exit(0) irrespective of any exceptions:
public void closeApplication(){
try{
while (ConnectionManager.isConnected()){
try{
ThreadManager.addMeasRequestPriority(eMeasRequest.DISCONNECT);
Thread.sleep(100);
}
catch (InterruptedException e){
}
}
ConfigurationManager.saveToXML(new File("ressources/settings/startup.xml"));
}
finally{
System.exit(0);
}
}
Though, you might also be looping infinitely in your while loop.
I am writing this question which is related to my previous topic:
Run bat file from java code to get desired result in txt file - no can do :(
In a shortcut: i wrote a program in java that runs a bat file. This bat file runs TestComplete8 script that performs desktop application test. After test is finished, bat file generates file called result.txt and prints information about test to it.
I'm stuck with another issue right now: Now from my java code i would like to wait until the bat run is finished. I do that by looping until the file called result.txt exists. Not the nicesest solution i guess but I thought it could work, also tried different solutions. What happens is that it will loop fine and wait until file exists, but testcomplete doesn't perform the test. It is very strange, because testcomplete runs, i can see that test starts, my AUT starts as well, but than nothing happens. Testcomplete is waiting for any object and doesn't click anywhere just waits until predefined time for action runs out. When i run the test without any waiting done in code, everything is fine. I just don't understand why nothing happens during the test when waiting is enabled and why it works fine when i just remove any do - while or waitFor(), or even i tried running it in seperate threads. :(
I have a feeling that it may be somehow related to the OS and have something to do with processes as it runs something like a bat as process and than bat runs it's child process as testcomplete or sth like that.
Thanks for any answers
Source code as asked:
Right now i was trying a solution with modified bat file:
#ECHO OFF
"C:\Program Files (x86)\Automated QA\TestComplete 8\Bin\TestComplete.exe" "C:..." /r /p:projname PathToApp="C:\...p" Login=... Password=B1 /t:"KeywordTests|..." /exit
and the code to run and wait in latest version is:
new Thread(new Runnable() {
public void run() {
File file = new File("D:\\");
int exitValue = -1;
try {
Process process = Runtime.getRuntime().exec(batch, null, file);
while (true) {
try {
exitValue = process.exitValue();
System.out.println(exitValue);
break;
} catch (IllegalThreadStateException e) {
// e.printStackTrace();
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("Waiting for process...");
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
The most likely cause, without knowing more about the problem, is a common one faced when launching external processes from Java. When launching an external process three streams are created between the parent and child process, input, output, error.
You can liken these to System.in, System.out and System.err. If the parent process (Java) does not actively consume the data on the out and error streams the child process may block as the OS will reach a buffer limit on the stream and prevent any more being written until it is consumed. This is quite likely if your script writes to standard out or standard error.
I would recommend using apache commons-exec to handle Java process launching.
Here's a code sample that I know works.
CommandLine commandLine = new CommandLine( "TestComplete8.bat" );
commandLine.addArgument( ... );
commandLine.addArgument( ... );
DefaultExecutor executor = new DefaultExecutor();
executor.setExitValue( 0 );
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ByteArrayOutputStream errorStream = new ByteArrayOutputStream();
executor.setStreamHandler( new PumpStreamHandler( outputStream, errorStream ) );
try
{
executor.execute( commandLine );
}
catch ( ExecuteException e )
{
// TODO: ...
}
catch ( IOException e )
{
// TODO: ...
}
Then you can examine the output/error streams if you wish when execute returns.
In my program, I need to run a external command in a Ubuntu environment (ntpdate) using java. Currently my code looks like this:
Runtime rt = Runtime.getRuntime();
byte[] readBuffer = new byte[131072];
// Exec a process to do the query
Process p = null;
try {
p = rt.exec("ntpdate -q " + ip);
} catch (Exception ex) {
ex.printStackTrace();
}
if(p!= null){
try {
Thread.sleep(1000);
} catch (Exception e) {
}
// Read the input stream, copy it to the file
InputStream in = p.getInputStream();
try {
int count = 0, rc;
while ((rc = in.read(readBuffer, count, readBuffer.length - count)) != -1) {
count += rc;
if (count >= readBuffer.length) {
p.destroy();
break;
}
}
p.destroy();
result = processOutput(readBuffer, count);
} catch (IOException ex) {
ex.printStackTrace();
}
p.destroy();
This code need to be ran simultaneously on multiple threads in order to maximize performance (I need to test a list of 1.000.000 addresses using ntpdate). However, it runs very slowly, barely consuming machine processing. What am I doing wrong? How could I make this more efficient?
The same problem arises when trying to execute "dig" using .exec(), so I doubt it is because of the specific program being called. Is there some restriction in using Runtime.exec() in a multi Threaded environment?
Is Java the most appropriate approach here? Perhaps this would be better in a shell script, which calls ntpdate in the background multiple times? I'm not sure what benefit you're getting from this code snippet by doing this in Java.
What are you doing with the InputStream from the process?
A bash script could do this like:
for ip in #...IP list
do
ntpdate -q $ip > $ip.txt &
done
Why are you waiting for 1 second at each time ?
try {
Thread.sleep(1000);
} catch (Exception e) {
}
This will do nothing but slowing the execution of your application.
Not sure why it's slow but you need to do a lot more to close your resources. Runtime.exec() needs quite a bit of care and attention to avoid hang-ups and leaking of file descriptors.
http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html
Are you sure the issue isn't ntpdate? If ntpdate is just sitting there waiting for a server response and has a large timeout value, then your application is going to sit there too.
Try calling ntpdate with a timeout of 0.2 and see if it makes a difference.
Also, as you're opening streams in your code, you definitely want to explicitly .close() them when you're done. Otherwise it might not happen until a GC which could be a very long time away.
I think I found the solution, and that is that there is no solution using java's Runtime.exec(). The problem seems to be that all calls to start a process are synchronized. Indeed, if you start each process alone (via synchronization) you get the exact same result of starting all processes together.
Are there any alternatives to exec? Otherwise, I will need to get some solution without linux's ntpdate...
I notice that both of the commands you tried involve network round-trips. How is the speed if you call something like echo or cat instead?