Вселената на Java част 1

изключението

Серия съдържание:

Това съдържание е част # от поредица # статии: Вселената на Java

Това съдържание е част от поредицата: Java Universe

Очаквайте нови статии от тази серия.

Обработката на изключения (англ.exceptions ) заема важно място в процеса на разработване на проекти на езика Java. За да видите това, просто погледнете колко изключения (илиизключения ) са декларирани в основните Java пакети и библиотеки на трети страни. Също така, един от първите аспекти, които програмистите научават, когато изучават езика Java, е използването на конструкциятаtry - catch - finally за улавяне и обработка на изключения.

И въпреки че всички програмисти са добре запознати с техническите аспекти на обработката на изключения при писане на приложение, първоначално малко хора мислят какво да правят с изключения, след като приложението е поставено в производствен режим. Най-често се стига до заключението, че „по време на разработката всички грешки са елиминирани или предвидени и следователно възникването на извънредни ситуации е изключено“ или този аспект просто е оставен на милостта на инструментите - средата за разработка и сървъра на приложения.

Въпреки това, когато възникне грешка на клиентския сървър в производствен режим, се оказва, че не е възможно да се намери информация за изключението, свързано с него, тъй като тази информация не е представена изцяло или просто липсва. Възможен е и обратният вариант, когато количеството информация е твърде голямо и е невъзможно да се изберат фрагменти в него, свързани с изключителната ситуация, която представлява интерес.

Целта на тази статия е да опише техниките(по-скоро емпирични, отколкото строго технически), които помагат да се организира работата с извънредни ситуации, така че по-късно да бъде лесно да се локализира източникът на изключение и да се предприемат мерки за отстраняване на грешката.

Намиране на причината за изключение

Отстраняването на грешката, която е причинила изключението, винаги трябва да започва с анализиране на проследяването на стека на метода, което се извършва автоматично от Java Virtual Machine, когато възникне изключение. Списък 1 показва изходния код за класаExceptionSample. Методътmethod1 на този клас се опитва да отвори входен поток за файл, който не съществува, което води до стандартно изключение,FileNotFoundException.

Списък 1. Кодов фрагмент с хвърлено изключение

Компилирането и изпълнението на този код отпечатва съдържанието на стека на методите в конзолата на Java в момента, в който е възникнало изключението, както е показано в списък 2.

Листинг 2. Проследяване на стека на метод, когато възникне изключение

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

Както можете да видите, ред 2 на листинг 2 показва методаopen на класаFileInputStream в библиотеката с класове JSE. Класовете, включени в тази библиотека, са ключови компоненти на платформата Java, те преминават през няколко етапатестване и грешки в тях са практически изключени. Следователно, въпреки че изключението е „изхвърлено“ от този метод, коренът на грешката трябва да се търси другаде. Методътinit, посочен на ред 3, също принадлежи към класа JSE и следователно е изключен.

По този начин, след изключване на системните методи на JSE, съмнителен е методътmethod1, намиращ се на ред 4. Този метод принадлежи към персонализирания класExceptionSample, така че е напълно възможно да възникнат грешки в него. И ако погледнете редове 8 и 9 в листинг 1, можете да видите защо е хвърлено изключението: когато се опитате да отворите файл, той не проверява дали той действително съществува.

Когато анализирате проследяване на стека на метод, не трябва да обръщате внимание на първия метод, посочен в него, а потърсете методи, които е най-вероятно да съдържат грешки. В този случай е напълно приложимо известното правило 80/20 - 80% от грешките са в 20% от изходния код. И тези 20% са само специфичен код на приложението - методи, свързани с класове на проекти, а основните 80% от кода са извиквания към JSE системни класове, на които може да се вярва напълно.

Анализиране на следите на стека на метода в JEE проекти

В JEE проект има няколко допълнителни неща, които трябва да имате предвид, когато анализирате следа. Първо, поради сложния жизнен цикъл на JEE приложение, проследяването може да изброява няколко десетки метода, а не четирите метода, показани в листинг 2. Следователно е необходимо специално внимание, за да се намерят сред всички тези методи тези, които принадлежат към класовете на приложенията.

Второ, в допълнение към класове от JSE библиотеки, JEE приложенията често използват класове от библиотеки на трети страни (например Spring или Hibernate). За съжаление библиотеките на трети страни може да са добреима грешки, защото малките екипи, разработващи тези библиотеки, нямат достатъчно ресурси, за да осигурят изчерпателно тестване. Следователно, ако търсенето на грешки в класовете на JEE приложението не е дало резултати, струва си да потърсите в Интернет информация за грешки, свързани с библиотечните класове, изброени в трасирането. Опитните програмисти също могат да изтеглят изходния код на библиотеката и сами да се опитат да намерят грешката.

Как правилно да организираме регистриране на изключения

Както е показано, за да се изолира успешно и коригира причината за изключение, е необходимо да се анализира проследяването на стека на метода в момента на възникването му. И за това ще е необходимо да се осигури регистриране на възникващи извънредни ситуации и при извършване на това, като цяло, просто действие, начинаещите програмисти много често правят грешки, които затрудняват последващия анализ.

Най-„тежката“ и неуловима грешка е пълното пренебрегване на изключителната ситуация. В този случай първоначалното изключение не се записва по никакъв начин в регистрационните файлове на приложението и потребителят забелязва, че нещо не е наред с програмата, след като страничните изключения са били хвърлени. Честно казано, трябва да се отбележи, че най-често такава грешка се прави не умишлено, а поради факта, че програмистът разчита твърде много на модерни среди за разработка (интегрирана среда за разработка) и техните инструменти за допълване на код. Обикновено, когато извикване на метод е написано в код, който може да генерира изключение, средата за разработка предлага обработка на това извикване чрез шаблонаtry - catch - finally. Програмистът прехвърля тази рутинна работа към IDE и се връща къмписане на основната функционалност на приложението. Проблемът е, че шаблонът, използван от IDE, може да изглежда като списък 3.

Листинг 3. Грешен модел за обработка на изключение
Листинг 4. Правилен модел за обработка на изключение

Как правилно да организираме изхода от изключителни ситуации

Най-лесният начин да постигнете това е с рамки, специално проектирани за регистриране на жизнения цикъл на Java приложения, като например библиотеката log4j. Разбира се, по време на разработката стандартни изходни потоци катоSystem.out иSystem.err също могат да се използват за регистриране на събития, но в производствен режим тази практика може да доведе до следните проблеми:

  • спад на производителността поради недостатъчна производителност на стандартните изходни потоци;
  • трудности при намирането на следи от изключения, тъй като огромно количество информация се извежда към стандартни потоци и по подразбиране не се изисква тази информация да се съхранява във файлове.

Използването на библиотеката log4j или подобна решава тези проблеми и улеснява анализа на следите, тъй като в този случай датата и часът на възникване на изключението и другата необходима информация ще се показват автоматично заедно с проследяването. Единственото важно нещо, което трябва да имате предвид е, че трябва да изведете информация за изключението с подходящ приоритет (или ниво на регистриране), както е показано в листинг 5.

Листинг 5. Регистриране на изключение с помощта на библиотеката log4j

Регистрирането на нивоdebug най-често е деактивирано в производството, но дори ако многопотребителско приложение извежда информация на нивоdebug, тази информация обикновено е толкова голяма, че е трудно да се намерят записи, свързани с конкретно изключение.

Ескалиране на изключения към по-високи нива на приложението

Когато организира обработката на изключения, програмистът може да се сблъска с друг проблем, който може значително да усложни търсенето на причината, която директно е довела до изключението. Отново, този проблем произтича от прекомерното разчитане на инструменти за разработка на софтуер и желанието на програмиста „да го направи както трябва“. Има няколко основни правила за обработка на изключения, две от които са изброени по-долу.

  • ако изключението не може да бъде обработено на нивото на приложението, където е възникнало, то трябва да бъде прехвърлено за обработка на по-високи нива на приложение;
  • от всяко ниво на приложението трябва да се „хвърлят“ изключения от съответните нива.

Ако комбинирате тези две правила заедно, ще получите следното заключение: изключение, което не може да бъде обработено на текущото ниво на приложение, трябва да бъде поставено в по-подходящ тип изключение и ескалирано до следващото ниво на приложение. На практика това означава, че когато бизнес компонент "хване" изключение за грешка в базата данни, той обгръща оригиналното изключение в ново изключение на бизнес слой и го "хвърля" за обработка, както е показано в листинг 6.

Листинг 6. Пример за ескалация на изключение

На следващото ниво този алгоритъм може да се повтори отново, което ще доведе до изпращане на изключение от още по-високо ниво и т.н. Въпреки че няма формални грешки в списък 6, нещо подобноТози подход може сериозно да попречи на анализа на извънредни ситуации, тъй като води до "разхвърляне" на файловете за редо лог. Коренът на проблема е на ред 3, където е изведена информация за изключението, тъй като такова извикване отпечатва следата на стека на извиканите методи. Ако такъв код присъства на различни нива на приложението, тогава можем да предположим, че информацията за проследяване ще бъде показана няколко пъти. Поради това дублиране ще бъде трудно да се определи къде точно е записано изключението първоначално и наистина да се намери информация за него като цяло, тъй като размерът на регистрационните файлове ще се увеличи значително.

Това е особено вярно за корпоративните JEE приложения, тъй като те обикновено се състоят от няколко нива и проследяванията на стека на метода също съдържат голям брой записи. За да избегнете попадането в такава ситуация, е необходимо правилно да организирате извеждането на информация за извънредната ситуация, например, както е показано в листинг 7.

Листинг 7. Ограничаване на изхода при ескалиране на изключение

Основното нещо е да не забравите да отпечатате пълния стек на повикванията на мястото, където ще се извърши окончателната обработка на изключението, в противен случай тази важна информация ще бъде загубена. Друг вариант е да работите в обратен ред: да отпечатате стека от извиканите методи, когато възникне първоначалното изключение, и на следващите нива да отпечатате само съобщения, прикачени към изключения. Изборът на опция зависи от личните предпочитания на програмиста, важно е само да го фиксирате в документацията и постоянно да го следвате при разработването на приложението.

Заключение

Търсенето на истинската причина, довела до появата на изключителнаситуации, може да се окаже доста предизвикателство, особено в многослойно корпоративно JEE приложение. А неправилно организираното извеждане на информация за извънредни ситуации може допълнително да усложни тази работа. Тази статия предоставя някои съвети за начинаещи програмисти, които да ви помогнат да анализирате причините за изключенията.

Първият съвет може да се приложи незабавно, когато се изследва проследяването на стека на методите, които са причинили хвърлянето на изключението. Може да има доста записи в трасиране на метод в JEE приложение и този трик помага на програмиста да изолира точно онези методи, които са в неговата зона на отговорност и най-вероятно са довели до изключението.

Другите два трика са свързани с правилата за писане на изходния код, като предлагат стил за регистриране на изключения и ескалирането им до най-високо ниво, така че по-късно, когато възникне изключение, да е удобно да се анализират лог файловете.