Spec-Zone .ru
спецификации, руководства, описания, API
Содержание документации

Проект Завершения работы Сцепляет API

Следующий Q&A адресует некоторые из вопросов проектирования API Рычагов Завершения работы.

Разве это не то, для чего runFinalizersOnExit?

Можно использовать метод Runtime.runFinalizersOnExit, или эквивалентный метод в System class, чтобы запланировать действия, чтобы иметь место, когда VM завершает работу должный выйти. Этот метод, однако, не работает на инициированные завершением завершения работы. Это, также по сути опасно, и фактически эти методы осуждались в версии 1.2 JavaTM 2 Платформы.

Почему Вы не предоставляете информацию относительно того, почему VM завершает работу?

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

Рычаги завершения работы будут выполнены, если VM откажет?

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

Почему рычаги завершения работы выполняются одновременно? Не имело бы большего количества смысла выполнять их в обратном порядке регистрации?

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

Почему рычаги, только распараллеливает, и незапущенные в этом? Не было бы более просто использовать объекты Runnable, или событие Beans-style и образцы слушателя?

У подхода, проявленного здесь, есть два преимущества перед более очевидными, и более часто предлагаемыми, ориентированными на обратный вызов проектами, основанными на объектах Runnable или слушателях события Beans-style.

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

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

Разве потоки не являются довольно дорогими вещами иметь в наличии, особенно если они не будут запущены, пока VM не завершает работу?

Большинство реализаций платформы Java фактически не выделяет ресурсы потоку, пока она не запускается, таким образом поддерживая ряд незапущенных потоков фактически очень дешев. Если Вы смотрите на внутренности java.lang.Thread, можно видеть, что его различные конструкторы только делают проверки безопасности и инициализируют частные поля. Собственный метод start() делает реальную работу выделения стека потока, и т.д., чтобы получить вещи, идущие.

Что относительно Персонального и Встроенного Java? Не будет запуск потоков во время завершения работы быть слишком дорогим на тех платформах?

Этот API, возможно, не является подходящим для меньших платформ Java. Потоки в Java 2 переноса Платформы больше информации чем потоки в JDK 1.1 и p/eJava. У потока есть загрузчик class, у него могут быть некоторые наследованные локальные переменные потока, и, в случае приложений GUI, он может быть связан с определенным контекстом приложения. Потоки прибудут, чтобы перенести даже больше информации, поскольку платформа развивается; например, служба безопасности планирует представить понятие пользовательских идентификационных данных на поток в их предстоящей платформе аутентификации.

Из-за всей этой контекстной информации рычаги завершения работы было бы более трудно записать и поддержать, если бы они были только объектами Runnable или слушателями события Beans-style. Предположите, что рычаг завершения работы Runnable, или эквивалентный слушатель события, нуждался в определенном бите контекстной потоком информации, чтобы выполнить ее операции. Такая информация могла быть сохранена в некотором общем ресурсе прежде, чем рычаг будет зарегистрирован. В то время как это является просто неуклюжим, предположите далее, что потоки получают некоторый новый тип контекстной информации в будущем выпуске. Если бы работа, вызванная рычагом также, развивается, чтобы нуждаться в той информации тогда код, который регистрируется, рычаг должен был бы быть исправлен, чтобы сохранить ту информацию также. Создание рычагов быть потоками вместо Runnable s или слушателей события изолирует их от этого вида будущего изменения.

Хорошо, но разве я не должен буду записать много кода только, чтобы зарегистрировать простой рычаг завершения работы?

Нет. Простые рычаги завершения работы могут часто писаться как анонимные внутренние классы, как в этом примере:
Runtime.getRuntime().addShutdownHook(new Thread() {
    public void run() { database.close(); }
});
Эта идиома прекрасна, пока Вы никогда не должны будете отменять рычаг, когда Вы должны были бы сохранить ссылку на рычаг, когда Вы создаете это.

Что относительно безопасности? Недоверяемый апплет может зарегистрировать рычаг завершения работы?

Если есть менеджер безопасности, установленный тогда, методы addShutdownHook И removeShutdownHook проверяют, что контекст защиты вызывающей стороны разрешает RuntimePermission("shutdownHooks"). Недоверяемый апплет не будет иметь этого разрешения, и поэтому не будет в состоянии зарегистрировать или вычеркнуть из списка рычаг завершения работы.

Что происходит, если рычаг завершения работы выдает исключение, и исключение не поймано?

Непойманные исключения обрабатываются в рычагах завершения работы так же, как в любом другом потоке, вызывая метод uncaughtException объекта ThreadGroup потока. Реализация по умолчанию этого метода печатает трассировку стека исключения к System.err и завершает поток. Отметьте, что непойманные исключения не заставляют VM выходить; это происходит только, когда все потоки недемона закончились или когда метод Runtime.exit вызывается.

Почему Вы добавляли метод Runtime.halt? Разве это не довольно опасно?

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

Что происходит, если завершение на выходе включается? Финализаторы будут выполнены прежде, во время, или после рычагов завершения работы?

Обработка завершения на выходе делается после того, как все рычаги завершения работы закончились. Иначе рычаг может перестать работать, если некоторые живые объекты завершаются преждевременно.

Oracle и/или его филиалы Авторское право © 1993, 2012, Oracle и/или его филиалы. Все права защищены.
Свяжитесь с Нами