Way to create an exception when program forced to exit? - java

I'm trying to make a simple Java wordcounting program.
When it reads Microsoft Office files, it first reads the text of the XML files (Microsoft Office files are actually bundles of zipped xml files!) and then reads them to a folder called "converted".
I want "converted" to be deleted right after the program ends, so I added a
new File("converted").deleteOnExit();
which does that well.
However, if the user of the program presses Ctrl+C in the command prompt, then the program will exit early, and the folder will not be deleted.
I would like to know if there's a way to throw an exception if a program is exited. It seems unlikely, because a forced exit of a program will probably stop any code, but I was wondering if this is possible. Then, I'll be able to handle the exception and exit the program correctly, so that the directory will be deleted. I mean, I can add this:
catch(ExitException e) { // if the exception is called "ExitException"
System.err.format("Program ended unexpectedly.%n");
System.exit(-1); // this line so that the folder can delete
}
(The way I understand it, the folder is only deleted if a System.exit() is called. Correct me if I'm wrong.)
Thanks.

There isn't really a way to have it throw an exception on ^C (Control C), but you can have code run when the program is exited in any way as seen below.
Try using shutdown hooks: Runtime.getRuntime().addShutdownHook() should run even on ^C.
Note that this won't run under very specific cases as defined there (SIGKILL), but it will handle most lower things.
Try this instead (run it once at some point in your program):
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
try {
new File("converted").delete();
} catch (Exception e) {
e.printStackTrace();
}
}
});
And get rid of your new File("converted").deleteOnExit();.

Related

Run a program without Try/Catch block

I'm making a sort of chat program in Java. Specifically, if I ask "can you open chrome?", the program will reply with "yes..." and then opens Google Chrome (Windows).
I have created the path to the Chrome as a string:
Runtime rt = Runtime.getRuntime()
String file="C:\\Program Files (x86)\\Google\\Chrome\\Application\\Chrome.exe";
I try to call the String, but says to either "Surround Statement with try/catch" or "Surround block with try/catch". Or the "Add throws clause to the "java.io.IOException" ".
myVocab.addPhrase("Can you open Chrome?", "Yes, one moment..." + rt.exec(file));
Whenever I do either of these, Chrome just opens automatically.
I'm somewhat new to Java so please tell me if there's an easier way to do this, or if I'm doing this completely wrong.
Some java functions need to be implemented with the try catch statements because it is possible to get an exception inside that function. An exception is defined as "An exception is an event, which occurs during the execution of a program, that disrupts the normal flow of the program's instructions" more info
So, to manage an exception, for your case, you could:
try { code1 } catch (ExceptionType name) { code2 }
where ExceptionType should correspond to the possible error type your code1 could give you.
Ex:
try { //code to open google } catch (InterruptedException e) { e.printStackTrace(); }
e.printStackTrace(); will print error details

Java. Prevent Jar App from multiple running with pop up message "already running". (using ServerSocket())

Currently i am trying to display a pop up message when user trying to run jar more than one time.
My current code is like below
public static void main(String[] args){
new ServerSocket(65535, 1, InetAddress.getLocalHost());// if there are already one
// running jar, it will prevent
// the program to execute
JOptionPane.showMessageDialog(frame, "Hello World \n"); //Display hello world message
// when run
}
expectation output when user run jar more than one time :
Your jar application is already running . . .
My question is, how can we display a message tell user the jar application is already running because ServerSocket() will prevent application from running, so "already running "pop up message i put after that will not run.
ANSWER:
try{
new ServerSocket(65535, 1, InetAddress.getLocalHost());
JOptionPane.showMessageDialog(frame, "Hello World \n");
}
catch(BindException ex){
JOptionPane.showMessageDialog
(frame, "Your jar application is already running . . . \n");
System.exit(0);
}
One commonly used way is to create a File on the disk that says app is running and delete that file on normal termination of jar, check if file exists on startup and display proper message, also consider the case of abnormal termination of jvm
For example eclipse locks current workspace with a .lock file
the best way is that create a file that show status of program and if a program run already, do not let program execute again. but you must be careful; if your program stop unexpected without edit file before terminate it make a lot of problem when you execute your program later
You need to catch BindException, and display your 'already running' popup, and then exit, all in that catch block.
You also need to catch any other IOExceptions that may arise.
You also need to store the ServerSocket into a static variable so that it won't be garbage-collected, which will close it.

Prevent jar from running if it's already running? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
java/shellscript code to find out if a jar file is already running on current machine
I would love to get a cross-platform solution for this, but even if it's unix only- that would be fine.
The simple solution would be to do this from the shell (Pseudocode)(if ps -aux | grep myJar | print {awk 2}.contains myPID, don't run myProgram.
Now unfortunately our linux team doesn't want a script like that running in production since it can (admittedly) have undesired behaviors.
So what I need is to be able to have a file run, and when it runs see if another program is running. If the program is already running and it's below that time limit, it should prevent the program from running.
A bit of an example:
Myprog.jar -- timeout 5 min
Myprog.jar is in a cron that gets called every 4 minutes,
the first time it's called it launches, the second time it's called it's still running, but since it's not over the timeout, it's fine.
If it's still running when the third check comes through (at 8 minutes into execution) it's killed, and its process is replaced by itself afterwards.
If someone can help me understand how to do this (We've been trying to set up a lock file with limited success)
Thanks!
You could make your program open a dummy file for writing with a FileWriter when your program starts, and keep the file open until the program is finished.
When you now start a second instance of your program, it will also try to open this file for writing, which will throw an IOException, because only one process can have a write handle to a file at the same time.
You could use a port as a semaphore. See this question for more info on that. I think a port would be a good cross-platform solution
You can create a temporary file on a fixed location.
private static final File LOCK_FILE = new File("app.lock");
public static boolean checkIfAlreadyRunning()
{
return LOCK_FILE.exists();
}
public static void createLockFile()
{
LOCK_FILE.createNewFile();
Runnable shutDown = new Runnable()
{
public void run()
{
try
{
LOCK_FILE.delete();
} catch (Exception e) { /* Sad but true */ }
}
};
Runtime.getRuntime().addShutdownHook(new Thread(shutDown));
Thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler()
{
public void uncaughtException(Thread t, Exception e)
{
shutDown.run();
System.exit(-1);
}
});
}
I had exactly the same problem, and it can be pretty tricky to solve. Both File and Socket based approaches can be made to work, but it gets really tricky on some OS's (think of Windows with multiple users in multiple terminal server sessions etc.).
First, determine the scope where you want only one instance. Then decide on a solution.
The ServerSocket method with a fixed port number will allow you one instance per machine (maybe not exactly what you want).
The locking file approach can be tailored to create the locking file in the users temp directoy, so it gives one instance per session/user.
I personally use a combined approach where the locking file specifies a random port and a second instance connects to that port to pass command line parameter to the running instance.

JUnit tests fail when creating new Files

We have several JUnit tests that rely on creating new files and reading them. However there are issues with the files not being created properly. But this fault comes and goes.
This is the code:
#Test
public void test_3() throws Exception {
// Deletes files in tmp test dir
File tempDir = new File(TEST_ROOT, "tmp.dir");
if (tempDir.exists()) {
for (File f : tempDir.listFiles()) {
f.delete();
}
} else {
tempDir.mkdir();
}
File file_1 = new File(tempDir, "file1");
FileWriter out_1 = new FileWriter(file_1);
out_1.append("# File 1");
out_1.close();
File file_2 = new File(tempDir, "file2");
FileWriter out_2 = new FileWriter(file_2);
out_2.append("# File 2");
out_2.close();
File file_3 = new File(tempDir, "fileXXX");
FileWriter out_3 = new FileWriter(file_3);
out_3.append("# File 3");
out_3.close();
....
The fail is that the second file object, file_2, never gets created. Sometimes. Then when we try to write to it a FileNotFoundException is thrown
If we run only this testcase, everything works fine.
If we run this testfile with some ~40 testcases, it can both fail and work depending on the current lunar cycle.
If we run the entire testsuite, consisting of some 10*40 testcases, it always fails.
We have tried
adding sleeps (5sec) after new File, nothing
adding while loop until file_2.exists() is true but the loop never stopped
catching SecurityException, IOException and even throwable when we do the New File(..), but caught nothing.
At one point we got all files to be created, but file_2 was created before file_1 and a test that checked creation time failed.
We've also tried adding file_1.createNewFile() and it always returns true.
So what is going on? How can we make tests that depend on actual files and always be sure they exist?
This has been tested in both java 1.5 and 1.6, also in Windows 7 and Linux. The only difference that can be observed is that sometimes a similar testcase before fails, and sometimes file_1 isn't created instead
Update
We tried a new variation:
File file_2 = new File(tempDir, "file2");
while (!file_2.canRead()) {
Thread.sleep(500);
try {
file_2.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
This results in alot of Exceptions of the type:
java.io.IOException: Access is denied
at java.io.WinNTFileSystem.createFileExclusively(Native Method)
at java.io.File.createNewFile(File.java:883)
... but eventually it works, the file is created.
Are there multiple instances of your program running at once?
Check for any extra instances of javaw.exe running. If multiple programs have handles to the same file at once, things can get very wonky very quickly.
Do you have antivirus software or anything else running that could be getting in the way of file creation/deletion, by handle?
Don't hardcode your file names, use random names. It's the only way to abstract yourself from the various external situations that can occur (multiple access to the same file, permissions, file system error, locking problems, etc...).
One thing for sure: using sleep() or retrying is guaranteed to cause weird errors at some point in the future, avoid doing that.
I did some googling and based on this lucene bug and this board question seems to indicate that there could be an issue with file locking and other processes using the file.
Since we are running this on ClearCase it seems plausible that ClearCase does some indexing or something similar when the files are being created. Adding loops that repeat until the file is readable solved the issue, so we are going with that. Very ugly solution though.
Try File#createTempFile, this at least guarantees you that there are no other files by the same name that would still hold a lock.

How to delete files from a USB Stick ? Using File.delete() doesn't work

after creating a file and populating it with that with a thread if the file is in a USB java can't delete it, when I try on disk it deletes the file ok !
Here is the part of the code that create and after an exception when try to delete the file.
if(canExport && fileCreated)
{
//Create the file
this.file.createNewFile();
//Export the data
this.run();
if(possible == false){ // in case writing fails delete the file created.
file.delete();
Export novaTentativa = new Export(plan);
novaTentativa.fileCreator(plan);
}
}
The file is created when the this.file.createNewFile() acts.
When this.run() runs, there is a lot of methods to populate the data and handle exceptions, if one exception is caught it sets the global variable possible to false so I know the file is created but empty in the USB, after that I try to delete it with file.delete();
You mention that you're trying to delete the file "after an exception" - consequently, your approach is on the wrong track and isn't going to work as-is.
If an exception is thrown by earlier methods (e.g. the createNewFile() call), then that exception will immediately propagate upwards, so your file.delete() call won't get a chance to execute. You'd need to wrap the earlier statements in a try block, and put the delete call in the corresponding catch or finally block in order for it to execute when an exception was thrown.
Here's an example of what you might try to do:
if(canExport && fileCreated)
{
//Create the file
this.file.createNewFile();
try
{
this.run();
}
catch (IOException e)
{
try
{
file.delete();
}
catch (IOException ignore) {} // don't want to mask the real exception
// Rethrow the actual exception from run() so callers can handle it
throw e;
}
}
An alternative approach rather than catching IOExceptions would be to have a finally block (which is always run) and then check a condition there, such as your possible flag.
Note as well that I start the try block after the call to createNewFile() - if an exception is thrown in the create file call then the file won't exist to delete at all!
As a file note, adding "a lot of code that asks for the thread to start over" in your error-handling block is probably not the best design. It would be more appropriate to simply consider recovering from IO situations here, and let the exception bubble up to the top and cause the thread/runnable to die. The logic around restarting tasks and/or resurrecting threads would be better positioned with the class that started the threads in the first place (e.g. a thread pool/task executor/etc.). Scattering the logic throughout the code will make it harder to see what any individual class is doing (not to mention that having a class marshall resources to resurrect itself just seems wrong from an OO standpoint).
Try explicitly stating the drive letter, path and folder to access the USB device to create write and read or delete the file. If that does not work then it is possible only a specific operating system utility or proprietory utility can delete the file.
How certain are you that you closed the file when the write failed? I'll bet money that you are missing a finally block somewhere in this.run(). That would result in exactly the behavior you describe - delete() will fail if the file is open (you should check it's return code - File.delete() doesn't throw exceptions if it is unable to delete the file).
If you want to test this, replace this.run() with a super, crazy simple implementation that writes 100 bytes to the file, sets 'possible' to false, then returns. If the file still won't delete, post the code you are using for this simplified version of run() and maybe someone can spot what's going on.

Categories