Рубрики
Без рубрики

Полезное исключение Nullpointerexception в Java 14

Узнайте о полезных NullPointerExceptions в Java 14.

Автор оригинала: baeldung.

1. Обзор

В этом уроке мы продолжим нашу серию на Java 14 , взглянув на Полезное NullPointerException s, которое является новой функцией, представленной в этой версии JDK.

2. Традиционное исключение Nullpointerexception

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

Предположим, мы хотим узнать адрес электронной почты сотрудника:

String emailAddress = employee.getPersonalDetails().getEmailAddress().toLowerCase();

Если сотрудник объект, получить личные данные() или получить адрес электронной почты() является нулевым, JVM выдает Исключение NullPointerException :

Exception in thread "main" java.lang.NullPointerException
  at com.baeldung.java14.npe.HelpfulNullPointerException.main(HelpfulNullPointerException.java:10)

Какова основная причина исключения? Трудно определить, какая переменная является null без использования отладчика. Кроме того, JVM выведет только метод, имя файла и номер строки, которые вызвали исключение .

В следующем разделе мы рассмотрим, как Java 14 через JEP 358 решит эту проблему.

3. Полезное исключение Nullpointerexception

SAP реализовала полезные NullPointerException s для своей коммерческой JVM в 2006 году. Он был предложен в качестве дополнения к сообществу OpenJDK в феврале 2019 года, и вскоре после этого он стал JEP. Следовательно, функция была завершена и перенесена в октябре 2019 года для выпуска JDK 14 .

По сути, JEP 358 направлен на улучшение читаемости NullPointerException s, генерируемого JVM, путем описания того, какая переменная является null .

JEP 358 приводит подробное сообщение NullPointerException , описывая переменную null вместе с методом, именем файла и номером строки. Он работает, анализируя инструкции байт-кода программы. Таким образом, он способен точно определить, какая переменная или выражение было null .

Самое главное, подробное сообщение об исключении по умолчанию отключено в JDK 14 . Чтобы включить его, нам нужно использовать опцию командной строки:

-XX:+ShowCodeDetailsInExceptionMessages

3.1. Подробное Сообщение Об Исключении

Давайте рассмотрим возможность повторного запуска кода с включенным флагом Показывать детали кода в сообщениях об исключениях :

Exception in thread "main" java.lang.NullPointerException: 
  Cannot invoke "String.toLowerCase()" because the return value of 
"com.baeldung.java14.npe.HelpfulNullPointerException$PersonalDetails.getEmailAddress()" is null
  at com.baeldung.java14.npe.HelpfulNullPointerException.main(HelpfulNullPointerException.java:10)

На этот раз, из дополнительной информации, мы знаем, что отсутствие адреса электронной почты личных данных сотрудника вызывает наше исключение. Знания, полученные в результате этого улучшения, могут сэкономить нам время во время отладки.

JVM составляет подробное сообщение об исключении из двух частей. Первая часть представляет собой неудачную операцию, следствием которой является ссылка null , в то время как вторая часть определяет причину null ссылки :

Cannot invoke "String.toLowerCase()" because the return value of "getEmailAddress()" is null

Чтобы создать сообщение об исключении, JEP 358 воссоздает часть исходного кода, которая поместила ссылку null в стек операндов.

3.2. Технические аспекты

Теперь, когда у нас есть хорошее понимание того, как идентифицировать null ссылки с помощью полезного NullPointerException s, давайте рассмотрим некоторые технические аспекты этого.

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

Во-вторых, JEP 358 вычисляет сообщение лениво, то есть только тогда, когда мы печатаем сообщение об исключении, а не когда возникает исключение . В результате не должно быть никакого влияния на производительность для обычных потоков JVM, где мы перехватываем и перестраиваем исключения, так как мы не всегда печатаем сообщение об исключении.

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

Рассмотрим простой пример, который мы скомпилировали, чтобы включить эту дополнительную отладочную информацию:

Employee employee = null;
employee.getName();

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

Cannot invoke 
  "com.baeldung.java14.npe.HelpfulNullPointerException$Employee.getName()" 
because "employee" is null

В отличие от этого, без дополнительной отладочной информации JVM предоставляет только то, что он знает о переменной в подробном сообщении:

Cannot invoke 
  "com.baeldung.java14.npe.HelpfulNullPointerException$Employee.getName()" 
because "" is null

Вместо имени локальной переменной ( employee ) JVM выводит индекс переменной, назначенный компилятором .

4. Заключение

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

Как всегда, полный исходный код статьи доступен на GitHub .