Manipulador de exceções globais não capturado em Java

Eu tenho um aplicativo e precisa codificar um manipulador de exceção global não-personalizado. Eu li todos os threads stackoverflow e cada um deles está faltando apenas um exemplo claro e simples de como isso deve ser implementado.

Considere este simples exemplo a seguir:

public static void log(String msg) throws Exception { String logPath = "/application/logs/java.log"; Calendar c = new GregorianCalendar(); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String now = format.format(c.getTime()); PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(logPath, true))); out.println(now + " " + msg); out.close(); } 

Ele lança uma exceção padrão que é apenas uma saída padrão. Como faço para implementar minha própria exceção, que substitui o padrão por algo simples como a saída do erro em um arquivo de log? Obviamente, o aplicativo real é muito maior e estamos falando de exceções não capturadas, e é por isso que os blocos try / catch não são a opção.

ATUALIZAÇÃO: Se você pudesse responder com um exemplo completo muito claro, porque eu encontrei dúzias de exemplos como o que o @RamonBoza forneceu, ainda não tenho idéia de como implementá-los, e é sobre isso que trata essa questão.

UPDATE2: Então eu tentei testar o único exemplo na resposta abaixo, obviamente não funciona. Eu criei um novo arquivo de class “MyRunnable” e colei o código nele:

 package mypackage; Thread t = new Thread(new MyRunnable()); t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { public void uncaughtException(Thread t, Throwable e) { LOGGER.error(t + " throws exception: " + e); } }); t.start(); //outside that class class MyRunnable implements Runnable(){ public void run(){ throw new RuntimeException("hey you!"); } } 

Escusado será dizer que eu recebo um monte de erros com isso. Como algo pode estar fora da aula?

UPDATE3: Esta é a solução que finalmente funciona:

 package mypackage; public class MyClass { public static void main(String[] args) throws Exception { Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { public void uncaughtException(Thread t, Throwable e) { StringWriter sw = new StringWriter(); e.printStackTrace(new PrintWriter(sw)); String stacktrace = sw.toString(); System.out.println(stacktrace); } }); //main method code } //Rest of the methods here } 

Você pode definir UncaughtExceptionHandler para o segmento que controla o código acima:

 // t is the parent code thread t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { public void uncaughtException(Thread t, Throwable e) { LOGGER.error(t + " throws exception: " + e); } }); 

Documentos Java para UncaughtExceptionHandler –

Quando um encadeamento estiver prestes a terminar devido a uma exceção não detectada, a Java Virtual Machine consultará o encadeamento para seu UncaughtExceptionHandler usando Thread.getUncaughtExceptionHandler () e chamará o método uncaughtException do manipulador, transmitindo o encadeamento e a exceção como argumentos

O setUncaughtExceptionHandler é comumente usado para liberar memory ou matar threads que o sistema não será capaz de matar e, talvez, permanecer zumbi.

Um exemplo real:

 Thread t = new Thread(new MyRunnable()); t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { public void uncaughtException(Thread t, Throwable e) { LOGGER.error(t + " throws exception: " + e); } }); t.start(); //outside that class class MyRunnable implements Runnable(){ public void run(){ throw new RuntimeException("hey you!"); } } 

Você pode usar UncaughtExceptionHandler para manipular a exceção que faz com que um thread seja encerrado abruptamente. Documento Java para UncaughtExceptionHandler –

Interface para manipuladores chamados quando um Thread termina abruptamente devido a uma exceção não identificada. Quando um encadeamento estiver prestes a terminar devido a uma exceção não detectada, a Java Virtual Machine consultará o encadeamento para seu UncaughtExceptionHandler usando Thread.getUncaughtExceptionHandler () e chamará o método uncaughtException do manipulador, transmitindo o encadeamento e a exceção como argumentos

Você precisa implementar essa interface e definir sua implementação de UncaughtExceptionHandler para um thread usando o método setUncaughtExceptionHandler. Há duas maneiras de você fazer isto –

  1. setUncaughtExceptionHandler
  2. setDefaultUncaughtExceptionHandler

1) setUncaughtExceptionHandler – Este será um manipulador de exceção específico do thread. Portanto, caso esse segmento seja finalizado por alguma exceção não tratada, esse manipulador será usado.

2) setDefaultUncaughtExceptionHandler – Este será um manipulador de exceção padrão no caso de não haver um manipulador específico de exceção não capturado para um encadeamento.

Exemplo –

 class MyExceptionHandler implements UncaughtExceptionHandler{ @Override public void uncaughtException(Thread arg0, Throwable arg1) { System.out.println("[DEFAULT EXCEPTION HANDLER] Caught some exception"); } } class MyThread extends Thread{ public MyThread() { setUncaughtExceptionHandler(new UncaughtExceptionHandler() { @Override public void uncaughtException(Thread t, Throwable e) { System.out.println("[THREAD SPECIFIC] My exception handler"); } }); } public void run(){ throw new RuntimeException(); } } public class Test { public static void main(String[] args) { Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler()); new MyThread().start(); // current thread does not have a thread specific exception handler throw new RuntimeException(); } } 

Você pode tentar configurar seu próprio manipulador de exceções não detectado , no entanto, aconselho fortemente contra ele. Se o seu aplicativo tiver partes que possam potencialmente quebrar e se essa exceção não for tratada corretamente no local em que o seu código for interrompido, todo o seu programa funcionará incorretamente com freqüência.