Откуда вы знаете все исключения, которые может выдать метод - PullRequest
3 голосов
/ 13 августа 2011

Есть ли способ получить некоторые детали относительно аспектов безопасности исключений стандартных классов Java? В основном работая с C ++ и C #, я запутался со спецификациями исключений Java, поэтому мне нужно понять, как правильно работать с исключениями.

Чтобы быть более конкретным, давайте рассмотрим ServerSocket. Он начинает прослушивать входящие соединения, как только его объект создан. Затем вы должны использовать accept(), чтобы принять соединение (если кто-то пытается подключиться).

Если вы ранее настроили сокет сервера на setSoTimeout(), есть изменение, которое accept() выдаст SocketTimeoutException, потому что никто не пытался подключиться в указанный период времени. Это нормально, серверный сокет по-прежнему пригоден для использования, поэтому вы просто вызываете accept() еще раз.

Но SocketTimeoutException - не единственное, что может бросить accept(). Что означают все остальные исключения? Если я заключу вызов в accept() с двумя предложениями catch: для SocketTimeoutException и IOException, могу ли я по-прежнему безопасно использовать связанный экземпляр ServerSocket после того, как попал в предложение IOException?

Мне бы очень хотелось получить ответы как по Java, так и по ServerSocket.

Ответы [ 6 ]

3 голосов
/ 13 августа 2011

Повторное использование объекта небезопасно.Для такого вопроса я всегда буду искать источник, поэтому он и открыт.

Так что если вы посмотрите на этот вопрос: http://kickjava.com/src/java/net/ServerSocket.java.htm вы заметите, что в accept() SocketException (наследуется от IOException), если сокет закрыт или больше не связан.Оба состояния указывают на то, что ServerSocket больше не является допустимым.

Поэтому для этого класса, как правило, если вы терпите неудачу с исключением, всегда старайтесь изящно закрыть ServerSocket в блоке finally, а затем воссоздать его.

Кроме того, в вашей области вопросов для всей Java: Всегда изучайте источник и понимайте, что делает интерфейс.Если это критически важные тесты записи, которые воспроизводят поведение (это не должно быть легко при таком низком уровне API).

Наконец, последовательно ли Java выполняет такие действия?Нет. Некоторые классы не имеют состояния, другие - нет (например, ServerSocket), некоторые - поточно-ориентированные, другие - нет.И вам нужно понять - либо из документации, либо (в основном) из кода - в каком состоянии они построены, чтобы понять, что делать, когда исключение сбивает вас с основного пути.

Большинство людей проклинают ихпроверил исключения Java, потому что большинство из них (как и большинство исключений IOException) в действительности не могут быть восстановлены осмысленным образом.Они утверждают, что в большинстве случаев вы не можете понять каждый прекрасный случай.По этой причине многие сложные фреймворки могут повторить попытку дважды или трижды, если они думают, что в этом случае могут, но в конце концов выдают исключение RuntimeException на верхний уровень фреймворка.Там они делают из этого что-то полезное (содержательная ошибка, обеспечивающая контекст) и регистрируют все детали, которые у них есть, что в большинстве случаев является огромным следом стека.Огромный источник знаний, которого многие разработчики опасаются.

Так что же вы можете сделать, если не смогли оправиться от неопробованной проблемы в кейсе?Подбросьте (возможно, с некоторым подклассом RuntimeException) наиболее значимую трассировку стека, аннотированную всем имеющимся у вас контекстом.Настройка мониторинга.И если вы столкнетесь с частой проблемой, исправьте ее.

1 голос
/ 13 августа 2011

Но SocketTimeoutException не единственное, что может выдать accept (). Что означают все остальные исключения?

Согласно javadoc , заявленными исключениями являются IOException, SecurityException, SocketTimeoutException и IllegalBlockingModeException. SecurityException и IllegalBlockingModeException встречаются только в определенных контекстах, и вы не должны пытаться их поймать и обработать. (Это не проблемы, которые вы хотите попытаться восстановить!) Случай IOException возникает, когда возникает «какая-то другая ошибка ввода-вывода». В javadoc не указано, какими могут быть эти ошибки ввода-вывода, но возможности могут включать такие вещи, как:

  • адрес, к которому вы привязаны, больше не действителен
  • произошла ошибка транспортного протокола
  • некоторая ошибка (проблема с ресурсом, ошибка ...) произошла в стеке протокола ОС

(Тот факт, что javadoc не говорит, какие подклассы IOException могут быть выброшены, является подсказкой, что вы не должны пытаться делать умные вещи, чтобы попытаться восстановить. Если вы это сделаете, ваш код, вероятно, будет платформой зависимый.)

Если я оберну вызов метода accept () двумя предложениями catch: для SocketTimeoutException и IOException, могу ли я по-прежнему безопасно использовать связанный экземпляр ServerSocket после того, как попал в предложение IOException?

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

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

1 голос
/ 13 августа 2011

Я еще не нашел простой способ проверить, находится ли объект в рабочем состоянии.Каждый объект имеет свои собственные правила.

В вашем конкретном случае с ServerSocket я бы попробовал одну из двух вещей:

  • Запустите netstat или какую-либо другую утилиту, чтобы увидеть, чтоОС думает, что сокет делает.Если ОС не думает, что слушает, значит, что-то случилось.или

  • Напишите тестовую программу, которая сгенерирует исключение, и посмотрите, что он делает.Я делаю это все время (особенно с проприетарным программным обеспечением).Было бы сложнее в выбранном вами случае ServerSocket, поскольку все сценарии, которые я могу придумать (например, используемый адрес, недостаточные привилегии и т. Д.), Никогда не приведут к тому, что объект все еще будет действительным.

1 голос
/ 13 августа 2011

Если вы прочитаете спецификацию для ServerSocket , вы увидите, что он выдает IOException "если возникает ошибка ввода-вывода при ожидании соединения". Безопасно ли снова accept() на розетке? Да. Собираетесь ли вы снова получить то же исключение? Скорее всего, так.

1 голос
/ 13 августа 2011

Да. Объект все еще существует - может быть в состоянии ошибки, в этом случае он будет выдавать другие исключения, пока это не будет исправлено.

0 голосов
/ 13 августа 2011

Вы можете найти свой ответ на javadoc setsoTimeout, он говорит:

Включить / отключить SO_TIMEOUT с указанным тайм-аутом в миллисекундах.Если для этой опции задано ненулевое время ожидания, вызов метода accept () для этого ServerSocket будет блокироваться только на это время.Если время ожидания истекает, создается исключение java.net.SocketTimeoutException, хотя ServerSocket все еще действует.Эта опция должна быть включена до начала операции блокировки, чтобы иметь эффект.Тайм-аут должен быть> 0. Тайм-аут, равный нулю, интерпретируется как бесконечный тайм-аут.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...