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.
Related
I have develop a simple java program to run APDU commands. It is working fine.
The file structure is
/moc
/omnikey
--Applet.java
--API.java
/omnikey.api
/omnikey.util
... another 3 more packages ...
Now, I want to extract all those extra packages to a new project and leave only the omnikey package (with Applet.java and API.java) to create a .jar with the needed functionality.
So I created a new project, copied all files, fixed the packages references and linked the external jars needed... and now it doesn't work...
The "new" file structure is like this
/apdu
/apduservice
/api
... files ...
/util
... files ...
/moc
/omnikey
Applet.java
API.java
For some reason, the execution hangs when I declare something from the apdu project. If I do
System.out.println("flag 1");
try {
apduservice.api.MocService ser = new apduservice.api.MocService(null);
} catch (CardServiceException e) {
e.printStackTrace();
}
System.out.println("flag 2");
I get no error trace and the output is flag 1. The execution doesn't stop until force it.
If I try the same thing with the previous configuration everything works.
System.out.println("flag 1");
try {
omnikey.api.MocService ser = new apduservice.api.MocService(null);
} catch (CardServiceException e) {
e.printStackTrace();
}
System.out.println("flag 2");
//output flag 1 and flag 2
I'm not sure where the error might be. I tried exporting the second project as jar, as runnable jar, reference it as a project inside Eclipse, and nothing, the same result. I've tried searching for a solution, but since I get no error, it's hard to know what to look for.
If someone could shed a light I'll be grateful.
PD: doesn't seem to be an Eclipse problem, I've referenced projects in other projects and it has work fine...
PD2: I'm not using Maven or anything like that to handle references. I rather not to, at least for now.
Decided to answer this since there's no logical reason for this to happen.
Solution:
change workspaces, open the two projects and link them. Eclipse was just having one of its days.
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!
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.
This question already has an answer here:
Java7 WatchService - Access Denied error trying to delete recursively watched nested directories (Windows only)
(1 answer)
Closed 7 years ago.
I'm using the new feature of Java7 for watching directories for changes (as it is described in the following tutorial: http://download.oracle.com/javase/tutorial/essential/io/notification.html )
The watching itself works (nearly) without problems.
More or less I have two issues and I hope some of you have an idea how to handle it.
After a folder is added to watch, the VM has access to it and it doesn't release it. This should not be such a big issue. But if you're creating a directory in another directory and in this one more. (e.g. you create in directory c:\tmp\a the directory b and in b the directory c (c:\tmp\a\b\c)) it is not possible to delete the directory a, because of the access of the VM to b and c. If you want to delete all of the folders (e.g., with your Windows Explorer) you have to delete c first, then b and then a. It's strange, but this way works (though is inconvenient)
This issue seems to be a result of the first one.
If many changes in a occur sometimes (more or less) I get an exception which tells me, the newly created folder is used by another process and it is not possible to access it. It's strange, because I think this should not matter to get a notification. And because it is not completely clear when exactly this exception is thrown.
Do you have an idea how to make it possible to not have the lock or at least to let the user the ability to delete such a directory structure in the classical convenient way?
Well I've tried the code showcased in the link you posted, doing the same things you're trying to do:
In my c:\temp directory I create programatically a c:\temp\a dir and then a c:\temp\a\b directory:
File startDir = new File("c:\temp");
if(!startDir.exists()) {
startDir.mkdir();
}
File aDir = new File("c:\\temp\\a");
File bDir = new File("c:\\temp\\a\\b");
if(!aDir.exists()) {
aDir.mkdir();
}
if(!bDir.exists()) {
bDir.mkdir();
}
Then I add watchers to the "a" and "b" directories:
public static void watch(final File dir,final WatchService watcher) {
Path path = dir.toPath();
try {
final WatchKey bDirWatchKey = path.register(watcher, StandardWatchEventKinds.ENTRY_MODIFY);
new Thread(new Runnable() {
public void run() {
System.out.println("Watching: "+dir.getName());
while(true) {
try {Thread.sleep(1000);} catch (InterruptedException e) {}
List<WatchEvent<?>> events = bDirWatchKey.pollEvents();
for(WatchEvent<?> event:events) {
System.out.println(dir.getName()+" event: #"+event.count()+","+event.kind()+" File="+event.context());
}
}
}
}).start();
} catch (IOException x) {
x.printStackTrace();
}
}
This works ok, if I modify files in "a" or "b" I get the corresponding console output.
It's true that with Windows Explorer (on a Windowx XP machine) I cannot delete a watched directory (it tells me I don't have access rights). I can however delete it with other tools such as Total Commander. I can even delete then from the Windows command line with rd c:\temp\a\b. I think this is more of an issue with Windows Explorer than with Java...
with regard to your 2nd problem, if you are getting the exception " the newly created folder is used by another process and it is not possible to access it". You can try using Atomic Operations in your code. this will help the operations to be not interrupted and MAY solve your problem.
Why do I get this error when I run this program? This occurs after random iterations. Usually after the 8000th iteration.
public static void main(String[] args)
{
FileWriter writer = null;
try
{
for(int i = 0; i < 10000; i++)
{
File file = new File("C:\\Users\\varun.achar\\Desktop\\TODO.txt");
if(file.exists())
{
System.out.println("File exists");
}
writer = new FileWriter(file, true);
writer.write(i);
System.out.println(i);
writer.close();
if(!file.delete())
{
System.out.println("unable to delete");
}
//Thread.sleep(10);
//writer = null;
//System.gc();
}
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
if(writer != null)
{
try
{
writer.close();
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
}
After the exception occurs, the file isn't present. That means the it is deleting, but FIleWriter tries to acquire the lock before that, even though it isn't a multi threaded program. Is it because the Windows isn't deleting the file fast enough, and hence the FileWriter doesn't get a lock? If so, then file.delete() method returns before windows actually deletes it?
How do i resolve it, since i'm getting a similar issue during load testing my application.
EDIT 1: Stacktrace:
java.io.FileNotFoundException: C:\Users\varun.achar\Desktop\TODO.txt (Access is denied)
at java.io.FileOutputStream.openAppend(Native Method)
at java.io.FileOutputStream.<init>(FileOutputStream.java:192)
at java.io.FileOutputStream.<init>(FileOutputStream.java:116)
at java.io.FileWriter.<init>(FileWriter.java:61)
EDIT 2 : Added file.exists() and file.delete conditions in the program. and the new stacktrace:
7452
java.io.FileNotFoundException: C:\Users\varun.achar\Desktop\TODO.txt (Access is denied)
at java.io.FileOutputStream.openAppend(Native Method)
at java.io.FileOutputStream.<init>(FileOutputStream.java:192)
at java.io.FileWriter.<init>(FileWriter.java:90)
at com.TestClass.main(TestClass.java:25)
EDIT 3 Thread dump
TestClass [Java Application]
com.TestClass at localhost:57843
Thread [main] (Suspended (exception FileNotFoundException))
FileOutputStream.<init>(File, boolean) line: 192
FileWriter.<init>(File, boolean) line: 90
TestClass.main(String[]) line: 24
C:\Users\varun.achar\Documents\Softwares\Java JDK\JDK 6.26\jdk\jre\bin\javaw.exe (09-Nov-2011 11:57:34 PM)
EDIT 4 : Program runs successfully on different machine with same OS. Now how do i ensure that the app with run successfully in the machine it is deployed in?
On any OS you can have only a certain number of open files/threads at a stretch. You seem to be hitting your OS limit. Try setting file to null inside the loop.
If I understand your stack trace correctly, the exception is coming when trying to create a new FileWriter. It's impossible to know the reason without investigating a bit further.
Return values may tell something. Especially, check what File.delete() returns.
Before trying to create new FileWriter, check what File.exists() returns.
If the previous delete() returns true and the exists() right after it also returns true, in a single-threaded program, then it's indeed something weird.
Edit: so it seems that deletion was successful and the file didn't exist after that. That how it's supposed to work, of course, so it's weird why FileWriter throws the exception. One more thought, try checking File.getParentFile().canWrite(). That is, do your permissions to write to the directory somehow disappear.
Edit 2:
Don't get the error on a different machine with the same OS. Now how do i make sure that this error won't come in the app where it'll be deployed?
So far you have one machine that works incorrectly and one that works correctly. Maybe you could try it on even more machines. It's possible that the first machine is somehow broken and that causes errors. It's amazing how often digital computers and their programs (I mean the OS and Java, not necessarily your program) can be just a "little bit broken" so that they work almost perfectly almost all of the time, but fail randomly with some specific hardware & use case - usually under heavy load - similar to how incorrect multi-threaded programs can behave. It doesn't have to be your fault to be your problem :-)
Frankly, the only way to make sure that errors won't come up in machine X is to run the program on machine X. Unusual stuff such as creating and deleting the same file 8000 times in rapid succession is prone to errors, even though it "should" work. Computers, operating systems and APIs are not perfect. The more unusual stuff you do, the more often the imperfections will realize themselves, because unusual usage is generally less thoroughly tested than everyday operations.
I have had the same issue, a java program (single threaded) that opens, deleted then re-opens the same file continuously.
On some windows systems we get the same issue as reported here, on Linux, Solaris, and various other windows systems it works fine.
Traceing the program with SysInternals Process Monitor (now MS) its clear the delete is done first, at the OS level, and clear the subsequent open fails with PENDING DELETE status.
So there seems to be some slight delay at the OS/NTFS/Disk level before the file is actually deleted, and that seems to be the cause of the random failure in our case.
As a workaround, I changed the .delete() call to instead just write over the top of it new FileWriter(file) and that seems to be working.
The problem did not occur on all systems, one specific model that would always fail, all be it after not fixed number of loops, was a Windows 7 / Dell Lattitude E6420 with WD Smartdrive, whereas my Windows 7 / Dell precision M4600 (with solid state drive) or T3400 with Linux I have never had the issue.
Cheers - Mark
It may be a long shot, but, can you try to work with a file that is NOT directly sitting on the Desktop. Instead of:
"C:\\Users\\varun.achar\\Desktop\\TODO.txt"
Try:
"C:\\Users\\varun.achar\\SomeOtherDirectory\\TODO.txt"
OS may be killing you here with all the Desktop hooks...
EDIT based on the comments:
Are there any scheduled jobs running on the "bad" machine?
Instead of debugging the environment, do you have a sys admin to do that?
Does this work on a clean Windows install? [95% chance it will]
Since the root cause seems to be environment, instead of solving a Windows configuration problem, would you be able to move forward with other tasks, and leave it to someone who keeps the list of discrepancies between the systems?
Can you conditionally try to write to the file ?
Using file.exists and then writing to it, so you can potentially avoid any other issues. Hard to say from this exception.
http://download.oracle.com/javase/6/docs/api/java/io/File.html#exists()
Could you also post a thread dump at that point, just to debug it further.
Please flush the writer, before writing again.
These are the scenerios you should handle before deleting a file http://www.java2s.com/Code/Java/File-Input-Output/DeletefileusingJavaIOAPI.htm
at least check for return value in your program.
Thanks folks for help me out but this is how it got resolved finally.
public static void main(String[] args)
{
FileWriter writer = null;
try
{
for(int i = 0; i < 10000; i++)
{
File file = new File("C:\\tenant-system-data\\abc.txt");
if(!file.getParentFile().canWrite())
{
System.out.println("parent file error");
}
if(file.exists())
{
System.out.println("File exists");
}
int count = 0;
while(count++ < 5)
{
try
{
file.createNewFile();
break;
}
catch(IOException e)
{
try
{
Thread.sleep(100);
}
catch(InterruptedException e1)
{
e1.printStackTrace();
}
}
}
writer = new FileWriter(file, true);
writer.write(i);
System.out.println(i);
writer.close();
if(!file.delete())
{
System.out.println("unable to delete");
}
//Thread.sleep(10);
//writer = null;
//System.gc();
}
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
if(writer != null)
{
try
{
writer.close();
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
}
I just had the same problem (FileWriter & Access Denied).
My guess for the reason: Windows 7 had put a lock on the file because a preview of the file content was shown in an Explorer window (the file was selected in the window).
Solution: I de-selected the file in the Explorer window. And the IOException was gone.
You have delete permission in the directory but not create permission.