javaw.exe не завершится после System.exit(0)

Я пишу эту Java-программу, в которой у меня есть JFrame и Thread. Все идет нормально, за исключением того, что когда я нажимаю кнопку «X», чтобы закрыть программу, сама программа закрывается (фрейм и его ресурсы уничтожаются), но процесс «javaw.exe» не заканчивается. Я должен завершить это вручную все время.

Я пробовал, конечно, setDefaultCloseOperation(JFrame.*EXIT_ON_CLOSE*) , я даже пробовал прослушиватель окна awt с System.exit(0) в нем, но все равно безуспешно.

Любые идеи, чтобы помочь?

Это мой код. [На вашем компьютере должен быть установлен JavaCV.]

class MyGrabber implements Runnable {
    final int INTERVAL = 1000;// /you may use interval
    IplImage image;
    CanvasFrame frame = new CanvasFrame("Web Cam");

    public MyGrabber() {
        frame.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
    }

    @Override
    public void run() {
        FrameGrabber grabber = new OpenCVFrameGrabber(0); // 1 for next camera
        int i = 0;
        try {
            grabber.start();

            while (true) {
                image = grabber.grab();
                if (image != null) {
                    cvSaveImage("test.jpg", image);
                    // show image on window
                    frame.showImage(image);
                }
                Thread.sleep(INTERVAL);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (com.googlecode.javacv.FrameGrabber.Exception e) {
            e.printStackTrace();
        }
    }
}

public class TestGrabber {
    public static void main(String[] args) {
        MyGrabber gs = new MyGrabber();
        Thread th = new Thread(gs);
        th.start();
    }
}

person Emil    schedule 09.06.2012    source источник
comment
Возможно, вам потребуется предоставить нам дополнительную информацию. Если вы не получите достойного решения в ближайшее время, рассмотрите возможность создания и публикации SSCCE.   -  person Hovercraft Full Of Eels    schedule 09.06.2012
comment
Дополнительная информация? Как, например? Что не понятно?   -  person Emil    schedule 09.06.2012
comment
Я не понимаю, что вызывает вашу текущую проблему, и боюсь, что это связано с тем, что опубликованный вами код не имеет ничего общего с текущей проблемой. Если я возьму ваш код, размещенный выше, помассирую его, чтобы он скомпилировался и запустился, он не воспроизвел проблему. Поэтому для меня это означает, что проблема, вероятно, заключается в другом месте кода, который не показан. У нас нет ни времени, ни желания просматривать весь ваш код, но если бы это был мой проект, я бы попытался отсеять код до минимального компилируемого и работоспособного кода, который на самом деле демонстрирует проблему. Тогда я бы разместил его здесь.   -  person Hovercraft Full Of Eels    schedule 09.06.2012
comment
У меня такое ощущение, что у вас есть поток, не являющийся демоном, который вы где-то запустили, хотя я думал, что System.ext(...) должен остановить даже их, и поэтому я остаюсь в замешательстве, как всегда.   -  person Hovercraft Full Of Eels    schedule 09.06.2012
comment
У вас есть поток, зарегистрированный как перехватчик выключения, и всегда, если у вас есть проблема, рассмотрите возможность использования jstack. Если мой процесс отказывается «выйти», скорее всего, он застрял в ловушке выключения, на самом деле код не требуется.   -  person bestsss    schedule 09.06.2012
comment
пожалуйста, предоставьте полную реализацию запуска - я полагаю, проблема в этом.   -  person popfalushi    schedule 09.06.2012
comment
Я разместил весь код.   -  person Emil    schedule 09.06.2012
comment
Так? Нет решения этой проблемы??   -  person Emil    schedule 09.06.2012


Ответы (3)


  • Выйдите из программы (используя System.exit() или JFrame.EXIT_ON_CLOSE)
  • Зайдите в диспетчер задач и запишите идентификатор процесса (pid)
  • Откройте окно терминала и cd c:\<path>\java\bin (замените <path> своей установкой Java)
  • Используйте jstack <pid> | more. Замените <pid> идентификатором процесса из диспетчера задач.

Посмотрите на потоки, которые не помечены как «демон». Будет по крайней мере один такой поток, который зависнет и имеет обработчик выключения в трассировке стека.

person Hendrik Brummermann    schedule 09.06.2012
comment
@ Эмиль, это покажет проблемы. Если вопросы не ясны, опубликуйте вывод. - person Hendrik Brummermann; 09.06.2012
comment
@HendrikBrummermann Спасибо за это, я смотрю в правильном направлении! - person Kingsolmn; 27.03.2013

Помните это,

The JVM will terminate only and only when 
All the Non-Daemon threads including the main thread has terminated.

You can try System.exit(0) on the main thread, which runs the main method.

Попробуйте создать класс, который расширяет JFrame, а затем поместите

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); в своем конструкторе.

и да.. в вашем основном методе, где вы делаете свой кадр видимым, используйте EventQueue..

Eg:

public static void main(String[] args){
   EventQueue.invokeLater(new Runnable(){

   public void run(){
         myframe.setVisible
        }
   });
 }
person Kumar Vivek Mitra    schedule 09.06.2012
comment
Я думаю, что System.exit(...) фактически остановит потоки, не являющиеся демонами, поэтому я не опубликовал ответ. Я думаю, что у @bestsss есть идея получше. - person Hovercraft Full Of Eels; 09.06.2012

Кажется, я нашел проблемный момент. Проблема появляется в "grabber.start();" линия. (Потому что, прокомментировав эту строку, все прошло нормально. Это проблема, которую показывает библиотека openCV. Поэтому я думаю, что избавиться от этой проблемы будет не так просто.

Спасибо всем за усилия, хотя.

Отредактировано: [НАЙДЕНО РЕШЕНИЕ]

Кажется, у них класс OpenCVFrameGrabber реализовал интерфейс Thread Runnable, поэтому объект, созданный этим классом, впоследствии запускается как поток. (Хотя и не то же самое). Так или иначе, в качестве решения этой проблемы я сначала выпустил граббер:

public Test() {
    //canvas.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
    canvas.addWindowListener(new WindowAdapter() {

        @Override
        public void windowClosing(WindowEvent e) {
            System.out.println("\nClosing it.");
            try {
                //if (grabber != null)
                        grabber.release();
                        //grabber.stop();
            } catch (Exception e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }

            System.exit(0);
        }
    });
}
person Emil    schedule 09.06.2012
comment
Вы не должны обращаться к FrameGrabber из разных потоков, это не гарантирует его потокобезопасность. Вы должны вызывать функцию «grabber.stop()/release()» из того же потока, из которого вы вызывали «start()» и «grab()». Затем процесс должен завершиться правильно. - person Samuel Audet; 10.06.2012