Здравствуйте, StanislavK, Вы писали:
SK>Есть аксиома — исключение в главное потоке приложения (который main) — логится, остальные — нет.
Вы ошибаетесь:
public class Test{
public static void main(String[] arg){
new Thread(){
public void run(){
throw new RuntimeException();
}
}.start();
}
}
Exception in thread "Thread-0" java.lang.RuntimeException
at Test$1.run(Test.java:5)
Дело совершенно не в main потоке, а в реализации ExecutorService
PD>При обращении по null происходит обращение по нулевому адресу (null pointer exception). Такое обращение приводит к исключению в процессоре , которое называется page fault, потому что в ОС Windows адреса в интервале 0..64К-1 недоступны, то есть страничный механизм настроен так, чтобы обращения к любому из этих адресов генерировали исключение. Выяснив причину page fault (причины могут быть разные, не обязательно связанные с действиями программы, например, если просто страница вытеснена в своп — тоже будет page fault), операционная система передает исключение в прикладную программу, после чего прикладная программа (в данном случае java vm) обрабатывает это исключение процессора и генерирует свое, явовское исключение (в данном случае NPE, в другом случае, скажем, ArithmeticException), которое и передается программе для обработки. PD>Это стандартный механизм обработки исключений процесора в x86/x64 по крайней мере.
Утверждать не стану, но у меня есть серьезнейшие сомнения в том, что джава завязывается на системный механизм обработки исключений, и вообще каким-либо образом с ним связана. Насколько я понимаю, все это реализуется в рантайме, а не на системном уровне. А если вылетит процессорное исключение, то джава с грохотом навернется, ибо это будет баг уже самой машины.
Кто более серьезно копал вопрос, поясните.
Новости очень смешные. Зря вы не смотрите. Как будто за наркоманами подсматриваешь. Только тетка с погодой в завязке.
There is no such thing as a winnable war.
Здравствуйте, Eugeny__, Вы писали:
E__>Утверждать не стану, но у меня есть серьезнейшие сомнения в том, что джава завязывается на системный механизм обработки исключений, и вообще каким-либо образом с ним связана. Насколько я понимаю, все это реализуется в рантайме, а не на системном уровне. А если вылетит процессорное исключение, то джава с грохотом навернется, ибо это будет баг уже самой машины.
Рантайм java есть просто процесс Win32, который работает как обычное Win32 приложение (других не бывает). Написан на С++. Он и перехватывает исключения процессора, а поэтому java vm не падает, так же как не падает моя программа, если в ней я буду обрабатывать исключения.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, StanislavK, Вы писали:
SK>>Я вот вас опять не понимаю. Вроде серьезный мужчина, а троллите. PD>Я Вас тоже. Вроде серьезная дискуссия, а Вы прибегаете к таким аргументам...
это и не аргумет вовсе.
SK>>Вот насчет этого: "NPE возникает как результат страничного исключения" я бы послушал поподробнее. Вы это откуда взяли? PD>При обращении по null происходит обращение по нулевому адресу (null pointer exception). Такое обращение приводит к исключению в процессоре , которое называется page fault, потому что в ОС Windows адреса в интервале 0..64К-1 недоступны, то есть страничный механизм настроен так, чтобы обращения к любому из этих адресов генерировали исключение. Выяснив причину page fault (причины могут быть разные, не обязательно связанные с действиями программы, например, если просто страница вытеснена в своп — тоже будет page fault), операционная система передает исключение в прикладную программу, после чего прикладная программа (в данном случае java vm) обрабатывает это исключение процессора и генерирует свое, явовское исключение (в данном случае NPE, в другом случае, скажем, ArithmeticException), которое и передается программе для обработки. PD>Это стандартный механизм обработки исключений процесора в x86/x64 по крайней мере.
Откуда вы все это взяли? Точнее откуда взяли понятно, но кто вам сказал, что ява так работает? Если в яве машине возникнет обращение по несуществующему адресу или деления на ноль, то процесс упадет, в лучшем случае, скинув дамп и немного диагностики. После такого никто в своем уме не будет пытаться восстановиться. А выглядеть это будет вот так (или так):
# An unexpected error has been detected by HotSpot Virtual Machine:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x7c911010, pid=3244, tid=280
#
# Java VM: Java HotSpot(TM) Client VM (1.5.0_02-b09 mixed mode, sharing)
# Problematic frame:
# C [ntdll.dll+0x1010]
#
# An error report file with more information is saved as hs_err_pid3244.log
#
# If you would like to submit a bug report, please visit:
# HotSpot Virtual Machine Error Reporting Page
чтобы не быть голословным, вот например, код операции, которая возвращает размер массива(из openjdk):
Видите CHECK_NULL после того как ссылку забрали со стека?
Еще стоит посмотреть, на месте в коде jdk где используется, виндовый SEH. Он как раз и отлавливает те самые исключения о которых вы говорите — EXCEPTION_ACCESS_VIOLATION, EXCEPTION_INT_DIVIDE_BY_ZERO и т.д. В этом коде и следа нет прокидывания этих исключений дальше.
Здравствуйте, Blazkowicz, Вы писали:
B>Здравствуйте, StanislavK, Вы писали:
SK>>Есть аксиома — исключение в главное потоке приложения (который main) — логится, остальные — нет. B>Вы ошибаетесь:
Правда, ошибаюсь.
B>Дело совершенно не в main потоке, а в реализации ExecutorService
+1
SK>Откуда вы все это взяли? Точнее откуда взяли понятно, но кто вам сказал, что ява так работает? Если в яве машине возникнет обращение по несуществующему адресу или деления на ноль, то процесс упадет, в лучшем случае, скинув дамп и немного диагностики. После такого никто в своем уме не будет пытаться восстановиться.
SK>чтобы не быть голословным, вот например, код операции, которая возвращает размер массива(из openjdk):
SK>
То, что вы привели — это код интерпретатора. Интерпретатор работает в самом начале. Как только обнаружен метод, выполняемый много раз, он компилируется в машинные коды. Вот найдите соответствующий кусок компилятора (кодогенератора) и посмотрим, генерится ли там проверка на null, или полагаются на аппаратную проверку.
SK>Видите CHECK_NULL после того как ссылку забрали со стека? SK>Еще стоит посмотреть, на месте в коде jdk где используется, виндовый SEH. Он как раз и отлавливает те самые исключения о которых вы говорите — EXCEPTION_ACCESS_VIOLATION, EXCEPTION_INT_DIVIDE_BY_ZERO и т.д. В этом коде и следа нет прокидывания этих исключений дальше.
Спасибо, ровно так, как я предполагал.
Новости очень смешные. Зря вы не смотрите. Как будто за наркоманами подсматриваешь. Только тетка с погодой в завязке.
There is no such thing as a winnable war.
Здравствуйте, StanislavK, Вы писали:
SK>>>Я вот вас опять не понимаю. Вроде серьезный мужчина, а троллите. PD>>Я Вас тоже. Вроде серьезная дискуссия, а Вы прибегаете к таким аргументам... SK>это и не аргумет вовсе.
Равно как и Ваш. Мне кажется, лучше вообще было не начинать эти инвективы в мой адрес.
SK>Откуда вы все это взяли? Точнее откуда взяли понятно, но кто вам сказал, что ява так работает? Если в яве машине возникнет обращение по несуществующему адресу или деления на ноль, то процесс упадет, в лучшем случае, скинув дамп и немного диагностики. После такого никто в своем уме не будет пытаться восстановиться. А выглядеть это будет вот так (или так):
SK>Видите CHECK_NULL после того как ссылку забрали со стека?
Да, по-видимому Вы правы.
В сущности есть 4 вида исключений процессора, которые портируются в прикладную программу
(1) не с нулевым указателем в яве невозможно
(2) и (4) вполне контролируемы обычным if
(3) неконтролируемо (поди пойми, будет в умножении overflow или нет — не логарифмы же вычислять!), но в яве с этим обошлись установкой режима FPU, когда вместо overflow возвращают NAN.
Вот с null — другое дело. Контролировать, конечно, несложно, но контролировать на каждой операции довольно-таки накладно. Допускаю, что ява-машина контролирует не на каждой, хотя и не очень легко привести случай, когда можно не контролировать. Решение, конечно, эффективное, но уж очень дорогое. В нативном коде так не делают : там либо обращаются напрямую по адресу в твердой уверенности, что адрес корректен, либо пытаются обратиться по адресу, который может быть и NULL, тогда ловят исключение и исправляют в обработчике исключения. Ява так не делает. Ясно.
PD>Вот с null — другое дело. Контролировать, конечно, несложно, но контролировать на каждой операции довольно-таки накладно. Допускаю, что ява-машина контролирует не на каждой, хотя и не очень легко привести случай, когда можно не контролировать. Решение, конечно, эффективное, но уж очень дорогое. В нативном коде так не делают : там либо обращаются напрямую по адресу в твердой уверенности, что адрес корректен, либо пытаются обратиться по адресу, который может быть и NULL, тогда ловят исключение и исправляют в обработчике исключения. Ява так не делает. Ясно.
Ну, как уже говорили, джит для конкретной системы и конкретной аппаратной платформы может и соптимизировать, но в общем случае мы имеем лекгопортируемое безопасное решение(if — он совсем мультиплатформенный, т.е. скомпиляется где угодно), а это основа джавы.
Хотя мне кажется, что в джит не станет заморачиваться с нативными исключениями(оно же еще и для разных архитектур и систем отличаться будет), а просто, зная достоверно дерево исполнения в текущем запущенном приложении, просто уберет к чертям ненужные проверки. Причем операция в рантайме минимкм на порядок более простая, чем для статического компилятора(например, все ссылки, которые уже инициализированы, и нигде не переопределяются, гарантированно уже валидные до конца работы, хотя при другом запуске может быть иначе — а джит обычно пробегает по уже давно инициализированному приложению, т.е. это не проблема). В Скале вообще с этим проще — там форсируется использование val(это аналог final в джаве) вместо var(переменная, т.е. может быть переопределена). И когда в коде 99% неизменяемых значений, задача еще более упрощается(заодно с многопоточностью несколько спокойнее, но это другой разговор).
Новости очень смешные. Зря вы не смотрите. Как будто за наркоманами подсматриваешь. Только тетка с погодой в завязке.
There is no such thing as a winnable war.
Здравствуйте, Eugeny__, Вы писали:
E__>Ну, как уже говорили, джит для конкретной системы и конкретной аппаратной платформы может и соптимизировать, но в общем случае мы имеем лекгопортируемое безопасное решение(if — он совсем мультиплатформенный, т.е. скомпиляется где угодно), а это основа джавы.
Да, только это значит, что проверки на кажлм обращении.
E__>Хотя мне кажется, что в джит не станет заморачиваться с нативными исключениями(оно же еще и для разных архитектур и систем отличаться будет), а просто, зная достоверно дерево исполнения в текущем запущенном приложении, просто уберет к чертям ненужные проверки. Причем операция в рантайме минимкм на порядок более простая, чем для статического компилятора(например, все ссылки, которые уже инициализированы, и нигде не переопределяются, гарантированно уже валидные до конца работы,
Слишком жесткое условие. Конечно, если они не переопределяются, это верно. Только вот определить, переопределяются они или нет, далеко не всегда так уж просто
>хотя при другом запуске может быть иначе — а джит обычно пробегает по уже давно инициализированному приложению, т.е. это не проблема).
Эту фразу я не понял. Если при другом запуске может быть иначе, то когда он пробегает ? Если при запуске(после инициализации), то еще ничего не известно ("может быть иначе"). Если же он во время работы то и дело пробегает по инициализированному приложению — когда именно ?
E__>>Ну, как уже говорили, джит для конкретной системы и конкретной аппаратной платформы может и соптимизировать, но в общем случае мы имеем лекгопортируемое безопасное решение(if — он совсем мультиплатформенный, т.е. скомпиляется где угодно), а это основа джавы.
PD>Да, только это значит, что проверки на кажлм обращении.
В режиме интерпритатора. На самом деле, не так уж все тяжко, проверка на ноль — легкая операция. Учитывая нишу джавы(сервера и обработка тонн текста), это ни о чем даже в интерпритации.
E__>>Хотя мне кажется, что в джит не станет заморачиваться с нативными исключениями(оно же еще и для разных архитектур и систем отличаться будет), а просто, зная достоверно дерево исполнения в текущем запущенном приложении, просто уберет к чертям ненужные проверки. Причем операция в рантайме минимкм на порядок более простая, чем для статического компилятора(например, все ссылки, которые уже инициализированы, и нигде не переопределяются, гарантированно уже валидные до конца работы,
PD>Слишком жесткое условие. Конечно, если они не переопределяются, это верно. Только вот определить, переопределяются они или нет, далеко не всегда так уж просто
Зная все дерево исполнения? Легче легкого. Это же байткод, а не асм(или тем более С++ код), там вручную человеку можно это установить за небольшое время, машине на это нужны наносекунды.
>>хотя при другом запуске может быть иначе — а джит обычно пробегает по уже давно инициализированному приложению, т.е. это не проблема).
PD>Эту фразу я не понял. Если при другом запуске может быть иначе, то когда он пробегает ? Если при запуске(после инициализации), то еще ничего не известно ("может быть иначе"). Если же он во время работы то и дело пробегает по инициализированному приложению — когда именно ?
Джит пробегает по часто выполняемому коду, т.е. по "узким горлышкам"(остальное выполняет интерпритер, бо нет смысла компилить в рантайме код, занимающий по процовому времени тысячные проценты от общего времени). Приложение к этому времени обычно уже подняло и инициализировало все свои компоненты(из конфигов, из сети, и с чертовых куличек), и значения многих переменных известны. Если нигде в загруженном коде нет установки значения переменной, то все проверки на ноль можно убрать, выполняя рантайм-компиляцию. Если код перезагружен(например, веб-серверу переложили файл с приложением), то, полагаю, все скомпиленное отменяется.
Новости очень смешные. Зря вы не смотрите. Как будто за наркоманами подсматриваешь. Только тетка с погодой в завязке.
There is no such thing as a winnable war.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, StanislavK, Вы писали:
PD>1) access violation PD>(1) не с нулевым указателем в яве невозможно
Теоретически возможно. Это будет означать проблему в JVM.
PD>Вот с null — другое дело. Контролировать, конечно, несложно, но контролировать на каждой операции довольно-таки накладно. Допускаю, что ява-машина контролирует не на каждой, хотя и не очень легко привести случай, когда можно не контролировать. Решение, конечно, эффективное, но уж очень дорогое. В нативном коде так не делают : там либо обращаются напрямую по адресу в твердой уверенности, что адрес корректен, либо пытаются обратиться по адресу, который может быть и NULL, тогда ловят исключение и исправляют в обработчике исключения. Ява так не делает. Ясно.
JVM так не делает еще потому, что Access Violation совсем не значит, что обратились по нулевому указателю.
PD>Вопрос же вот какой. Почему-то абсолютно отсутствует какая бы то ни было выдача по случаю самого NPE.
Потому что:
1. Разработчики Concurrency API — не Ванга и не знают, какой вам нужен способ обработки исключений и чем он лучше других способов.
2. Если вас волнует результат выполнения задачи (исключение тоже является результатом), вы по определению должны использовать FutureTask.
3. Если вас интересует появление исключений непосредственно в нити выполнения задачи, вы пишете свой try-catch в её реализации.
4. Пп. 2-3 полностью закрывают все потребности разработчиков, поэтому в добавлении в API каких-то дополнительных обработчиков нет смысла.
Здравствуйте, Eugeny__, Вы писали:
E__>Джит пробегает по часто выполняемому коду, т.е. по "узким горлышкам"(остальное выполняет интерпритер, бо нет смысла компилить в рантайме код, занимающий по процовому времени тысячные проценты от общего времени). Приложение к этому времени обычно уже подняло и инициализировало все свои компоненты(из конфигов, из сети, и с чертовых куличек), и значения многих переменных известны. Если нигде в загруженном коде нет установки значения переменной, то все проверки на ноль можно убрать, выполняя рантайм-компиляцию. Если код перезагружен(например, веб-серверу переложили файл с приложением), то, полагаю, все скомпиленное отменяется.
Если речь идёт о локальных переменных, проблем нет. Если речь идёт о полях, их может поменять код, например, через рефлексию, а это уже невозможно отследить предварительным анализом. Никаких предположений о том, что полям не присваивается NULL, VM делать не может. Поэтому либо будут проверки, либо будет ловиться аппаратное исключение и преобразовываться в JVM исключение (я не гуру машинного кода, но вроде бы тут никаких особенных проблем не должно возникнуть, ситуация для процессора вполне обычная).
Здравствуйте, vsb, Вы писали:
vsb>Если речь идёт о локальных переменных, проблем нет. Если речь идёт о полях, их может поменять код, например, через рефлексию, а это уже невозможно отследить предварительным анализом.
Теоретически, JVM вполне может при попытке доступа к полю через рефлексию отменять такие спекулятивные оптимизации.
Практически же я вообще сильно сомневаюсь что у JITа есть время анализировать все загруженные классы на предмет наличия присваиваний.
Здравствуйте, StanislavK, Вы писали:
PD>>1) access violation PD>>(1) не с нулевым указателем в яве невозможно SK>Теоретически возможно. Это будет означать проблему в JVM.
Да. Манипулируя в свое время с unsafe (не помню имя класса, что-то из sun.misc кажется) я его получил. Но это уж мои проблемы.
PD>>Вот с null — другое дело. Контролировать, конечно, несложно, но контролировать на каждой операции довольно-таки накладно. Допускаю, что ява-машина контролирует не на каждой, хотя и не очень легко привести случай, когда можно не контролировать. Решение, конечно, эффективное, но уж очень дорогое. В нативном коде так не делают : там либо обращаются напрямую по адресу в твердой уверенности, что адрес корректен, либо пытаются обратиться по адресу, который может быть и NULL, тогда ловят исключение и исправляют в обработчике исключения. Ява так не делает. Ясно. SK>JVM так не делает еще потому, что Access Violation совсем не значит, что обратились по нулевому указателю.
Вот это как раз выяснить в обработчике нативного исключения можно. По крайней мере для Windows.
Здравствуйте, RomikT, Вы писали:
RT>Здравствуйте, vsb, Вы писали:
vsb>>Если речь идёт о локальных переменных, проблем нет. Если речь идёт о полях, их может поменять код, например, через рефлексию, а это уже невозможно отследить предварительным анализом. RT>Теоретически, JVM вполне может при попытке доступа к полю через рефлексию отменять такие спекулятивные оптимизации. RT>Практически же я вообще сильно сомневаюсь что у JITа есть время анализировать все загруженные классы на предмет наличия присваиваний.
Нафига все-то? Просто хук на рефлексию поставить для этого поля. Рефлексия и так не самая скоростная штука, еще одна проверка ей сильно не помешает, зато поможет в оптимизации в рантайме.
Новости очень смешные. Зря вы не смотрите. Как будто за наркоманами подсматриваешь. Только тетка с погодой в завязке.
There is no such thing as a winnable war.
Здравствуйте, Eugeny__, Вы писали:
E__>Здравствуйте, RomikT, Вы писали:
RT>>Здравствуйте, vsb, Вы писали:
vsb>>>Если речь идёт о локальных переменных, проблем нет. Если речь идёт о полях, их может поменять код, например, через рефлексию, а это уже невозможно отследить предварительным анализом. RT>>Теоретически, JVM вполне может при попытке доступа к полю через рефлексию отменять такие спекулятивные оптимизации. RT>>Практически же я вообще сильно сомневаюсь что у JITа есть время анализировать все загруженные классы на предмет наличия присваиваний.
E__>Нафига все-то? Просто хук на рефлексию поставить для этого поля.
Что все? Оптимизации? Потому что речь шла об оптимизациях, основанных на предположении о неизменности поля, поэтому его запись естетсвенно должна отменять все такие оптимизации. Именно в виде хука на рефлексию.