views:

182

answers:

6

What is the best way to have a (Java) program recognize it crashed last time it ran and show a message along the lines of "it looks like this program crashed on you last time. Report this problem here: [email protected] ...."

Is there a recommended way of doing this? (Bad?) ideas I had would be:

  • Have the program store a temporary key file at startup and then delete it when closing regularly. If the file exists at startup, show the message.
  • Recognize deadlocks and store an "error file" in this case. If an "error file" exists at startup, show the error message and move the file into an archive or something similar.
+3  A: 

Crash as in an uncaught exception? The use a Thread.setDefaultUncaughtExceptionHandler, and display the message as part of the crash.

On the first idea, how do you handle multiply instances of the applications running at the same time? (Also think about multi-user environments).

Recognize deadlocks - How often are deadlocks the problem? I guess you could monitor the thread states on all the "key" threads.

You then have external forces killing the application, should they be considered a problem that you should report? After all your application was not at fault in this case.

Finally, always store an "error file" in the form of a log. Use a proper logging framework (i.e. Java Logging or Log4J). You could check the last lines of this for a signal that the application exited normally but again you will need to be careful in multi-instance environments.

mlk
A: 

What I do is redirect System.err to a file, so that any error message (like crashes) end up in a file I can later process...

The code to do this is quite simple...

String errLog = "c:\\myLog";
try 
{
  java.io.PrintStream err = new java.io.PrintStream(new java.io.FileOutputStream(errLog));
  System.setErr(err);
}
catch (java.io.FileNotFoundException fnfe) {}
Marcos Crispino
I would recommend using a proper logging framework over redirecting System.err.
mlk
+6  A: 

There are three reasons why a Java program can crash:

  • Unhandled RuntimeException. This is easy to solve with a try-catch in main.
  • Unhandled Errors. These are rare but can be caught in main also. I usually catch Throwable in main. See below for a template.
  • If you use threads, then look at Thread.setDefaultUncaughtExceptionHandler().
  • Bugs in the VM, or program killed by the user, or hardware violent shutdown. These will lead to a crash which can't be caught. Here, your best option is to create a flag file somewhere with new File(...).deleteOnExit(). Java will clean it up for you if it gets a chance.

The problem with deadlocks is how to detect that you have a deadlock. I haven't seen a consistent way to do that, yet.

import org.apache.commons.lang.exception.ExceptionUtils;

public class Demo
{
    public static void main (String[] args)
    {
        try
        {
            Demo obj = new Demo ();
            obj.run (args);
            System.out.println ("Done.");
        }
        catch (Throwable t)
        {
            ExceptionUtils.printRootCauseStackTrace (t);
        }
    }
}
Aaron Digulla
or program killed by the user, or hardware violent shutdown, etc.
kriss
That only catches issues with the "main" thread. If you start extra threads then if they throw a Runtime Exception or Error the message will be lost.
mlk
@mlk: thanks, I've updated the answer.
Aaron Digulla
A: 

I'm going to mimic Marcos here. Create a configuration or log file that will host the last error message and last run date of the program. Then read that file during program load.

AProgrammer
+2  A: 

A variant of the first solution you propose is common enough on Un*x for processes: store the pid file of a running process in a file at startup. When the program is launched again you can check if this file still exists (and even if the process with this pid is running).

With Java you could probably adapt this idea using Threadid defined in ThreadMXBean. But any file would do. A file that contains a key as you propose seems a good enough way. You could also put some usefull information in it like last execution time. If it's still there at startup the program didn't stopped cleanly.

It could also become something like a launch log file that trace program events including startup and clean stops, and maybe locks.

kriss
A: 

Many of these answers are about tracking exceptions that caused your app to quit working.

Another possibility is that the application just quit (i.e. user killed it, computer shutdown, power outage, etc.). I think your temporary key idea will work for that. It's similar to how text editing programs, such as vi or Word, automatically create a special copy of the file being edited. Upon opening it checks to see if the special copy exists and asks if you want to recover the file.

Thien