Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Обработка ошибок, listener на стек ошибок 
V
    Опции темы
Connie
Дата 20.6.2009, 15:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 382
Регистрация: 12.8.2008

Репутация: 1
Всего: 9



Я бы хотел в программе при возникновении Exception вызывать диалог, в котором предлагать пользователю, отправить мне ошибки, которые программа сыпет в консоль.

А как можно узнать, что появилось какое то исключение? Речь не идет только о блоках try{}catch{} хотя можно и достаточно ловить ошибки только в них, тогда можно сообщать о ошибки какому то листеру в блоке catch

А как быть если вдруг возникнет исключение с делением на ноль? Такое ведь не обрабатывается? блоками try{}catch{}

Это сообщение отредактировал(а) Connie - 2.7.2009, 13:09
PM MAIL WWW   Вверх
powerOn
Дата 20.6.2009, 19:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


software saboteur
****


Профиль
Группа: Участник
Сообщений: 4367
Регистрация: 7.10.2005

Репутация: 47
Всего: 159



Цитата(Connie @  20.6.2009,  16:40 Найти цитируемый пост)
А как можно узнать, что появилось какое то исключение? Речь не идет только о блоках try{}catch{} хотя можно и достаточно ловить ошибки только в них,


Вот и ловите в try-catch. smile

Цитата(Connie @  20.6.2009,  16:40 Найти цитируемый пост)
А как быть если вдруг возникнет исключение с делением на ноль? Такое ведь не обрабатывается? блоками try{}catch{} 


catch (Throwable th) {} ловит все Java исключения.



--------------------
user posted image нет времени думать - нужно писать КОД!

PM MAIL   Вверх
Connie
Дата 20.6.2009, 20:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 382
Регистрация: 12.8.2008

Репутация: 1
Всего: 9



powerOn, 
Цитата
Вот и ловите в try-catch.
это понятно, так и буду делать
Цитата
catch (Throwable th) {} ловит все Java исключения.
Хм... а вот вопрос, где это прописать? smile
То есть программа, которая после запуска слушает различные action event и выполняет по ним соответствующие действия, тут все просто, но где то в этих действиях могут возникнуть исключительные ситуации, то есть мне где тот тут и нужно ловить?

P.S. моя программа крайне нетребовательна, но один из пользователей довел свой диск до состояния, когда на нем осталось 4 кбт свободного места и тут и сказалась "тихая" обработка ошибок smile т.е. действие делается,  а результата нет. Я попробовал в каждом try{}catch{} выводить мессагу, но это неверный путь, вот и озадачился как можно поймать все исключительные ситуации. 

Хех, лирика какая то...
PM MAIL WWW   Вверх
COVD
Дата 20.6.2009, 21:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 26.7.2005

Репутация: 17
Всего: 43



Цитата

А как можно узнать, что появилось какое то исключение?


Можно перенаправить в приложении System.err - пусть пишет не в консоль, а в вами созданный обьект PrintStream. И запустить отдельный thread , который будет читать строки сообщений из вашего PrintStream. Все неперехваченные исключения там и всплывут в виде последовательности строк, которые генерируются методом printStackTrace() . И перехваченные исключения там будут, если в блоке catch вызывается printStackTrace(). Любой вывод типа System.err.println(..) перенаправится .

http://blogs.sun.com/nickstephen/entry/jav..._system_out_and

Это сообщение отредактировал(а) COVD - 20.6.2009, 23:09
PM MAIL   Вверх
Evgeni68
Дата 20.6.2009, 23:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 37
Регистрация: 9.7.2007

Репутация: 2
Всего: 3



По-моему UncaughtExceptionHandler - то что Вам нужно. Пример.
PM MAIL   Вверх
Connie
Дата 21.6.2009, 08:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 382
Регистрация: 12.8.2008

Репутация: 1
Всего: 9



Цитата
По-моему UncaughtExceptionHandler - то что Вам нужно.
спасибо, классная штука, но только на исключения, которые я ловлю в блоках try{}catch{} она не реагирует, но она и предназначена ловить неожиданные ошибки, может буду использовать этот метод как часть того, что я задумал smile 

Цитата
Можно перенаправить в приложении System.err - пусть пишет не в консоль, а в вами созданный обьект PrintStream. И запустить отдельный thread ,
а вот это ближе к тому, что мне надо, спасибо, буду допиливать под себя smile
PM MAIL WWW   Вверх
Connie
Дата 25.6.2009, 21:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 382
Регистрация: 12.8.2008

Репутация: 1
Всего: 9



Сделал так, покритикуйте smile
Код

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.util.logging.*;
import java.io.*;
import java.util.*;

public class Main extends JFrame {
    public static void main(String[] args) {
        // initialize logging to go to rolling log file
  
        // preserve old stdout/stderr streams in case they might be useful
        PrintStream stderr = System.err;

        // now rebind stdout/stderr to logger
        LoggingOutputStream los;

        //Передаем старый вывод ошибок
        los = new LoggingOutputStream(stderr);
        System.setErr(new PrintStream(los, true));
  
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new Main().setVisible(true);
            }
        });
    }

    // throws an exception on the event dispatch thread
    private Action edtAction = new AbstractAction("EDT Exception") {
        public void actionPerformed(ActionEvent e) {
            throw new RuntimeException("Exception generated on the EDT");
        }
    };

    // throws an exception on another thread
    private Action threadAction = new AbstractAction("Thread Exception") {
        public void actionPerformed(ActionEvent e) {

            new Thread("Sample Thread") {
                @Override
                public void run() {
                    throw new RuntimeException("Exception thrown on a thread");
                }
            }.start();

        }
    };

    public Main() {
        super("Uncaught Exception Handler Demo");
        
        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        buttonPanel.add(new JButton(edtAction));
        buttonPanel.add(new JButton(threadAction));
        getContentPane().add(buttonPanel, BorderLayout.SOUTH);

        pack();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
    }
}


Код

import java.io.*;
/**
 * An OutputStream that writes contents to a Logger upon each call to flush()
 */
class LoggingOutputStream extends ByteArrayOutputStream {

    private String lineSeparator;
    private PrintStream olderrstr;
    private ErrorHappend err = null;
    /**
     * Constructor
     * @param logger Logger to write to
     * @param level Level at which to write the log message
     */
    public LoggingOutputStream(/*Logger logger, Level level,*/PrintStream old) {
        super();
        lineSeparator = System.getProperty("line.separator");
        olderrstr = old;

                //Создаем в отдельном потоке окно с выводом ошибок
                //и в дальнейшем возможностью их обработки, например
                //отправки отчета по мылу
                err = new ErrorHappend();
                err.start();
    }

    /**
     * upon flush() write the existing contents of the OutputStream
     * to the logger as a log record.
     * @throws java.io.IOException in case of error
     */
    @Override
    public void flush() throws IOException {
        //String record;
        synchronized(this) {
            super.flush();
            final String record = this.toString();
            
            super.reset();

            if (record.length() == 0 || record.equals(lineSeparator)) {
                // avoid empty records
                return;
            }
            //выводим сообщение об ошибке как и было до вмешательства
            olderrstr.println(record);
            //Добавляем строку exception'а
            err.addLine(record+lineSeparator);
        }
    }
}


ну и собственно окно отработки ошибок
Код

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;


public class ErrorHappend extends Thread implements Runnable{
    JFrame error;
    JTextArea text;

    public ErrorHappend(){
    }

    public void addLine(String line){
        error.setVisible(true);
        text.append(line);
    }
    @Override
    public void run(){
        error = new JFrame();
        error.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        error.setLayout(new BorderLayout());
        text = new JTextArea();
        text.setEditable(false);
        
        error.add(new JScrollPane(text),BorderLayout.CENTER);
        JButton btnEmail = new JButton("Email (dummy)");
        JButton btn = new JButton("Close");
        btn.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent ev){
                error.setVisible(false);
                error.dispose();
            }
        });
        error.add(btn,BorderLayout.SOUTH);
        error.add(btnEmail,BorderLayout.NORTH);
        
        error.setSize(new Dimension(300,200));
        error.setLocationRelativeTo(null);
        error.setAlwaysOnTop(true);
    }
}

PM MAIL WWW   Вверх
ShellRaiser
Дата 2.7.2009, 10:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


еще чуть и закоммичу
*


Профиль
Группа: Участник
Сообщений: 156
Регистрация: 20.7.2007
Где: Белaрусь, Гродно

Репутация: нет
Всего: 1



вопрос, а ты на любой эксепшн хочешь повесить отправку? создай один класс занимающия ся этим к примеру ErrorReporter.send(Exception e)
или сохраняй всё в лог файл, при сбоях приложения предложи пользователю прислать тебе лог...=\ так ты сможешь просмотреть в логах не только изза чего именно этот эксепшн, а и други факторы на это повлиявшие

вот только ещё есть смешной и глупый вопрос, что ты будешь делать если эксепшн будет валиться при отправке...=) если криво настроен javamail будет?smile
PM MAIL ICQ Skype   Вверх
Connie
Дата 2.7.2009, 13:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 382
Регистрация: 12.8.2008

Репутация: 1
Всего: 9



ShellRaiser, я переделал совсем все что выше понаписал, теперь это выглядит так
Цитата
вопрос, а ты на любой эксепшн хочешь повесить отправку?
да
Цитата
или сохраняй всё в лог файл
а как быть, если на диске нет свободного места? )))))
Цитата
вот только ещё есть смешной и глупый вопрос, что ты будешь делать если эксепшн будет валиться при отправке.
выводить сообщение, что бы в этом случае пользователь руками скопировал вывод стека в письмо и прислал по указанному адресу smile
запускаем всю эту бодягу
Код

import javax.swing.*;
import java.io.*;

public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        PrintStream stderr = System.err;
        LoggingOutputStream los;
        los = new LoggingOutputStream(stderr);
        System.setErr(new PrintStream(los, true));

        SwingUtilities.invokeLater(new Runnable(){
            public void run(){
                new Parent();
            }
        });
    }

}


Вот родитель, генерирующий всякие исключения
Код

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

public class Parent extends JFrame{
    Child ch = null;
    public Parent(){
        Stack.setAlive(true);
        setLayout(new BorderLayout());
        Box box = new Box(BoxLayout.PAGE_AXIS);
        box.add(new JButton(new AbstractAction("EDT Exception") {
        public void actionPerformed(ActionEvent e) {
            throw new RuntimeException("Exception generated on the EDT");
            }
        }));
        box.add(new JButton(new AbstractAction("Thread Exception") {
        public void actionPerformed(ActionEvent e) {
            new Thread("Sample Thread") {
                @Override
                public void run() {
                    throw new RuntimeException("Exception thrown on a thread");
                }
            }.start();
        }
        }));
        
        add(box,BorderLayout.CENTER);
        
        JButton btn2 = new JButton("info");
        btn2.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent ev){
                //А тут просто допишем в стек чего попало
                synchronized (Stack.getInstance()) {
                  Stack.getInstance().getStackTrace().add("пример4\n");
                  Stack.getInstance().getStackTrace().add("пример5\n");
                }
            }
        });
        
        add(btn2,BorderLayout.SOUTH);
        
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        pack();
        setVisible(true);
        this.addWindowListener(new WindowAdapter(){
            @Override
            public void windowClosed(WindowEvent ev){
                Stack.setAlive(false);
                if (ch!=null && !ch.isVisible()){
                    //Форма вывода невидна, закрываем ее
                    ch.stopThread();
                    ch.dispose();
                    System.exit(0);
                }else if (ch!=null){
                    ch.stopThread();
                }
            }
        });
        SwingUtilities.invokeLater(new Runnable(){
                        public void run(){
                           ch = new Child("SendMail V0.0");
                        } 
        });
    }
}


Обработка ошибок, если они появляются
Код

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.net.*;


public class Child extends JFrame{
    private Desktop desktop = null;
    private JTextArea text;
    private boolean flag = true;
    public Child(final String ver){
        if (Desktop.isDesktopSupported()){
            desktop = Desktop.getDesktop();
        }
        setTitle("Ошибка в работе программы "+ver);
        text = new JTextArea();
        text.setEditable(false);
        JLabel lbl = new JLabel(
                "<html><center><h3><font color=red>В работе программы произошла ошибка,<br>" +
                "Вы можете отправить сообщение о ошибке автору по электронной почте<br>" +
                "или продолжить работу</font></h3></center><br>" +
                "Ниже находится описание ошибки, которое может помочь рабобраться<br>" +
                "с проблемой, для разработчика эта информация очень важна</html>");
        lbl.setHorizontalAlignment(SwingConstants.CENTER);
        add(lbl,
                BorderLayout.NORTH);

        JButton btnEmail = new JButton("Отправить отчет");
        btnEmail.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent ev){
                boolean noemail = false;
                if (Desktop.isDesktopSupported()){
                    if (desktop.isSupported(Desktop.Action.MAIL)){
                        URI uri = null;
                        text.selectAll();
                        text.copy();
                        try {
                            uri = new URI("mailto", 
                     "[email protected]?SUBJECT=Error in "+ver+
                     "&BODY=Опишите причину появляения ошибки, а так же\n" +
                     "Нажмите Ctrl+V для вставки в письмо лога ошибок\n\n",
                            null);
                     //Пришлось использовать буфер обмена, т.к. длина сообщения передаваемого
                     //таким образом ограничена длиной командной строки
                     //а писать полноценный почтовый клиент не хочется
                            desktop.mail(uri);
                        }catch(Exception ex){
                            ex.printStackTrace();
                            noemail = true;
                        }
                    }
                }else noemail = true;
                if (noemail){
                    //это на тот случай, если не удалось вызвать почтовый клиент
                    //Под KDE не запускается из java :(
                    JOptionPane.showMessageDialog(Child.this,
                            "Ваша система не поддерживает вызов email клиента по умолчанию\n" +
                            "Запустите его сами и скопируйте вывод ошибок в это письмо\n"+
                            "адрес для отправки ошибок: [email protected]",
                            "Неудача отправки письма",
                            JOptionPane.ERROR_MESSAGE);
                }
            }
        });
        add(new JScrollPane(text),BorderLayout.CENTER);

        JButton btnClose = new JButton("Закрыть и продолжить работу");
        btnClose.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent ev){
                setVisible(false);
                if (!Stack.isAlive()){
                    flag = false;//завершаем тред
                    dispose();
                    System.exit(0);
                }
            }
        });
        JPanel bottom = new JPanel(new GridLayout(1,3,10,5));
        bottom.add(btnEmail);
        bottom.add(btnClose);

        add(bottom,BorderLayout.SOUTH);
        setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        setSize(600,400);
        setLocationRelativeTo(null);
        setAlwaysOnTop(true);
        runThread();
        this.addWindowListener(new WindowAdapter(){
            @Override
            public void windowClosing(WindowEvent ev){
                setVisible(false);
                //Тут проверяем нужно ли удалить ресурсы 
                //занятые окном
                if (!Stack.isAlive()){
                    flag = false;//завершаем тред
                    dispose();
                    System.exit(0);
                }
            }
        });
    }//что бы закрыть запускаем тред, который смотрит за стеком, как только 
    //стек исчезает - убиваем данное окно
    public void runThread(){
        Thread t = new Thread(){
            @Override
            public void run(){
                while (flag){
                    try{
                        Thread.sleep(100);
                    }catch(Exception ex){};//задержка нужна для того, что бы LoggingOutputStream
                    //имел шанс записать в стек, стек синхронизируемый и если из него постоянно читать
                    //то запись в него происходит крайне медленно или вообще не происходит
                    //на Linux работает без паузы, на Windows без паузы не работает
                    if (Stack.getInstance().getStackTrace().size()>0){
                    setVisible(true);
                    while (Stack.getInstance().getStackTrace().size()>0){
                        synchronized (Stack.getInstance()) {
                            text.append(Stack.getInstance().getStackTrace().remove(0));
                        }
                    }
                    }
                }
            }
        };
        t.start();
    }
    public void stopThread(){
        flag = false;
    }
}


подмена стандартного вывода ошибок
Код

import java.io.*;

class LoggingOutputStream extends ByteArrayOutputStream {

    private String lineSeparator;

    private PrintStream olderrstr;
    /**
     * Constructor
     * @param logger Logger to write to
     * @param level Level at which to write the log message
     */
    public LoggingOutputStream(PrintStream old) {
        super();

        lineSeparator = System.getProperty("line.separator");
        olderrstr = old;
    }

    /**
     * upon flush() write the existing contents of the OutputStream
     * to the logger as a log record.
     * @throws java.io.IOException in case of error
     */
    @Override
    public void flush() throws IOException {
        //String record;
        synchronized(this) {
            super.flush();
            final String record = this.toString();

            super.reset();

            if (record.length() == 0 || record.equals(lineSeparator)) {
                // avoid empty records
                return;
            }
            //а это вывод в старый поток, т.е. в консоли ничего не меняется
            olderrstr.println(record);
            //добавляем строчку в стек
            synchronized (Stack.getInstance()) {
                Stack.getInstance().getStackTrace().add(record+lineSeparator);
            }
        }
    }
}


А вот стек, можно допилить, но вроде пойдет
Код

import java.util.*;
public class Stack {
    private static boolean alive = true;
    private static Vector<String> stack = new Vector();
    private static Stack instance = null;
    private Stack(){
    }
    public static synchronized Stack getInstance(){
        if (instance==null){
            instance = new Stack();
        }
        return instance;
    }
    public Vector<String> getStackTrace(){
        //вот тут нужно синхронизирорвать доступ к данному полю
        return stack;
    }
    public static synchronized boolean isAlive(){
        return alive;
    }
    public static synchronized void setAlive(boolean state){
        alive = state;
    }
    
}


Это сообщение отредактировал(а) Connie - 2.7.2009, 13:12
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1627 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.