2013-06-14 14 views
7

Общей проблемой с выходом консоли Java Java является то, что System.out и System.err обычно не синхронизируются должным образом, возможно потому, что они находятся на разных потоках. Это приводит к вперемешку вывода, такие как следующие: выходВызывает ошибки, которые должны быть правильно упорядочены с помощью println на выходе консоли

отладки вперемешку с выполнения трассировки стека исключений

[8, 1, 3, 5, 9, 13, 15, 17, 19] 
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 9 
scanning xAnswer: 1 xValue: 1 total: 1 [1, 1, 0, 0, 0, 0, 0, 0, 0] 
    at cra.common.Group_jsc.listSubsetSum(Group_jsc.java:29) 
scanning xAnswer: 2 xValue: 2 total: 4 [2, 1, 2, 0, 0, 0, 0, 0, 0] 
    at cra.common.Group_jsc.main(Group_jsc.java:12) 
scanning xAnswer: 3 xValue: 3 total: 9 [3, 1, 2, 3, 0, 0, 0, 0, 0] 
scanning xAnswer: 4 xValue: 4 total: 18 [4, 1, 2, 3, 4, 0, 0, 0, 0] 
scanning xAnswer: 5 xValue: 5 total: 31 [5, 1, 2, 3, 4, 5, 0, 0, 0] 
    reset to xAnswer: 4 xValue: 5 total: 26 [4, 1, 2, 3, 5, 5, 0, 0, 0] 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
scanning xAnswer: 5 xValue: 6 total: 41 [5, 1, 2, 3, 5, 6, 0, 0, 0] 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    reset to xAnswer: 4 xValue: 6 total: 35 [4, 1, 2, 3, 6, 6, 0, 0, 0] 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:601) 
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120) 
scanning xAnswer: 5 xValue: 7 total: 52 [5, 1, 2, 3, 6, 7, 0, 0, 0] 
    reset to xAnswer: 4 xValue: 7 total: 45 [4, 1, 2, 3, 7, 7, 0, 0, 0] 
scanning xAnswer: 5 xValue: 8 total: 64 [5, 1, 2, 3, 7, 8, 0, 0, 0] 
    reset to xAnswer: 4 xValue: 8 total: 56 [4, 1, 2, 3, 8, 8, 0, 0, 0] 

Process finished with exit code 1 

Поскольку исключение произошло в конце процесса я бы ожидать, что печать из Исключение составляет ПОСЛЕ все println в программе. Почему это происходит и что можно сделать, чтобы исправить проблему?

(обратите внимание, что этот конкретный пример из консоли IDEA IntelliJ, но то же самое происходит в Eclipse, и других Java Иды)

+0

Я добавил некоторые детали и ссылки на регистрационные пакеты в своем ответе @Tyler. Как упоминает @fge, в JVM встроен 'java.util.logging'. – Gray

+0

Можете ли вы показать некоторые из кода @Tyler? Вы уверены, что исключение происходит после запуска сканера? Это не в другом потоке? – Gray

+0

@Gray Это не какая-то непонятная проблема. Это затрагивает любого, кто проделал какую-либо работу с Java. Если вы хотите продемонстрировать эффект для себя, просто создайте цикл, который выплескивает много вещей в stdout, а затем выйдет из строя. –

ответ

2

Общая проблема с выходом консоли VM Java является то, что System.out и системы. err обычно не синхронизируются должным образом,

Нет, они синхронизированы отлично. Проблема в том, что линии смешиваются, потому что они печатаются как отдельные вызовы println(...). Это код из Exception.printStackTrace():

 StackTraceElement[] trace = getOurStackTrace(); 
     for (int i=0; i < trace.length; i++) 
      s.println("\tat " + trace[i]); 

Лесорубы (например, log4j) получить полный трассировки стека и превратить несколько строк в один выходной вызов журнала, который затем сохранялось атомарно.

Почему это происходит и что можно сделать для устранения проблемы?

Как правило, при использовании программ Unix стандартное значение буферизуется, а стандартная ошибка - нет. Я не думал, что это правда с Java, но, возможно, это так. Для чтения javadocs от System.out:

«Стандартный» выходной поток. Этот поток уже открыт и готов принять выходные данные. Обычно этот поток соответствует выходному изображению или другому выходному целевому назначению, заданному средой хоста или пользователем.

Versus для System.err:

По соглашению, этот выходной поток используется для отображения сообщений об ошибках или другую информацию, которая должна прийти к непосредственному вниманию пользователя, даже если выходной поток основной, значение переменной out, было перенаправлено в файл или другой адрес , который обычно не контролируется постоянно.

Смотрите этот ответ для получения более подробной информации: Why do System.err statements get printed first sometimes?

Если запустив из командной строки, вы должны перенаправить вне и заблуждаться вывод различных файлов.Вот как это сделать с помощью ~ UNIX:

How to redirect stderr and stdout to different files in the same line of bash?

В Java вы можете использовать System.setOut(...) и System.setErr(...) послать другой вывод к различным PrintStream с так что линии не чередовать.


Вы редактировали вопрос, чтобы отметить, что это происходит изнутри IDE. Если вам нужно использовать System.out и err, вы можете перенаправить их с помощью Java-кода выше.

Однако, как правило, вместо этого используется код ведения журнала. Общие пакеты протоколирования: log4j или logback, которые записывают одно многострочное сообщение журнала в выходной файл, чтобы они не чередовали. Как упоминает @fge, есть также java.util.logging built into the JVM, хотя другие пакеты предоставляют больше возможностей.

+0

Этот ответ не объясняет причину. Поскольку ошибка возникает после вызовов System.out.println, ни одна из строк в System.err не должна была быть напечатана до этого, но они это сделали. Первая часть моего вопроса - объяснить, почему это происходит. –

+0

И вы считали, что мой ответ не был полезен @TylerDurden. Да. – Gray

0

Почему это происходит и что можно сделать для устранения проблемы?

Поскольку syserr и sysout являются отдельными потоками данных, но консоль системы (IDE) пытается отображать оба одновременно. Это можно исправить, используя Logger, который, как правило, правильно упорядочивает записи в журнале.

Другая возможность заключается в вызове System.setErr и присвоении его PrintStream для файла журнала ошибок. Это будет эквивалентное Java решение для перенаправления потока ошибок.

+0

Я бы хотел использовать существующую консоль. Что вы подразумеваете под «Logger»? Могут ли они быть установлены без проблем или потребуются дополнительные неприятности? –

+2

@TylerDurden есть java.util.logging в JDK – fge

+0

Справа, это моя точка: консоль пытается ОБРАТИТЬ ИХ ОБА ОДИННАДЦАТОЙ, чтобы использовать ваши точные слова. Однако в вышеприведенном случае исключение происходит ПОСЛЕ того, как вывод на печать system.out был напечатан, поэтому вся ошибка должна была быть напечатана после того, как была напечатана информация system.out, поскольку в хронологическом порядке произошла ошибка после system.out. печать вызова. Это проблема, которую я пытаюсь понять и решить. Я считаю, что вручную буферизация потоков является обходным решением, а не решением. –

 Смежные вопросы

  • Нет связанных вопросов^_^