Что поддерживает процессы Java после выполнения JAR? - PullRequest
2 голосов
/ 19 ноября 2010

У меня есть jav-файл java, который я выполняю из командной строки Windows. Код завершается нормально (то есть делает то, что должен), но процесс Java продолжает работать. Приложение однопоточное. Мне нужно нажать Ctrl-c, чтобы остановить процесс после завершения кода, чтобы вернуть командную строку.

Я предполагаю, что мог бы поставить System.exit(0) в конце моего основного метода, который предположительно исправит это, но у меня сложилось впечатление, что в этом нет необходимости. При каких условиях Java-процессы остаются живыми в конце выполнения? Вот оболочка моего основного метода:

public static void main(String[] args) {
    try {
        //application code here
        Logger.log("Now finished");
    } catch (SomeExceptoin e) {
        Logger.error("Some error occured");
    }
}

Где регистратор - мой собственный невероятно простой статический класс, который просто сбрасывает сообщения в System.out.println(). «Теперь закончено» отображается в консоли, но процесс продолжает выполняться. Есть идеи?

РЕДАКТИРОВАТЬ: В соответствии с просьбой, вот код регистратора во всей своей красе (я вас предупреждал:)

public class Logger {
   public static void logInfo(String logMessage)
   {
      System.out.println(timestamp() + logMessage);
   }
   private static String timestamp()
   {
      SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd hh:mm:ss");
      String timestamp = "[" + formatter.format(new Date()) + "] ";
      return timestamp;
   }
}

РЕДАКТИРОВАТЬ РЕДАКТИРОВАТЬ: я поставил блок finally на мою попытку выше с кодом дампа потока по ссылке в ответе instanceofTom. Вот вывод:

... [2010.11.18 11:22:57] Вывод завершен. Вся обработка сейчас завершена.


Название темы: Ссылочный обработчик java.lang.Object.wait (собственный метод) java.lang.Object.wait (Object.java:485) java.lang.ref.Reference $ ReferenceHandler.run (Reference.java:116)


Название темы: Финализатор java.lang.Object.wait (собственный метод) java.lang.ref.ReferenceQueue.remove (ReferenceQueue.java:116) java.lang.ref.ReferenceQueue.remove (ReferenceQueue.java:132) java.lang.ref.Finalizer $ FinalizerThread.run (Finalizer.java:159)


Название темы: Диспетчер сигналов


Название темы: Attach Listener


Имя темы: Java2D Disposer java.lang.Object.wait (собственный метод) java.lang.ref.ReferenceQueue.remove (ReferenceQueue.java:116) java.lang.ref.ReferenceQueue.remove (ReferenceQueue.java:132) sun.java2d.Disposer.run (Disposer.java:125) java.lang.Thread.run (Thread.java:619)


Название темы: главная java.lang.Thread.getStackTrace (Thread.java:1436) com.my.code.WorkloadManager.visit (WorkloadManager.java:124) com.my.code.WorkloadManager.visit (WorkloadManager.java:138) com.my.code.WorkloadManager.main (WorkloadManager.java:71) sun.reflect.NativeMethodAccessorImpl.invoke0 (собственный метод) sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:39) sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:25) java.lang.reflect.Method.invoke (Method.java:597) org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main (JarRsrcLoader.java:56)


Название темы: com.google.inject.internal.Finalizer java.lang.Object.wait (собственный метод) java.lang.ref.ReferenceQueue.remove (ReferenceQueue.java:116) java.lang.ref.ReferenceQueue.remove (ReferenceQueue.java:132) com.google.inject.internal.Finalizer.run (Finalizer.java:114)


Название темы: AWT-Windows sun.awt.windows.WToolkit.eventLoop (собственный метод) sun.awt.windows.WToolkit.run (WToolkit.java:291) java.lang.Thread.run (Thread.java:619)


Имя потока: EventQueueMonitor-ComponentEvtDispatch java.lang.Object.wait (собственный метод) java.lang.Object.wait (Object.java:485) com.sun.java.accessibility.util.ComponentEvtDispatchThread.run (EventQueueMonitor.java:616) ********* ******* Название темы: Ссылочный обработчик java.lang.Object.wait (собственный метод) java.lang.Object.wait (Object.java:485) java.lang.ref.Reference $ ReferenceHandler.run (Reference.java:116)


Название темы: Финализатор java.lang.Object.wait (собственный метод) java.lang.ref.ReferenceQueue.remove (ReferenceQueue.java:116) java.lang.ref.ReferenceQueue.remove (ReferenceQueue.java:132) java.lang.ref.Finalizer $ FinalizerThread.run (Finalizer.java:159)


Название темы: Диспетчер сигналов


Название темы: Attach Listener


Название темы: Java2D Disposer java.lang.Object.wait (собственный метод) java.lang.ref.ReferenceQueue.remove (ReferenceQueue.java:116) java.lang.ref.ReferenceQueue.remove (ReferenceQueue.java:132) sun.java2d.Disposer.run (Disposer.java:125) java.lang.Thread.run (Thread.java:619)


Название темы: главная java.lang.Thread.getStackTrace (Thread.java:1436) com.my.code.WorkloadManager.visit (WorkloadManager.java:124) com.my.code.WorkloadManager.visit (WorkloadManager.java:138) com.my.code.WorkloadManager.main (WorkloadManager.java:71) sun.reflect.NativeMethodAccessorImpl.invoke0 (собственный метод) sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:39) sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:25) java.lang.reflect.Method.invoke (Method.java:597) org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main (JarRsrcLoader.java:56)


Название темы: com.google.inject.internal.Finalizer java.lang.Object.wait (собственный метод) java.lang.ref.ReferenceQueue.remove (ReferenceQueue.java:116) java.lang.ref.ReferenceQueue.remove (ReferenceQueue.java:132) com.google.inject.internal.Finalizer.run (Finalizer.java:114)


Название темы: AWT-Windows sun.awt.windows.WToolkit.eventLoop (собственный метод) sun.awt.windows.WToolkit.run (WToolkit.java:291) java.lang.Thread.run (Thread.java:619)


Имя потока: EventQueueMonitor-ComponentEvtDispatch java.lang.Object.wait (собственный метод) java.lang.Object.wait (Object.java:485) com.sun.java.accessibility.util.ComponentEvtDispatchThread.run (EventQueueMonitor.java:616)

Ответы [ 4 ]

4 голосов
/ 19 ноября 2010

Java-приложения с пользовательским интерфейсом запускают потоки обработки событий, которые не являются потоками "демона". То есть программа не прекратит работу, пока эти потоки работают & mdash; даже если в данный момент окна не отображаются.

У вас есть команда "Выход" в вашем меню? Его Action должно вызывать System.exit(0).

2 голосов
/ 19 ноября 2010

Судя по дампу вашего потока, похоже, что загружается одна из библиотек Google (возможно, Guice или Guava).

Thread name: com.google.inject.internal.Finalizer 
java.lang.Object.wait(Native Method)
java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:116) 
java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:132) 
com.google.inject.internal.Finalizer.run(Finalizer.java:114) 

Если это так, то эта ошибка может вызывать проблему:

Это связано с темой финализатора небыть отпущенным правильно.Размещены различные обходные пути.

2 голосов
/ 19 ноября 2010

Java-процесс будет оставаться активным, пока в нем запущен один или несколько потоков, не являющихся демонами.

Рассмотрите возможность использования JVisualVM, расположенного в каталоге bin Java JDK, и присоедините его к своей программе Java. Там вы сможете выполнить анализ активных потоков и их состояние, а также выполнить дамп потока.

2 голосов
/ 19 ноября 2010

Если все в вашем коде кажется нормальным, вполне вероятно, что все еще запущен потерянный поток.

Код здесь описывает, как составить список всех потоков, работающих в данный момент в JVM

В качестве альтернативы вы можете использовать профилировщик или IDE со встроенным профилировщиком для просмотра запущенных потоков.

Было бы полезно ответить на этот вопрос, если бы вы могли сообщить нам, какие потоки все еще работают, когда ваш код завершен; Несмотря на то, что ваш код может быть однопоточным, в JVM, скорее всего, будут работать и другие потоки, такие как поток сборки мусора (хотя потоки GC не будут останавливать выход JVM)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...