Spec-Zone .ru
спецификации, руководства, описания, API
|
ГЛАВА 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).
throw
оператор (§14.16) выполнялся в коде Java.
stop
из класса Thread
(§20.20.16) был вызван
Throwable
и экземпляры его подклассов. Эти классы являются, все вместе, классами исключений.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) не должны привести к проверенному исключению; если Вы делаете, ошибка времени компиляции происходит.
Error
и его подклассы), освобождаются со времени компиляции, проверяя, потому что они могут произойти во многих точках в программе, и восстановление от них является трудным или невозможным. Программа Java, объявляя такие исключения была бы нарушена, бессмысленно. RuntimeException
и его подклассы), освобождаются со времени компиляции, проверяя, потому что, в суждении разработчиков Java, имея необходимость объявить такие исключения не помог бы значительно в установлении правильности программ Java. Многие из операций и конструкции языка Java могут привести к исключениям на этапе выполнения. Информация, доступная компилятору Java, и уровню анализа, который выполняет компилятор, обычно не достаточна, чтобы установить, что такие исключения на этапе выполнения не могут произойти, даже при том, что это может быть очевидно для программиста Java. Требование, чтобы такие классы исключений были объявлены, просто было бы раздражением программистам Java. Например, определенный код мог бы реализовать круговую структуру данных, которая, конструкцией, никогда не может включать null
ссылки; программист может тогда быть уверенным это a NullPointerException
не может произойти, но для компилятора было бы трудно доказать это. Технология доказательства теорем, которая необходима, чтобы установить такие глобальные свойства структур данных, выходит за рамки этой Спецификации языка Java.
catch
пункт a try
оператор (§14.18), который обрабатывает исключение. Оператор или выражение динамически включаются a catch
пункт, если это появляется в пределах try
блок try
оператор которого catch
пункт является частью, или если вызывающая сторона оператора или выражения динамически включается catch
пункт.
Вызывающая сторона оператора или выражения зависит от того, где это происходит:
newInstance
это выполнялось, чтобы заставить объект создаваться.
static
переменная, тогда вызывающая сторона является выражением, которое использовало класс или интерфейс, чтобы заставить это быть инициализированным. 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).
Асинхронные исключения редки в Java. Они происходят только в результате:
stop
методы класса Thread
(§20.20.15, §20.20.16) или ThreadGroup
(§20.21.8, §20.21.9)
InternalError
(§11.5.2.2) в виртуальной машине Java stop
методы могут быть вызваны одним потоком, чтобы влиять на другой поток или все потоки в указанной группе потока. Они являются асинхронными, потому что они могут произойти в любой точке в выполнении другого потока или потоков. InternalError
считается асинхронным так, чтобы это могло быть обработано, используя тот же самый механизм, который обрабатывает stop
метод, как будет теперь описан. Java разрешает небольшому, но ограниченному количеству выполнения происходить прежде, чем асинхронное исключение будет выдано. Этой задержке разрешают позволить оптимизированному коду обнаруживать и выдавать эти исключения в точках, где это практично, чтобы обработать их, повинуясь семантике языка Java.
Простая реализация могла бы опросить относительно асинхронных исключений в точке каждой инструкции передачи управления. Так как у программы Java есть конечный размер, это обеспечивает привязанный полная задержка обнаружения асинхронного исключения. Так как никакое асинхронное исключение не произойдет между передачами управления, у генератора кода есть некоторая гибкость, чтобы переупорядочить вычисление между передачами управления для большей производительности.
Бумага, Опрашивающая Эффективно на Аппаратных средствах Запаса Марком Фили, Proc. Конференция 1993 года по Функциональному программированию и Архитектуре ЭВМ, Копенгагену, Дания, стр 179-187, рекомендуется как дальнейшее чтение.
Как все исключения, асинхронные исключения точны (§11.3.1).
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]
"вывод, который происходит для каждого вызова
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
.
Exception
и RuntimeException
Exception
суперкласс всех исключений, с которых обычные программы могут хотеть восстановиться. RuntimeException
подкласс класса Exception
. Подклассы RuntimeException
классы исключений непроверенные. Пакет java.lang
определяет следующие стандартные исключения на этапе выполнения непроверенные, который, как все другие классы в пакете java.lang
, неявно импортируются и поэтому может быть упомянут их простыми именами:
ArithmeticException
: Исключительная арифметическая ситуация возникла, такие как целочисленное деление (§15.16.2) работа с делителем нуля.
ArrayStoreException
: Попытка была предпринята, чтобы сохранить в компонент массива значение, класс которого не является присвоением, совместимым с компонентным типом массива (§10.10, §15.25.1).
ClassCastException
: Попытка была предпринята, чтобы бросить (§5.4, §15.15) ссылку на объект к несоответствующему типу.
IllegalArgumentException
: Метод передали недопустимый или несоответствующий параметр или вызван на несоответствующий объект. Подклассы этого класса включают: IllegalThreadStateException:
Поток не был в соответствующем состоянии для требуемой работы.
NumberFormatException
: Попытка была предпринята, чтобы преобразовать a String
к значению числового типа, но String
не имел соответствующего формата. IllegalMonitorStateException
: Поток попытался ожидать на (§20.1.6, §20.1.7, §20.1.8) или уведомить (§20.1.9, §20.1.10) другие потоки, ожидающие на объекте, что он не заблокировал.
IndexOutOfBoundsException
: Или индекс некоторого вида (такой относительно массива, строки, или вектор) или поддиапазон, определенный или двумя индексными значениями или индексом и длиной, испытывал недостаток диапазона.
NegativeArraySizeException
: Попытка была предпринята, чтобы создать массив с отрицательной длиной (§15.9).
NullPointerException
: Попытка была предпринята, чтобы использовать нулевую ссылку в случае, где ссылка на объект требовалась.
SecurityException
: Нарушение защиты было обнаружено (§20.17). java.util
определяет следующие дополнительные стандартные исключения на этапе выполнения непроверенные: java.util.EmptyStackException
: Попытка была предпринята, чтобы получить доступ к элементу пустого стека.
java.util.NoSuchElementException
: Попытка была предпринята, чтобы получить доступ к элементу пустого вектора. Exception
кроме RuntimeException
все проверенные классы исключений. Пакет java.lang
определяет следующие стандартные исключения, который, как все другие классы в пакете java.lang
, неявно импортируются и поэтому может быть упомянут их простыми именами:
ClassNotFoundException
: Класс или интерфейс с указанным именем не могли быть найдены (§20.3.8).
CloneNotSupportedException
: clone
метод (§20.1.5) класса Object
был вызван, чтобы клонировать объект, но класс того объекта не реализует Cloneable
интерфейс.
IllegalAccessException
: Попытка была предпринята, чтобы загрузить класс, используя строку, дающую ее полностью определенное имя, но у в настоящий момент выполняющегося метода нет доступа к определению указанного класса, потому что класс не public
и находится в другом пакете.
InstantiationException
: Попытка была предпринята, чтобы создать экземпляр класса, используя newInstance
метод в классе Class
, но указанный объект класса нельзя инстанцировать, потому что это - интерфейс, abstract
, или массив.
InterruptedException
: Текущий поток ожидал, и другой поток прервал текущий поток, используя interrupt
метод класса Thread
(§20.20.31). java.io
определяет следующие дополнительные стандартные исключения: java.io.IOException
: Требуемая работа ввода-вывода не могла обычно завершаться. Подклассы этого класса включают: java.io.EOFException
: С концом файла встретились перед нормальным завершением входной работы.
java.io.FileNotFoundException
: Файл с именем, определенным строкой имени файла или путем, не был найден в пределах файловой системы.
java.io.InterruptedIOException
: Текущий поток ожидал завершения работы ввода-вывода, и другой поток прервал текущий поток, используя interrupt
метод класса Thread
(§20.20.31).
java.io.UTFDataFormatException
: Требуемое преобразование строки к или от Java, измененный формат UTF-8 не мог быть завершен (§22.1.15, §22.2.14), потому что строка была слишком длинной или потому что подразумеваемые данные UTF-8 не были результатом кодирования строки Unicode в UTF-8. java.net
определяет следующие дополнительные подклассы java.io.IOException
: u java.net.MalformedURLException
: Строка, которая была обеспечена как URL, или как часть URL, имела несоответствующий формат или определила неизвестный протокол.
java.net.ProtocolException
: Некоторый аспект сетевого протокола не был правильно выполнен.
java.net.SocketException
: Работа, включающая сокет, не могла обычно завершаться.
java.net.UnknownHostException
: Имя сетевого узла не могло быть разрешено к сетевому адресу.
java.net.UnknownServiceException
: Сетевое соединение не может поддерживать требуемую службу. Error
Error
и его стандартные подклассы являются исключениями, с которых обычные программы, как обычно ожидают, не восстановятся. Класс Error
отдельный подкласс Throwable
, отличный от Exception
в иерархии классов, чтобы позволить программам использовать идиому: } catch (Exception e) {поймать все исключения, от которых восстановление может быть возможным, не фиксируя ошибки, от которых восстановление обычно не возможно.
Пакет java.lang
определяет все ошибочные классы, описанные здесь. Эти классы, как все другие классы в пакете java.lang
, неявно импортируются и поэтому может быть упомянут их простыми именами.
LinkageError
когда загрузка, редактирование, подготовка, проверка или ошибка инициализации происходят: ClassFormatError
, ClassCircularityError
, и NoClassDefFoundError
описываются там.
IllegalAccessError
, InstantiationError
, NoSuchFieldError
, и NoSuchMethodError
, все из которых являются подклассами IncompatibleClassChangeError
, и, также, UnsatisfiedLinkError
.
VerifyError
описывается там.
AbstractMethodError
.
ExceptionInInitializerError
если выполнение статического инициализатора или инициализатора для a static
поле приводит к исключению, которое не является Error
или подкласс Error
. VirtualMachineError
когда внутреннее ограничение ошибки или ресурса препятствует тому, чтобы это реализовало семантику Языка Java. Эта спецификация языка и Спецификация виртуальной машины Java определяют следующие ошибки виртуальной машины: InternalError
: Внутренняя ошибка произошла в виртуальной машине Java, из-за отказа в программном обеспечении, реализовывая виртуальную машину, отказ в базовом программном обеспечении хост-системы, или отказ в аппаратных средствах. Эта ошибка поставляется асинхронно, когда она обнаруживается, и может произойти в любой точке в программе Java.
OutOfMemoryError
: Виртуальная машина Java исчерпала или виртуальную память или физическую память, и автоматический менеджер по хранению не смог исправить достаточно памяти, чтобы удовлетворить объектный запрос создания.
StackOverflowError
: Виртуальная машина Java исчерпала стековое пространство для потока, обычно потому что поток делает неограниченное число рекурсивных вызовов из-за отказа в программе выполнения.
UnknownError
: Исключение или ошибка произошли, но, по некоторым причинам, виртуальная машина Java неспособна сообщить о фактическом исключении или ошибке. OutOfMemoryError
и попытка восстановиться с этого, возможно тщательно отбрасывая ссылки на объекты. Мы исследуем улучшения к Java, чтобы упростить обработку условий из памяти. Одна возможность состояла бы в том, чтобы поддерживать автоматическую приостановку потока, который встречается OutOfMemoryError
и позвольте другому потоку обрабатывать error
ситуация. Такой метод мог бы также разрешить программе Java восстанавливаться с a StackOverflowError
если это переполнение не следует из незавершающейся рекурсии. Предложения для других подходов приветствуются.
Содержание | Предыдущий | Следующий | Индекс
Спецификация языка Java (HTML, сгенерированный Блинчиком "сюзет" Pelouch 24 февраля 1998)
Авторское право © Sun Microsystems, Inc 1996 года. Все права защищены
Пожалуйста, отправьте любые комментарии или исправления к doug.kramer@sun.com