Мое сообщение в блоге за март 2019 года « Лучшее сообщение по умолчанию NullPointerException Сообщения приходят на Java? ”Было написано, когда проект JEP для улучшенных сообщений NullPointerException еще не был нацелен на конкретный выпуск JDK. С тех пор этот проект JEP стал JEP 358 («Полезные исключения NullPointerException») , который был предназначен для JDK 14 . Более того, начальная реализация ( JDK-8218628 ) уже находится в ветви JDK 14 и доступна для использования в сборке 20 раннего доступа JDK 14 (2019/10/23) .
В этом посте я продемонстрирую пример кода, представленный в моем предыдущем посте, для JDK 14 Early Access Build 20, чтобы продемонстрировать предоставленные дополнительные подробности. Чтобы увидеть этот пример кода, который был написан для преднамеренного введения множества ситуаций, приводящих к NullPointerException , см. Предыдущую публикацию или просмотр исходного кода на GitHub .
После загрузки JDK 14 Early Access Build 20 и указания моего пути я вижу следующее при запуске java -version :
|
1
2
3
|
openjdk version "14-ea" 2020-03-17OpenJDK Runtime Environment (build 14-ea+20-879)OpenJDK 64-Bit Server VM (build 14-ea+20-879, mixed mode, sharing) |
С JDK 14 Early Access Build 20, настроенным соответствующим образом, я перестроил исходный код, упомянутый ранее, а затем повторно запустил код с помощью средства запуска java без каких-либо новых опций. Вывод этого (показанный ниже) существенно не отличается от вывода с предыдущими версиями JDK.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
=========================================| #1: Element [0] on null boolean array |=========================================java.lang.NullPointerException at dustin.examples.npe.NpeDemo.demonstrateFirstExampleIndexAccessOnNullBooleanArray(Unknown Source) at dustin.examples.npe.NpeDemo.demonstrateJdk8218628Examples(Unknown Source) at dustin.examples.npe.NpeDemo.main(Unknown Source)=================================| #2: .length on null boolean[] |=================================java.lang.NullPointerException at dustin.examples.npe.NpeDemo.demonstrateSecondExampleLengthOnNullBooleanArray(Unknown Source) at dustin.examples.npe.NpeDemo.demonstrateJdk8218628Examples(Unknown Source) at dustin.examples.npe.NpeDemo.main(Unknown Source)=======================================| #3: Assigning float to null float[] |=======================================java.lang.NullPointerException at dustin.examples.npe.NpeDemo.demonstrateThirdExampleAssigningValueToElementOfNullFloatArray(Unknown Source) at dustin.examples.npe.NpeDemo.demonstrateJdk8218628Examples(Unknown Source) at dustin.examples.npe.NpeDemo.main(Unknown Source)======================================| #4: Accessing field on null object |======================================java.lang.NullPointerException at dustin.examples.npe.NpeDemo.demonstrateFourthExampleAccessInstanceFieldOfNullObject(Unknown Source) at dustin.examples.npe.NpeDemo.demonstrateJdk8218628Examples(Unknown Source) at dustin.examples.npe.NpeDemo.main(Unknown Source)===================| #5: throw null; |===================java.lang.NullPointerException at dustin.examples.npe.NpeDemo.demonstrateFifthExampleThrowingConstantNull(Unknown Source) at dustin.examples.npe.NpeDemo.demonstrateJdk8218628Examples(Unknown Source) at dustin.examples.npe.NpeDemo.main(Unknown Source)================================================| #6: Method invocation on null instance field |================================================java.lang.NullPointerException at dustin.examples.npe.NpeDemo.demonstrateSixthExampleMethodInvocationOnNullInstanceField(Unknown Source) at dustin.examples.npe.NpeDemo.demonstrateJdk8218628Examples(Unknown Source) at dustin.examples.npe.NpeDemo.main(Unknown Source)=============================================| #7: synchronized() on null instance field |=============================================java.lang.NullPointerException at dustin.examples.npe.NpeDemo.demonstrateSeventhExampleSynchronizedNullInstanceField(Unknown Source) at dustin.examples.npe.NpeDemo.demonstrateJdk8218628Examples(Unknown Source) at dustin.examples.npe.NpeDemo.main(Unknown Source)==========================================================================| >>> Null Lost in Long Series of Method Invocations in Single Statement |==========================================================================java.lang.NullPointerException at dustin.examples.npe.NpeDemo.demonstrateNullLostInSeriesOfMethodInvocationsInSingleStatement(Unknown Source) at dustin.examples.npe.NpeDemo.main(Unknown Source)=======================================================| >>> Null Lost in Dereferenced Constructor Arguments |=======================================================java.lang.NullPointerException at dustin.examples.npe.NpeDemo.demonstrateNullLostInConstructorAcceptingMultiplePotentiallyNullArgumentsDereferenced(Unknown Source) at dustin.examples.npe.NpeDemo.main(Unknown Source)==================================================| >>> Null Lost in Dereferenced Method Arguments |==================================================java.lang.NullPointerException at dustin.examples.npe.NpeDemo.demonstrateNullLostInMethodAcceptingMultiplePotentiallyNullArgumentsDereferenced(Unknown Source) at dustin.examples.npe.NpeDemo.main(Unknown Source) |
Как показывает вышеприведенный вывод, даже с новым JDK 14 Early Access Build 20 я не вижу никакой новой подробной информации о NullPointerException когда я запускаю свое приложение в обычном режиме. Я включил этот вывод, чтобы показать, что требуется специальный флаг, чтобы включить более подробные NullPointerException и чтобы было удобнее сравнивать вывод без дополнительных подробностей и с ними. В следующем выводном листинге показаны дополнительные сведения, предоставляемые при -XX:+ShowCodeDetailsInExceptionMessages запуска Java флаг -XX:+ShowCodeDetailsInExceptionMessages :
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
=========================================| #1: Element [0] on null boolean array |=========================================java.lang.NullPointerException: Cannot load from byte/boolean array because "<local1>" is null at dustin.examples.npe.NpeDemo.demonstrateFirstExampleIndexAccessOnNullBooleanArray(Unknown Source) at dustin.examples.npe.NpeDemo.demonstrateJdk8218628Examples(Unknown Source) at dustin.examples.npe.NpeDemo.main(Unknown Source)=================================| #2: .length on null boolean[] |=================================java.lang.NullPointerException: Cannot read the array length because "<local1>" is null at dustin.examples.npe.NpeDemo.demonstrateSecondExampleLengthOnNullBooleanArray(Unknown Source) at dustin.examples.npe.NpeDemo.demonstrateJdk8218628Examples(Unknown Source) at dustin.examples.npe.NpeDemo.main(Unknown Source)=======================================| #3: Assigning float to null float[] |=======================================java.lang.NullPointerException: Cannot store to float array because "<local1>" is null at dustin.examples.npe.NpeDemo.demonstrateThirdExampleAssigningValueToElementOfNullFloatArray(Unknown Source) at dustin.examples.npe.NpeDemo.demonstrateJdk8218628Examples(Unknown Source) at dustin.examples.npe.NpeDemo.main(Unknown Source)======================================| #4: Accessing field on null object |======================================java.lang.NullPointerException: Cannot read field "nullInstanceField" because "<local1>" is null at dustin.examples.npe.NpeDemo.demonstrateFourthExampleAccessInstanceFieldOfNullObject(Unknown Source) at dustin.examples.npe.NpeDemo.demonstrateJdk8218628Examples(Unknown Source) at dustin.examples.npe.NpeDemo.main(Unknown Source)===================| #5: throw null; |===================java.lang.NullPointerException: Cannot throw exception because "null" is null at dustin.examples.npe.NpeDemo.demonstrateFifthExampleThrowingConstantNull(Unknown Source) at dustin.examples.npe.NpeDemo.demonstrateJdk8218628Examples(Unknown Source) at dustin.examples.npe.NpeDemo.main(Unknown Source)================================================| #6: Method invocation on null instance field |================================================java.lang.NullPointerException: Cannot invoke "String.isEmpty()" because "this.nullInstanceField" is null at dustin.examples.npe.NpeDemo.demonstrateSixthExampleMethodInvocationOnNullInstanceField(Unknown Source) at dustin.examples.npe.NpeDemo.demonstrateJdk8218628Examples(Unknown Source) at dustin.examples.npe.NpeDemo.main(Unknown Source)=============================================| #7: synchronized() on null instance field |=============================================java.lang.NullPointerException: Cannot enter synchronized block because "this.nullInstanceField" is null at dustin.examples.npe.NpeDemo.demonstrateSeventhExampleSynchronizedNullInstanceField(Unknown Source) at dustin.examples.npe.NpeDemo.demonstrateJdk8218628Examples(Unknown Source) at dustin.examples.npe.NpeDemo.main(Unknown Source)==========================================================================| >>> Null Lost in Long Series of Method Invocations in Single Statement |==========================================================================java.lang.NullPointerException: Cannot invoke "dustin.examples.npe.DysfunctionalLocation$Province.getCity()" because the return value of "dustin.examples.npe.DysfunctionalLocation$Nation.getProvince()" is null at dustin.examples.npe.NpeDemo.demonstrateNullLostInSeriesOfMethodInvocationsInSingleStatement(Unknown Source) at dustin.examples.npe.NpeDemo.main(Unknown Source)=======================================================| >>> Null Lost in Dereferenced Constructor Arguments |=======================================================java.lang.NullPointerException: Cannot invoke "java.lang.Long.longValue()" because "<local6>" is null at dustin.examples.npe.NpeDemo.demonstrateNullLostInConstructorAcceptingMultiplePotentiallyNullArgumentsDereferenced(Unknown Source) at dustin.examples.npe.NpeDemo.main(Unknown Source)==================================================| >>> Null Lost in Dereferenced Method Arguments |==================================================java.lang.NullPointerException: Cannot invoke "java.lang.Long.longValue()" because "<local6>" is null at dustin.examples.npe.NpeDemo.demonstrateNullLostInMethodAcceptingMultiplePotentiallyNullArgumentsDereferenced(Unknown Source) at dustin.examples.npe.NpeDemo.main(Unknown Source) |
В JEP 358 объясняется использование этого флага для просмотра дополнительных сведений об NullPointerException : «Эта функция может быть переключена с помощью новой boolean опции командной строки -XX { + | - } ShowCodeDetailsInExceptionMessages -XX { + | - } ShowCodeDetailsInExceptionMessages . Опция сначала будет иметь значение «по умолчанию», чтобы сообщение не печаталось. Он предназначен для включения деталей кода в сообщениях об исключениях по умолчанию в более поздней версии » Как мы видим, эта функция изначально отключена по умолчанию, но в будущем планируется включить более подробные сообщения NullPointerException .
Недавний твит задал вопрос: «Как это будет работать, если байт-код не содержит имен переменных?» Вопрос продолжился, приведя конкретный пример: «Предположим, у нас есть код, подобный Object a = ....; a.getName(); //NPE Object a = ....; a.getName(); //NPE Object a = ....; a.getName(); //NPE Какие сообщения NPE будут иметь? » Хотя пример этого включен в мою серию тестов, показанных ранее, я подумал, что приведу здесь более конкретный пример в ответ на этот вопрос. Следующий листинг кода (который также доступен на GitHub ) показывает код, адаптированный из примера, используемого в твите.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
package dustin.examples.npe;/** * Simple demonstration to answer Tweet-ed question * "How it will work if bytecode doesn't contain variable names?" */public class TwoDoubleWhiskeyTweetExample{ public static void main(final String[] arguments) { final Person person = null; person.getName(); //NPE } public static class Person { private String name; public Person(final String newName) { name = newName; } public String getName() { return name; } }} |
На следующем снимке экрана показан результат запуска этого простого приложения с JDK 14 Early Access Build 20 без, а затем с флагом запуска java -XX:+ShowCodeDetailsInExceptionMessages .

Как показывает снимок экрана, использование флага -XX:+ShowCodeDetailsInExceptionMessages с JDK 14 раннего доступа Build 20 предоставляет дополнительную информацию, относящуюся к этому простому примеру NullPointerException : «Невозможно вызвать» dustin.examples.npe.TwoDoubleWhiskeyTweetExample $ Person.getName () «Потому что« <local1> »имеет значение null»
Пример, который проще и даже ближе к исходному примеру, представленному в вопросе Tweet-ed, доступен на GitHub .
JEP 358 (« Полезные исключения NullPointerException ») может быть не таким кричащим, как некоторые другие JEP, которые приходят в новые выпуски JDK, но в конечном итоге это может быть тот, который в конечном итоге обеспечивает большую ценность для разработчиков Java на ежедневной основе, чем некоторые из его более ярких коллег. Есть множество примеров, где это будет полезно, и многие из этих примеров ситуаций описаны в самом JEP и в моих примерах кода, на которые есть ссылки в этом посте.
|
Опубликовано на Java Code Geeks с разрешения Дастина Маркса, партнера нашей программы JCG . См. Оригинальную статью здесь: Лучшие Сообщения NPE в JDK 14 Мнения, высказанные участниками Java Code Geeks, являются их собственными. |