Содержание | Предыдущий | Следующий | Индекс

ГЛАВА 11

Исключения


Когда программа Java нарушает семантические ограничения языка Java, виртуальная машина Java сигнализирует эту ошибку к программе как исключение. Примером такого нарушения является попытка индексировать вне границ массива. Некоторые языки программирования и их реализации реагируют на такие ошибки, безапелляционно завершая программу; другие языки программирования позволяют реализации реагировать произвольным или непредсказуемым способом. Ни один из этих подходов не является совместимым с целями проекта Java: обеспечить мобильность и устойчивость. Вместо этого Java определяет, что исключение будет выдано, когда семантические ограничения будут нарушены и вызовут нелокальную передачу управления от точки, где исключение произошло с точкой, которая может быть определена программистом. Исключение, как говорят, выдается от точки, где это произошло и, как говорят, поймано в точке, которой передается управление.

Программы Java могут также выдать исключения явно, используя throw операторы (§14.16). Это обеспечивает альтернативу старомодному стилю условий ошибки из-за неправильного обращения, возвращая забавные значения, такие как целочисленное значение -1 где отрицательная величина обычно не ожидалась бы. Опыт показывает, что слишком часто такие забавные значения игнорируются или не проверяются на вызывающими сторонами, приводя к программам, которые не устойчивы, показывают нежелательное поведение, или обоих.

Каждое исключение представляется экземпляром класса Throwable или один из его подклассов; такой объект может использоваться, чтобы перенести информацию от точки, в которой исключение происходит с обработчиком, который ловит это. Обработчики устанавливаются catch пункты try операторы (§14.18). Во время процесса выдачи исключения виртуальная машина Java резко завершает, один за другим, любые выражения, операторы, метод и вызовы конструктора, статические инициализаторы, и полевые выражения инициализации, которые начали, но не завершили выполнение в текущем потоке. Этот процесс продолжается, пока обработчик не находится, который указывает, что это обрабатывает то определенное исключение, называя класс исключения или суперкласс класса исключения. Если никакой такой обработчик не находится, то метод uncaughtException (§20.21.31) вызывается для ThreadGroup это - родитель текущего потока таким образом, каждое усилие прилагается, чтобы избежать позволять исключению идти необработанное.

Механизм исключения Java интегрируется с моделью синхронизации Java (§17), так, чтобы блокировки были выпущены как synchronized операторы (§14.17) и вызовы synchronized методы (§8.4.3.5, §15.11) завершаются резко.

Эта глава описывает различные причины исключений (§11.1). Это детализирует, как исключения проверяются во время компиляции (§11.2) и обрабатываются во время выполнения (§11.3). Подробному примеру (§11.4) тогда следует объяснение иерархии исключения и стандартных классов исключений (§11.5).

11.1 Причины Исключений

Исключение выдается по одной из трех причин:

Исключения представляются экземплярами класса Throwable и экземпляры его подклассов. Эти классы являются, все вместе, классами исключений.

11.2 Время компиляции Проверяя Исключений

Язык Java проверяет, во время компиляции, что программа Java содержит обработчики для проверенных исключений, анализируя, который проверял, что исключения могут следовать из выполнения метода или конструктора. Для каждого проверенного исключения, которое является возможным результатом, throws пункт для метода (§8.4.4) или конструктор (§8.6.4) должен упомянуть класс того исключения или один из суперклассов класса того исключения. Это время компиляции, проверяя на присутствие обработчиков исключений разрабатывается, чтобы сократить количество исключений, которые должным образом не обрабатываются.

Классы исключений непроверенные являются классом RuntimeException и его подклассы, и класс Error и его подклассы. Все другие классы исключений являются проверенными классами исключений. Стандартный API Java определяет много классов исключений, оба проверенные и непроверенные. Дополнительные классы исключений, оба проверенные и непроверенные, могут быть объявлены программистами Java. См. §11.5 для описания иерархии класса исключений Java и классов исключений, определенных стандартным API Java и виртуальной машиной Java.

Проверенные классы исключений, названные в throws пункт является частью контракта между конструктором и пользователем метода или конструктором. throws пункт метода переопределения, возможно, не определяет, что этот метод приведет к выдаче любого проверенного исключения, которое переопределенный метод не разрешается throws пункт, чтобы бросить. Когда интерфейсы включаются, больше чем одно объявление метода может быть переопределено единственным объявлением переопределения. В этом случае у объявления переопределения должен быть a throws пункт, который является совместимым со всеми переопределенными объявлениями (§9.4).

Переменные инициализаторы для полей (§8.3.2) и статические инициализаторы (§8.5) не должны привести к проверенному исключению; если Вы делаете, ошибка времени компиляции происходит.

11.2.1 Почему Ошибки Не Проверяются

Те классы исключений непроверенные, которые являются ошибочными классами (Error и его подклассы), освобождаются со времени компиляции, проверяя, потому что они могут произойти во многих точках в программе, и восстановление от них является трудным или невозможным. Программа Java, объявляя такие исключения была бы нарушена, бессмысленно.

11.2.2 Почему Исключения на этапе выполнения Не Проверяются

Классы исключения на этапе выполнения (RuntimeException и его подклассы), освобождаются со времени компиляции, проверяя, потому что, в суждении разработчиков Java, имея необходимость объявить такие исключения не помог бы значительно в установлении правильности программ Java. Многие из операций и конструкции языка Java могут привести к исключениям на этапе выполнения. Информация, доступная компилятору Java, и уровню анализа, который выполняет компилятор, обычно не достаточна, чтобы установить, что такие исключения на этапе выполнения не могут произойти, даже при том, что это может быть очевидно для программиста Java. Требование, чтобы такие классы исключений были объявлены, просто было бы раздражением программистам Java.

Например, определенный код мог бы реализовать круговую структуру данных, которая, конструкцией, никогда не может включать null ссылки; программист может тогда быть уверенным это a NullPointerException не может произойти, но для компилятора было бы трудно доказать это. Технология доказательства теорем, которая необходима, чтобы установить такие глобальные свойства структур данных, выходит за рамки этой Спецификации языка Java.

11.3 Обработка Исключения

Когда исключение выдается, управление передается от кода, который вызвал исключение к самому близкому динамически включающему catch пункт a try оператор (§14.18), который обрабатывает исключение.

Оператор или выражение динамически включаются a catch пункт, если это появляется в пределах try блок try оператор которого catch пункт является частью, или если вызывающая сторона оператора или выражения динамически включается catch пункт.

Вызывающая сторона оператора или выражения зависит от того, где это происходит:

Ли деталь catch дескрипторы пункта исключение определяется, сравнивая класс объекта, который был брошен в объявленный тип параметра catch пункт. catch пункт обрабатывает исключение, если тип его параметра является классом исключения или суперклассом класса исключения. Эквивалентно, a catch пункт поймает любой объект исключения, который является instanceof (§15.19.2) объявленный тип параметра.

Передача управления, которая происходит, когда исключение выдается причины резкое завершение выражений (§15.5) и операторы (§14.1) до a catch с пунктом встречаются, который может обработать исключение; выполнение тогда продолжается, выполняя блок этого catch пункт. Код, который вызвал исключение, никогда не возобновляется.

Если нет catch пункт, обрабатывающий исключение, может быть найден, тогда текущий поток (поток, который встречался, исключение) завершается, но только в конце концов finally пункты были выполнены и метод uncaughtException (§20.21.31) был вызван для ThreadGroup это - родитель текущего потока.

В ситуациях, где это является требуемым, чтобы гарантировать, что один блок кода всегда выполняется за другим, даже если тот другой блок кода завершается резко, a try оператор с a finally пункт (§14.18.2) может использоваться. Если a try или catch блок в a try-finally или try-catch-finally оператор завершается резко, тогда finally пункт выполняется во время распространения исключения, даже если никакое соответствие catch пункт в конечном счете находится. Если a finally пункт выполняется из-за резкого завершения a try блок и finally сам пункт завершается резко, тогда причина резкого завершения try блок отбрасывается, и новая причина резкого завершения распространяется оттуда.

Точные правила для резкого завершения и для ловли исключений определяются подробно со спецификацией каждого оператора в §14 и для выражений в §15 (особенно §15.5).

11.3.1 Исключения Точны

Исключения в Java точны: когда передача управления имеет место, все эффекты выполняемых операторов и выражения, оцененные перед, точка, от которой выдается исключение, должно казаться, имела место. Никакие выражения, операторы, или части этого, которые происходят после точки, от которой выдается исключение, может казаться, не были оценены. Если оптимизированный код теоретически выполнил некоторые из выражений или операторов, которые следуют за точкой, в которой происходит исключение, такой код должен быть подготовлен скрыть это спекулятивное выполнение от видимого пользователем состояния программы Java.

11.3.2 Обработка Асинхронных Исключений

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

Асинхронные исключения редки в Java. Они происходят только в результате:

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

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

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

Бумага, Опрашивающая Эффективно на Аппаратных средствах Запаса Марком Фили, Proc. Конференция 1993 года по Функциональному программированию и Архитектуре ЭВМ, Копенгагену, Дания, стр 179-187, рекомендуется как дальнейшее чтение.

Как все исключения, асинхронные исключения точны (§11.3.1).

11.4 Пример Исключений

Рассмотрите следующий пример:


class TestException extends Exception {

TestException() { super(); }

TestException(String s) { super(s); }
} class Test { public static void main(String[] args) { for (int i = 0; i < args.length; i++) {

			try {
				thrower(args[i]);
				System.out.println("Test \"" + args[i] +
					"\" didn't throw an exception");
			} catch (Exception e) {
				System.out.println("Test \"" + args[i] +
					"\" threw a " + e.getClass() +
					"\n        with message: " + e.getMessage());
			}
		}
	}

static int thrower(String s) throws TestException { try { if (s.equals("divide")) { int i = 0; return i/i; } if (s.equals("null")) { s = null; return s.length(); } if (s.equals("test")) throw new TestException("Test message"); return 0; } finally { System.out.println("[thrower(\"" + s + "\") done]"); } } }
Если мы выполняем тестовую программу, передавая это параметры:

divide null not test
это производит вывод:


[thrower("divide") done]
Test "divide" threw a class java.lang.ArithmeticException
        with message: / by zero
[thrower("null") done]
Test "null" threw a class java.lang.NullPointerException
        with message: null
[thrower("not") done]
Test "not" didn't throw an exception
[thrower("test") done]
Test "test" threw a class TestException
        with message: Test message
Этот пример объявляет класс исключений TestException. main метод класса Test вызывает thrower метод четыре раза, заставляя исключения быть брошенным три из этих четырех раз. try оператор в методе main выгоды каждое исключение, что thrower броски. Ли вызов thrower завершается обычно или резко, сообщение печатается, описывая, что произошло.

Объявление метода thrower должен иметь a throws пункт, потому что это может бросить экземпляры TestException, который является проверенным классом исключений (§11.2). Ошибка времени компиляции произошла бы если throws пункт был опущен.

Заметьте что finally пункт выполняется на каждом вызове thrower, происходит ли исключение, как показано"[thrower(...) done]"вывод, который происходит для каждого вызова

11.5 Иерархия Исключения

Возможные исключения в программе Java организуются в иерархии классов, базировался в классе Throwable (§11.5, §20.22), прямой подкласс Object. Классы Exception и Error прямые подклассы Throwable. Класс RuntimeException прямой подкласс Exception.

Классы исключений объявляются стандартными пакетами java.lang, java.util, java.io и java.net вызываются стандартными классами исключений.

Программы Java могут использовать существующие ранее классы исключений в throw операторы, или определяют дополнительные классы исключений, как подклассы Throwable или любого из его подклассов, как соответствующий. Чтобы использовать в своих интересах время компиляции Java, проверяя на обработчики исключений, это типично, чтобы определить самые новые классы исключений как проверенные классы исключений, определенно как подклассы Exception это не подклассы RuntimeException.

11.5.1 Классы Exception и RuntimeException

Класс Exception суперкласс всех исключений, с которых обычные программы могут хотеть восстановиться.

11.5.1.1 Стандартные Исключения на этапе выполнения

Класс RuntimeException подкласс класса Exception. Подклассы RuntimeException классы исключений непроверенные.

Пакет java.lang определяет следующие стандартные исключения на этапе выполнения непроверенные, который, как все другие классы в пакете java.lang, неявно импортируются и поэтому может быть упомянут их простыми именами:

Пакет java.util определяет следующие дополнительные стандартные исключения на этапе выполнения непроверенные:

11.5.1.2 Стандартные Проверенные Исключения

Стандартные подклассы Exception кроме RuntimeException все проверенные классы исключений.

Пакет java.lang определяет следующие стандартные исключения, который, как все другие классы в пакете java.lang, неявно импортируются и поэтому может быть упомянут их простыми именами:

Пакет java.io определяет следующие дополнительные стандартные исключения:

Стандартный пакет java.net определяет следующие дополнительные подклассы java.io.IOException:

u java.net.MalformedURLException: Строка, которая была обеспечена как URL, или как часть URL, имела несоответствующий формат или определила неизвестный протокол.

11.5.2 Класс Error

Класс Error и его стандартные подклассы являются исключениями, с которых обычные программы, как обычно ожидают, не восстановятся. Класс Error отдельный подкласс Throwable, отличный от Exception в иерархии классов, чтобы позволить программам использовать идиому:

} catch (Exception e) {
поймать все исключения, от которых восстановление может быть возможным, не фиксируя ошибки, от которых восстановление обычно не возможно.

Пакет java.lang определяет все ошибочные классы, описанные здесь. Эти классы, как все другие классы в пакете java.lang, неявно импортируются и поэтому может быть упомянут их простыми именами.

11.5.2.1 Загрузка и Ошибки Редактирования

Виртуальная машина Java бросает объект, который является экземпляром подкласса LinkageError когда загрузка, редактирование, подготовка, проверка или ошибка инициализации происходят:

11.5.2.2 Ошибки Виртуальной машины

Виртуальная машина Java бросает объект, который является экземпляром подкласса класса VirtualMachineError когда внутреннее ограничение ошибки или ресурса препятствует тому, чтобы это реализовало семантику Языка Java. Эта спецификация языка и Спецификация виртуальной машины Java определяют следующие ошибки виртуальной машины:

Сложная программа Java может быть разработана, чтобы обработать OutOfMemoryError и попытка восстановиться с этого, возможно тщательно отбрасывая ссылки на объекты.

Мы исследуем улучшения к Java, чтобы упростить обработку условий из памяти. Одна возможность состояла бы в том, чтобы поддерживать автоматическую приостановку потока, который встречается OutOfMemoryError и позвольте другому потоку обрабатывать error ситуация. Такой метод мог бы также разрешить программе Java восстанавливаться с a StackOverflowError если это переполнение не следует из незавершающейся рекурсии. Предложения для других подходов приветствуются.


Содержание | Предыдущий | Следующий | Индекс

Спецификация языка Java (HTML, сгенерированный Блинчиком "сюзет" Pelouch 24 февраля 1998)
Авторское право © Sun Microsystems, Inc 1996 года. Все права защищены
Пожалуйста, отправьте любые комментарии или исправления к doug.kramer@sun.com



Spec-Zone.ru - all specs in one place



free hit counter