1 /*
2 * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2019 SAP SE. All rights reserved.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 */
24
25 /**
26 * @test
27 * @key randomness
28 * @summary Test extended NullPointerException message for
29 * classfiles generated with debug information. In this case the name
30 * of the variable containing the array is printed.
31 * @bug 8218628 8248476
32 * @modules java.base/java.lang:open
33 * @library /testlibrary/asm
34 * @library /test/lib
35 * @compile -g NullPointerExceptionTest.java
36 * @run main/othervm -XX:MaxJavaStackTraceDepth=1 -XX:+ShowCodeDetailsInExceptionMessages NullPointerExceptionTest hasDebugInfo
37 */
38 /**
39 * @test
40 * @key randomness
41 * @summary Test extended NullPointerException message for class
42 * files generated without debugging information. The message lists
43 * detailed information about the entity that is null.
44 * @bug 8218628 8248476
45 * @modules java.base/java.lang:open
46 * @library /testlibrary/asm
47 * @library /test/lib
48 * @compile NullPointerExceptionTest.java
49 * @run main/othervm -XX:MaxJavaStackTraceDepth=1 -XX:+ShowCodeDetailsInExceptionMessages NullPointerExceptionTest
50 */
51
52 import java.io.ByteArrayInputStream;
53 import java.io.ByteArrayOutputStream;
54 import java.io.ObjectInputStream;
55 import java.io.ObjectOutputStream;
56 import java.lang.invoke.MethodHandles.Lookup;
57 import java.lang.reflect.Array;
58 import java.util.ArrayList;
59 import java.util.Random;
60
61 import org.objectweb.asm.ClassWriter;
62 import org.objectweb.asm.Label;
63 import org.objectweb.asm.MethodVisitor;
64 import jdk.test.lib.Asserts;
65 import jdk.test.lib.Utils;
66
67 import static java.lang.invoke.MethodHandles.lookup;
68 import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
69 import static org.objectweb.asm.Opcodes.ACC_SUPER;
70 import static org.objectweb.asm.Opcodes.ACONST_NULL;
71 import static org.objectweb.asm.Opcodes.ALOAD;
72 import static org.objectweb.asm.Opcodes.ASTORE;
73 import static org.objectweb.asm.Opcodes.GETFIELD;
74 import static org.objectweb.asm.Opcodes.GETSTATIC;
75 import static org.objectweb.asm.Opcodes.ICONST_1;
76 import static org.objectweb.asm.Opcodes.ICONST_2;
77 import static org.objectweb.asm.Opcodes.INVOKESPECIAL;
78 import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
79 import static org.objectweb.asm.Opcodes.ARETURN;
80 import static org.objectweb.asm.Opcodes.IRETURN;
81 import static org.objectweb.asm.Opcodes.RETURN;
82
83 /**
84 * Tests NullPointerExceptions
85 */
86 public class NullPointerExceptionTest {
87
88 // Some fields used in the test.
89 static Object nullStaticField;
90 NullPointerExceptionTest nullInstanceField;
91 static int[][][][] staticArray;
92 static long[][] staticLongArray = new long[1000][];
93 DoubleArrayGen dag;
94 ArrayList<String> names = new ArrayList<>();
95 ArrayList<String> curr;
96 static boolean hasDebugInfo = false;
97 static final Random rng = Utils.getRandomInstance();
98
99 static {
100 staticArray = new int[1][][][];
101 staticArray[0] = new int[1][][];
102 staticArray[0][0] = new int[1][];
103 }
104
105 public static void checkMessage(Throwable t, String expression,
106 String obtainedMsg, String expectedMsg) {
107 System.out.println("\nSource code:\n " + expression + "\n\nOutput:");
108 t.printStackTrace(System.out);
109 if (expectedMsg != null && obtainedMsg == null) {
110 Asserts.fail("Got null but expected this message: \"" + expectedMsg + "\".");
111 }
112 if (obtainedMsg != expectedMsg && // E.g. both are null.
113 !obtainedMsg.equals(expectedMsg)) {
114 System.out.println("expected msg: " + expectedMsg);
115 Asserts.assertEquals(expectedMsg, obtainedMsg);
116 }
117 System.out.println("\n----");
118 }
119
120 public static void main(String[] args) throws Exception {
121 NullPointerExceptionTest t = new NullPointerExceptionTest();
122 if (args.length > 0) {
123 hasDebugInfo = true;
124 }
125
126 System.out.println("Tests for the first part of the message:");
127 System.out.println("========================================\n");
128
129 // Test the message printed for the failed action.
130 t.testFailedAction();
131
132 System.out.println("Tests for the second part of the message:");
133 System.out.println("=========================================\n");
134 // Test the method printed for the null entity.
135 t.testNullEntity();
136
137 System.out.println("Further tests:");
138 System.out.println("==============\n");
139
140 // Test if parameters are used in the code.
141 // This is relevant if there is no debug information.
142 t.testParameters();
143
144 // Test that no message is printed for exceptions
145 // allocated explicitly.
146 t.testCreation();
147
148 // Test that no message is printed for exceptions
149 // thrown in native methods.
150 t.testNative();
151
152 // Test that two calls to getMessage() return the same
153 // message.
154 // It is a design decision that it returns two different
155 // String objects.
156 t.testSameMessage();
157
158 // Test serialization.
159 // It is a design decision that after serialization the
160 // the message is lost.
161 t.testSerialization();
162
163 // Test that messages are printed for code generated
164 // on-the-fly.
165 t.testGeneratedCode();
166
167 // Some more interesting complex messages.
168 t.testComplexMessages();
169 }
170
171 // Helper method to cause test case.
172 private double callWithTypes(String[][] dummy1, int[][][] dummy2, float dummy3, long dummy4, short dummy5,
173 boolean dummy6, byte dummy7, double dummy8, char dummy9) {
174 return 0.0;
175 }
176
177 @SuppressWarnings("null")
178 public void testFailedAction() {
179 int[] ia1 = null;
180 float[] fa1 = null;
181 Object[] oa1 = null;
182 boolean[] za1 = null;
183 byte[] ba1 = null;
184 char[] ca1 = null;
185 short[] sa1 = null;
186 long[] la1 = null;
187 double[] da1 = null;
188
189 // iaload
190 try {
191 int val = ia1[0];
192 System.out.println(val);
193 Asserts.fail();
194 } catch (NullPointerException e) {
195 checkMessage(e, "int val = ia1[0];", e.getMessage(),
196 "Cannot load from int array because " +
197 (hasDebugInfo ? "\"ia1\"" : "\"<local1>\"") + " is null");
198 }
199 // faload
200 try {
201 float val = fa1[0];
202 System.out.println(val);
203 Asserts.fail();
204 } catch (NullPointerException e) {
205 checkMessage(e, "float val = fa1[0];", e.getMessage(),
206 "Cannot load from float array because " +
207 (hasDebugInfo ? "\"fa1\"" : "\"<local2>\"") + " is null");
208 }
209 // aaload
210 try {
211 Object val = oa1[0];
212 System.out.println(val);
213 Asserts.fail();
214 } catch (NullPointerException e) {
215 checkMessage(e, "Object val = oa1[0];", e.getMessage(),
216 "Cannot load from object array because " +
217 (hasDebugInfo ? "\"oa1\"" : "\"<local3>\"") + " is null");
218 }
219 // baload (boolean)
220 try {
221 boolean val = za1[0];
222 System.out.println(val);
223 Asserts.fail();
224 } catch (NullPointerException e) {
225 checkMessage(e, "boolean val = za1[0];", e.getMessage(),
226 "Cannot load from byte/boolean array because " +
227 (hasDebugInfo ? "\"za1\"" : "\"<local4>\"") + " is null");
228 }
229 // baload (byte)
230 try {
231 byte val = ba1[0];
232 System.out.println(val);
233 Asserts.fail();
234 } catch (NullPointerException e) {
235 checkMessage(e, "byte val = ba1[0];", e.getMessage(),
236 "Cannot load from byte/boolean array because " +
237 (hasDebugInfo ? "\"ba1\"" : "\"<local5>\"") + " is null");
238 }
239 // caload
240 try {
241 char val = ca1[0];
242 System.out.println(val);
243 Asserts.fail();
244 } catch (NullPointerException e) {
245 checkMessage(e, "char val = ca1[0];", e.getMessage(),
246 "Cannot load from char array because " +
247 (hasDebugInfo ? "\"ca1\"" : "\"<local6>\"") + " is null");
248 }
249 // saload
250 try {
251 short val = sa1[0];
252 System.out.println(val);
253 Asserts.fail();
254 } catch (NullPointerException e) {
255 checkMessage(e, "short val = sa1[0];", e.getMessage(),
256 "Cannot load from short array because " +
257 (hasDebugInfo ? "\"sa1\"" : "\"<local7>\"") + " is null");
258 }
259 // laload
260 try {
261 long val = la1[0];
262 System.out.println(val);
263 Asserts.fail();
264 } catch (NullPointerException e) {
265 checkMessage(e, "long val = la1[0];", e.getMessage(),
266 "Cannot load from long array because " +
267 (hasDebugInfo ? "\"la1\"" : "\"<local8>\"") + " is null");
268 }
269 // daload
270 try {
271 double val = da1[0];
272 System.out.println(val);
273 Asserts.fail();
274 } catch (NullPointerException e) {
275 checkMessage(e, "double val = da1[0];", e.getMessage(),
276 "Cannot load from double array because " +
277 (hasDebugInfo ? "\"da1\"" : "\"<local9>\"") + " is null");
278 }
279
280 // iastore
281 try {
282 ia1[0] = 0;
283 System.out.println(ia1[0]);
284 Asserts.fail();
285 } catch (NullPointerException e) {
286 checkMessage(e, "ia1[0] = 0;", e.getMessage(),
287 "Cannot store to int array because " +
288 (hasDebugInfo ? "\"ia1\"" : "\"<local1>\"") + " is null");
289 }
290 // fastore
291 try {
292 fa1[0] = 0.7f;
293 System.out.println(fa1[0]);
294 Asserts.fail();
295 } catch (NullPointerException e) {
296 checkMessage(e, "fa1[0] = 0.7f;", e.getMessage(),
297 "Cannot store to float array because " +
298 (hasDebugInfo ? "\"fa1\"" : "\"<local2>\"") + " is null");
299 }
300 // aastore
301 try {
302 oa1[0] = new Object();
303 System.out.println(oa1[0]);
304 Asserts.fail();
305 } catch (NullPointerException e) {
306 checkMessage(e, "oa1[0] = new Object();", e.getMessage(),
307 "Cannot store to object array because " +
308 (hasDebugInfo ? "\"oa1\"" : "\"<local3>\"") + " is null or is a null-free array and there's an attempt to store null in it");
309 }
310 // bastore (boolean)
311 try {
312 za1[0] = false;
313 System.out.println(za1[0]);
314 Asserts.fail();
315 } catch (NullPointerException e) {
316 checkMessage(e, "za1[0] = false;", e.getMessage(),
317 "Cannot store to byte/boolean array because " +
318 (hasDebugInfo ? "\"za1\"" : "\"<local4>\"") + " is null");
319 }
320 // bastore (byte)
321 try {
322 ba1[0] = 0;
323 System.out.println(ba1[0]);
324 Asserts.fail();
325 } catch (NullPointerException e) {
326 checkMessage(e, "ba1[0] = 0;", e.getMessage(),
327 "Cannot store to byte/boolean array because " +
328 (hasDebugInfo ? "\"ba1\"" : "\"<local5>\"") + " is null");
329 }
330 // castore
331 try {
332 ca1[0] = 0;
333 System.out.println(ca1[0]);
334 Asserts.fail();
335 } catch (NullPointerException e) {
336 checkMessage(e, "ca1[0] = 0;", e.getMessage(),
337 "Cannot store to char array because " +
338 (hasDebugInfo ? "\"ca1\"" : "\"<local6>\"") + " is null");
339 }
340 // sastore
341 try {
342 sa1[0] = 0;
343 System.out.println(sa1[0]);
344 Asserts.fail();
345 } catch (NullPointerException e) {
346 checkMessage(e, "sa1[0] = 0;", e.getMessage(),
347 "Cannot store to short array because " +
348 (hasDebugInfo ? "\"sa1\"" : "\"<local7>\"") + " is null");
349 }
350 // lastore
351 try {
352 la1[0] = 0;
353 System.out.println(la1[0]);
354 Asserts.fail();
355 } catch (NullPointerException e) {
356 checkMessage(e, "la1[0] = 0;", e.getMessage(),
357 "Cannot store to long array because " +
358 (hasDebugInfo ? "\"la1\"" : "\"<local8>\"") + " is null");
359 }
360 // dastore
361 try {
362 da1[0] = 0;
363 System.out.println(da1[0]);
364 Asserts.fail();
365 } catch (NullPointerException e) {
366 checkMessage(e, "da1[0] = 0;", e.getMessage(),
367 "Cannot store to double array because " +
368 (hasDebugInfo ? "\"da1\"" : "\"<local9>\"") + " is null");
369 }
370
371 // arraylength
372 try {
373 int val = za1.length;
374 System.out.println(val);
375 Asserts.fail();
376 } catch (NullPointerException e) {
377 checkMessage(e, " int val = za1.length;", e.getMessage(),
378 "Cannot read the array length because " +
379 (hasDebugInfo ? "\"za1\"" : "\"<local4>\"") + " is null");
380 }
381 // athrow
382 try {
383 RuntimeException exc = null;
384 throw exc;
385 } catch (NullPointerException e) {
386 checkMessage(e, "throw exc;", e.getMessage(),
387 "Cannot throw exception because " +
388 (hasDebugInfo ? "\"exc\"" : "\"<local10>\"") + " is null");
389 }
390 // monitorenter
391 try {
392 synchronized (nullInstanceField) {
393 // desired
394 }
395 } catch (NullPointerException e) {
396 checkMessage(e, "synchronized (nullInstanceField) { ... }", e.getMessage(),
397 "Cannot enter synchronized block because " +
398 "\"this.nullInstanceField\" is null");
399 }
400 // monitorexit
401 // No test available
402
403 // getfield
404 try {
405 Object val = nullInstanceField.nullInstanceField;
406 System.out.println(val);
407 Asserts.fail();
408 } catch (NullPointerException e) {
409 checkMessage(e, "Object val = nullInstanceField.nullInstanceField;", e.getMessage(),
410 "Cannot read field \"nullInstanceField\" because " +
411 "\"this.nullInstanceField\" is null");
412 }
413 // putfield
414 try {
415 nullInstanceField.nullInstanceField = new NullPointerExceptionTest();
416 System.out.println(nullInstanceField.nullInstanceField);
417 Asserts.fail();
418 } catch (NullPointerException e) {
419 checkMessage(e, "nullInstanceField.nullInstanceField = new NullPointerExceptionTest();", e.getMessage(),
420 "Cannot assign field \"nullInstanceField\" because " +
421 "\"this.nullInstanceField\" is null");
422 }
423 // invokevirtual
424 try {
425 String val = nullInstanceField.toString();
426 System.out.println(val);
427 Asserts.fail();
428 } catch (NullPointerException e) {
429 checkMessage(e, "String val = nullInstanceField.toString();", e.getMessage(),
430 "Cannot invoke \"Object.toString()\" because " +
431 "\"this.nullInstanceField\" is null");
432 }
433 // invokeinterface
434 try {
435 NullPointerExceptionTest obj = this;
436 Object val = obj.dag.getArray();
437 Asserts.assertNull(val);
438 Asserts.fail();
439 } catch (NullPointerException e) {
440 checkMessage(e, "Object val = obj.dag.getArray();", e.getMessage(),
441 "Cannot invoke \"NullPointerExceptionTest$DoubleArrayGen.getArray()\" because " +
442 (hasDebugInfo ? "\"obj" : "\"<local10>") + ".dag\" is null");
443 }
444 // invokespecial
445 G g = null;
446 try {
447 byte[] classBytes = G.generateSub2GTestClass();
448 Lookup lookup = lookup();
449 Class<?> clazz = lookup.defineClass(classBytes);
450 g = (G) clazz.getDeclaredConstructor().newInstance();
451 } catch (Exception e) {
452 e.printStackTrace();
453 Asserts.fail("Generating class Sub2G failed.");
454 }
455 try {
456 g.m2("Beginning");
457 } catch (NullPointerException e) {
458 checkMessage(e, "return super.m2(x).substring(2); // ... where super is null by bytecode manipulation.", e.getMessage(),
459 "Cannot invoke \"G.m2(String)\" because \"null\" is null");
460 }
461 // Test parameter and return types
462 try {
463 boolean val = (nullInstanceField.callWithTypes(null, null, 0.0f, 0L, (short)0, false, (byte)0, 0.0, 'x') == 0.0);
464 Asserts.assertTrue(val);
465 Asserts.fail();
466 } catch (NullPointerException e) {
467 checkMessage(e, "boolean val = (nullInstanceField.callWithTypes(null, null, 0.0f, 0L, (short)0, false, (byte)0, 0.0, 'x') == 0.0);", e.getMessage(),
468 "Cannot invoke \"NullPointerExceptionTest.callWithTypes(String[][], int[][][], float, long, short, boolean, byte, double, char)\" because " +
469 "\"this.nullInstanceField\" is null");
470 }
471 }
472
473 static void test_iload() {
474 int i0 = 0;
475 int i1 = 1;
476 int i2 = 2;
477 int i3 = 3;
478 @SuppressWarnings("unused")
479 int i4 = 4;
480 int i5 = 5;
481
482 int[][] a = new int[6][];
483
484 // iload_0
485 try {
486 a[i0][0] = 77;
487 Asserts.fail();
488 } catch (NullPointerException e) {
489 checkMessage(e, "a[i0][0] = 77;", e.getMessage(),
490 "Cannot store to int array because " +
491 (hasDebugInfo ? "\"a[i0]\"" : "\"<local6>[<local0>]\"") + " is null");
492 }
493 // iload_1
494 try {
495 a[i1][0] = 77;
496 Asserts.fail();
497 } catch (NullPointerException e) {
498 checkMessage(e, "a[i1][0] = 77;", e.getMessage(),
499 "Cannot store to int array because " +
500 (hasDebugInfo ? "\"a[i1]\"" : "\"<local6>[<local1>]\"") + " is null");
501 }
502 // iload_2
503 try {
504 a[i2][0] = 77;
505 Asserts.fail();
506 } catch (NullPointerException e) {
507 checkMessage(e, "a[i2][0] = 77;", e.getMessage(),
508 "Cannot store to int array because " +
509 (hasDebugInfo ? "\"a[i2]\"" : "\"<local6>[<local2>]\"") + " is null");
510 }
511 // iload_3
512 try {
513 a[i3][0] = 77;
514 Asserts.fail();
515 } catch (NullPointerException e) {
516 checkMessage(e, "a[i3][0] = 77;", e.getMessage(),
517 "Cannot store to int array because " +
518 (hasDebugInfo ? "\"a[i3]\"" : "\"<local6>[<local3>]\"") + " is null");
519 }
520 // iload
521 try {
522 a[i5][0] = 77;
523 Asserts.fail();
524 } catch (NullPointerException e) {
525 checkMessage(e, "a[i5][0] = 77;", e.getMessage(),
526 "Cannot store to int array because " +
527 (hasDebugInfo ? "\"a[i5]\"" : "\"<local6>[<local5>]\"") + " is null");
528 }
529 }
530
531 // Other datatyes than int are not needed.
532 // If we implement l2d and similar bytecodes, we can print
533 // long expressions as array indexes. Then these here could
534 // be used.
535 static void test_lload() {
536 long long0 = 0L; // l0 looks like 10. Therefore long0.
537 long long1 = 1L;
538 long long2 = 2L;
539 long long3 = 3L;
540 @SuppressWarnings("unused")
541 long long4 = 4L;
542 long long5 = 5L;
543
544 int[][] a = new int[6][];
545
546 // lload_0
547 try {
548 a[(int)long0][0] = 77;
549 Asserts.fail();
550 } catch (NullPointerException e) {
551 checkMessage(e, "a[(int)long0][0] = 77;", e.getMessage(),
552 "Cannot store to int array because " +
553 (hasDebugInfo ? "\"a[...]\"" : "\"<local12>[...]\"") + " is null");
554 }
555 // lload_1
556 try {
557 a[(int)long1][0] = 77;
558 Asserts.fail();
559 } catch (NullPointerException e) {
560 checkMessage(e, "a[(int)long1][0] = 77;", e.getMessage(),
561 "Cannot store to int array because " +
562 (hasDebugInfo ? "\"a[...]\"" : "\"<local12>[...]\"") + " is null");
563 }
564 // lload_2
565 try {
566 a[(int)long2][0] = 77;
567 Asserts.fail();
568 } catch (NullPointerException e) {
569 checkMessage(e, "a[(int)long2][0] = 77;", e.getMessage(),
570 "Cannot store to int array because " +
571 (hasDebugInfo ? "\"a[...]\"" : "\"<local12>[...]\"") + " is null");
572 }
573 // lload_3
574 try {
575 a[(int)long3][0] = 77;
576 Asserts.fail();
577 } catch (NullPointerException e) {
578 checkMessage(e, "a[(int)long3][0] = 77;", e.getMessage(),
579 "Cannot store to int array because " +
580 (hasDebugInfo ? "\"a[...]\"" : "\"<local12>[...]\"") + " is null");
581 }
582 // lload
583 try {
584 a[(int)long5][0] = 77;
585 Asserts.fail();
586 } catch (NullPointerException e) {
587 checkMessage(e, "a[(int)long5][0] = 77;", e.getMessage(),
588 "Cannot store to int array because " +
589 (hasDebugInfo ? "\"a[...]\"" : "\"<local12>[...]\"") + " is null");
590 }
591 }
592
593 static void test_fload() {
594 float f0 = 0.0f;
595 float f1 = 1.0f;
596 float f2 = 2.0f;
597 float f3 = 3.0f;
598 @SuppressWarnings("unused")
599 float f4 = 4.0f;
600 float f5 = 5.0f;
601
602 int[][] a = new int[6][];
603
604 // fload_0
605 try {
606 a[(int)f0][0] = 77;
607 Asserts.fail();
608 } catch (NullPointerException e) {
609 checkMessage(e, "a[(int)f0][0] = 77;", e.getMessage(),
610 "Cannot store to int array because " +
611 (hasDebugInfo ? "\"a[...]\"" : "\"<local6>[...]\"") + " is null");
612 }
613 // fload_1
614 try {
615 a[(int)f1][0] = 77;
616 Asserts.fail();
617 } catch (NullPointerException e) {
618 checkMessage(e, "a[(int)f1][0] = 77;", e.getMessage(),
619 "Cannot store to int array because " +
620 (hasDebugInfo ? "\"a[...]\"" : "\"<local6>[...]\"") + " is null");
621 }
622 // fload_2
623 try {
624 a[(int)f2][0] = 77;
625 Asserts.fail();
626 } catch (NullPointerException e) {
627 checkMessage(e, "a[(int)f2][0] = 77;", e.getMessage(),
628 "Cannot store to int array because " +
629 (hasDebugInfo ? "\"a[...]\"" : "\"<local6>[...]\"") + " is null");
630 }
631 // fload_3
632 try {
633 a[(int)f3][0] = 77;
634 Asserts.fail();
635 } catch (NullPointerException e) {
636 checkMessage(e, "a[(int)f3][0] = 77;", e.getMessage(),
637 "Cannot store to int array because " +
638 (hasDebugInfo ? "\"a[...]\"" : "\"<local6>[...]\"") + " is null");
639 }
640 // fload
641 try {
642 a[(int)f5][0] = 77;
643 Asserts.fail();
644 } catch (NullPointerException e) {
645 checkMessage(e, "a[(int)f5][0] = 77;", e.getMessage(),
646 "Cannot store to int array because " +
647 (hasDebugInfo ? "\"a[...]\"" : "\"<local6>[...]\"") + " is null");
648 }
649 }
650
651 @SuppressWarnings("null")
652 static void test_aload() {
653 F f0 = null;
654 F f1 = null;
655 F f2 = null;
656 F f3 = null;
657 @SuppressWarnings("unused")
658 F f4 = null;
659 F f5 = null;
660
661 // aload_0
662 try {
663 f0.i = 33;
664 Asserts.fail();
665 } catch (NullPointerException e) {
666 checkMessage(e, "f0.i = 33;", e.getMessage(),
667 "Cannot assign field \"i\" because " +
668 (hasDebugInfo ? "\"f0\"" : "\"<local0>\"") + " is null");
669 }
670 // aload_1
671 try {
672 f1.i = 33;
673 Asserts.fail();
674 } catch (NullPointerException e) {
675 checkMessage(e, "f1.i = 33;", e.getMessage(),
676 "Cannot assign field \"i\" because " +
677 (hasDebugInfo ? "\"f1\"" : "\"<local1>\"") + " is null");
678 }
679 // aload_2
680 try {
681 f2.i = 33;
682 Asserts.fail();
683 } catch (NullPointerException e) {
684 checkMessage(e, "f2.i = 33;", e.getMessage(),
685 "Cannot assign field \"i\" because " +
686 (hasDebugInfo ? "\"f2\"" : "\"<local2>\"") + " is null");
687 }
688 // aload_3
689 try {
690 f3.i = 33;
691 Asserts.fail();
692 } catch (NullPointerException e) {
693 checkMessage(e, "f3.i = 33;", e.getMessage(),
694 "Cannot assign field \"i\" because " +
695 (hasDebugInfo ? "\"f3\"" : "\"<local3>\"") + " is null");
696 }
697 // aload
698 try {
699 f5.i = 33;
700 Asserts.fail();
701 } catch (NullPointerException e) {
702 checkMessage(e, "f5.i = 33;", e.getMessage(),
703 "Cannot assign field \"i\" because " +
704 (hasDebugInfo ? "\"f5\"" : "\"<local5>\"") + " is null");
705 }
706 }
707
708 // Helper class for test cases.
709 class A {
710 public B to_b;
711 public B getB() { return to_b; }
712 }
713
714 // Helper class for test cases.
715 class B {
716 public C to_c;
717 public B to_b;
718 public C getC() { return to_c; }
719 public B getBfromB() { return to_b; }
720 }
721
722 // Helper class for test cases.
723 class C {
724 public D to_d;
725 public D getD() { return to_d; }
726 }
727
728 // Helper class for test cases.
729 class D {
730 public int num;
731 public int[][] ar;
732 }
733
734
735 @SuppressWarnings("null")
736 public void testArrayChasing() {
737 int[][][][][][] a = null;
738 try {
739 a[0][0][0][0][0][0] = 99;
740 Asserts.fail();
741 } catch (NullPointerException e) {
742 checkMessage(e, "a[0][0][0][0][0] = 99; // a is null", e.getMessage(),
743 "Cannot load from object array because " +
744 (hasDebugInfo ? "\"a\"" : "\"<local1>\"") + " is null");
745 }
746 a = new int[1][][][][][];
747 try {
748 a[0][0][0][0][0][0] = 99;
749 Asserts.fail();
750 } catch (NullPointerException e) {
751 checkMessage(e, "a[0][0][0][0][0] = 99; // a[0] is null", e.getMessage(),
752 "Cannot load from object array because " +
753 (hasDebugInfo ? "\"a[0]\"" : "\"<local1>[0]\"") + " is null");
754 }
755 a[0] = new int[1][][][][];
756 try {
757 a[0][0][0][0][0][0] = 99;
758 Asserts.fail();
759 } catch (NullPointerException e) {
760 checkMessage(e, "a[0][0][0][0][0] = 99; // a[0][0] is null", e.getMessage(),
761 "Cannot load from object array because " +
762 (hasDebugInfo ? "\"a[0][0]\"" : "\"<local1>[0][0]\"") + " is null");
763 }
764 a[0][0] = new int[1][][][];
765 try {
766 a[0][0][0][0][0][0] = 99;
767 Asserts.fail();
768 } catch (NullPointerException e) {
769 checkMessage(e, "a[0][0][0][0][0] = 99; // a[0][0][0] is null", e.getMessage(),
770 "Cannot load from object array because " +
771 (hasDebugInfo ? "\"a[0][0][0]\"" : "\"<local1>[0][0][0]\"") + " is null");
772 }
773 try {
774 System.out.println(a[0][0][0].length);
775 Asserts.fail();
776 } catch (NullPointerException e) {
777 checkMessage(e, "a[0][0][0].length; // a[0][0][0] is null", e.getMessage(),
778 "Cannot read the array length because " +
779 (hasDebugInfo ? "\"a[0][0][0]\"" : "\"<local1>[0][0][0]\"") + " is null");
780 }
781 a[0][0][0] = new int[1][][];
782 try {
783 a[0][0][0][0][0][0] = 99;
784 Asserts.fail();
785 } catch (NullPointerException e) {
786 checkMessage(e, "a[0][0][0][0][0] = 99; // a[0][0][0][0] is null", e.getMessage(),
787 "Cannot load from object array because " +
788 (hasDebugInfo ? "\"a[0][0][0][0]\"" : "\"<local1>[0][0][0][0]\"") + " is null");
789 }
790 a[0][0][0][0] = new int[1][];
791 // Reaching max recursion depth. Prints <array>.
792 try {
793 a[0][0][0][0][0][0] = 99;
794 Asserts.fail();
795 } catch (NullPointerException e) {
796 checkMessage(e, "a[0][0][0][0][0] = 99; // a[0][0][0][0][0] is null", e.getMessage(),
797 "Cannot store to int array because " +
798 "\"<array>[0][0][0][0][0]\" is null");
799 }
800 a[0][0][0][0][0] = new int[1];
801 try {
802 a[0][0][0][0][0][0] = 99;
803 } catch (NullPointerException e) {
804 Asserts.fail();
805 }
806 }
807
808 @SuppressWarnings("null")
809 public void testPointerChasing() {
810 A a = null;
811 try {
812 a.to_b.to_c.to_d.num = 99;
813 Asserts.fail();
814 } catch (NullPointerException e) {
815 checkMessage(e, "a.to_b.to_c.to_d.num = 99; // a is null", e.getMessage(),
816 "Cannot read field \"to_b\" because " +
817 (hasDebugInfo ? "\"a\"" : "\"<local1>\"") + " is null");
818 }
819 a = new A();
820 try {
821 a.to_b.to_c.to_d.num = 99;
822 Asserts.fail();
823 } catch (NullPointerException e) {
824 checkMessage(e, "a.to_b.to_c.to_d.num = 99; // a.to_b is null", e.getMessage(),
825 "Cannot read field \"to_c\" because " +
826 (hasDebugInfo ? "\"a.to_b\"" : "\"<local1>.to_b\"") + " is null");
827 }
828 a.to_b = new B();
829 try {
830 a.to_b.to_c.to_d.num = 99;
831 Asserts.fail();
832 } catch (NullPointerException e) {
833 checkMessage(e, "a.to_b.to_c.to_d.num = 99; // a.to_b.to_c is null", e.getMessage(),
834 "Cannot read field \"to_d\" because " +
835 (hasDebugInfo ? "\"a.to_b.to_c\"" : "\"<local1>.to_b.to_c\"") + " is null");
836 }
837 a.to_b.to_c = new C();
838 try {
839 a.to_b.to_c.to_d.num = 99;
840 Asserts.fail();
841 } catch (NullPointerException e) {
842 checkMessage(e, "a.to_b.to_c.to_d.num = 99; // a.to_b.to_c.to_d is null", e.getMessage(),
843 "Cannot assign field \"num\" because " +
844 (hasDebugInfo ? "\"a.to_b.to_c.to_d\"" : "\"<local1>.to_b.to_c.to_d\"") + " is null");
845 }
846 }
847
848 @SuppressWarnings("null")
849 public void testMethodChasing() {
850 A a = null;
851 try {
852 a.getB().getBfromB().getC().getD().num = 99;
853 Asserts.fail();
854 } catch (NullPointerException e) {
855 checkMessage(e, "a.getB().getBfromB().getC().getD().num = 99; // a is null", e.getMessage(),
856 "Cannot invoke \"NullPointerExceptionTest$A.getB()\" because " +
857 (hasDebugInfo ? "\"a" : "\"<local1>") + "\" is null");
858 }
859 a = new A();
860 try {
861 a.getB().getBfromB().getC().getD().num = 99;
862 Asserts.fail();
863 } catch (NullPointerException e) {
864 checkMessage(e, "a.getB().getBfromB().getC().getD().num = 99; // a.getB() is null", e.getMessage(),
865 "Cannot invoke \"NullPointerExceptionTest$B.getBfromB()\" because " +
866 "the return value of \"NullPointerExceptionTest$A.getB()\" is null");
867 }
868 a.to_b = new B();
869 try {
870 a.getB().getBfromB().getC().getD().num = 99;
871 Asserts.fail();
872 } catch (NullPointerException e) {
873 checkMessage(e, "a.getB().getBfromB().getC().getD().num = 99; // a.getB().getBfromB() is null", e.getMessage(),
874 "Cannot invoke \"NullPointerExceptionTest$B.getC()\" because " +
875 "the return value of \"NullPointerExceptionTest$B.getBfromB()\" is null");
876 }
877 a.to_b.to_b = new B();
878 try {
879 a.getB().getBfromB().getC().getD().num = 99;
880 Asserts.fail();
881 } catch (NullPointerException e) {
882 checkMessage(e, "a.getB().getBfromB().getC().getD().num = 99; // a.getB().getBfromB().getC() is null", e.getMessage(),
883 "Cannot invoke \"NullPointerExceptionTest$C.getD()\" because " +
884 "the return value of \"NullPointerExceptionTest$B.getC()\" is null");
885 }
886 a.to_b.to_b.to_c = new C();
887 try {
888 a.getB().getBfromB().getC().getD().num = 99;
889 Asserts.fail();
890 } catch (NullPointerException e) {
891 checkMessage(e, "a.getB().getBfromB().getC().getD().num = 99; // a.getB().getBfromB().getC().getD() is null", e.getMessage(),
892 "Cannot assign field \"num\" because " +
893 "the return value of \"NullPointerExceptionTest$C.getD()\" is null");
894 }
895 }
896
897 @SuppressWarnings("null")
898 public void testMixedChasing() {
899 A a = null;
900 try {
901 a.getB().getBfromB().to_c.to_d.ar[0][0] = 99;
902 Asserts.fail();
903 } catch (NullPointerException e) {
904 checkMessage(e, "a.getB().getBfromB().to_c.to_d.ar[0][0] = 99; // a is null", e.getMessage(),
905 "Cannot invoke \"NullPointerExceptionTest$A.getB()\" because " +
906 (hasDebugInfo ? "\"a\"" : "\"<local1>\"") + " is null");
907 }
908 a = new A();
909 try {
910 a.getB().getBfromB().to_c.to_d.ar[0][0] = 99;
911 Asserts.fail();
912 } catch (NullPointerException e) {
913 checkMessage(e, "a.getB().getBfromB().to_c.to_d.ar[0][0] = 99; // a.getB() is null", e.getMessage(),
914 "Cannot invoke \"NullPointerExceptionTest$B.getBfromB()\" because " +
915 "the return value of \"NullPointerExceptionTest$A.getB()\" is null");
916 }
917 a.to_b = new B();
918 try {
919 a.getB().getBfromB().to_c.to_d.ar[0][0] = 99;
920 Asserts.fail();
921 } catch (NullPointerException e) {
922 checkMessage(e, "a.getB().getBfromB().to_c.to_d.ar[0][0] = 99; // a.getB().getBfromB() is null", e.getMessage(),
923 "Cannot read field \"to_c\" because " +
924 "the return value of \"NullPointerExceptionTest$B.getBfromB()\" is null");
925 }
926 a.to_b.to_b = new B();
927 try {
928 a.getB().getBfromB().to_c.to_d.ar[0][0] = 99;
929 Asserts.fail();
930 } catch (NullPointerException e) {
931 checkMessage(e, "a.getB().getBfromB().to_c.to_d.ar[0][0] = 99; // a.getB().getBfromB().to_c is null", e.getMessage(),
932 "Cannot read field \"to_d\" because " +
933 "\"NullPointerExceptionTest$B.getBfromB().to_c\" is null");
934 }
935 a.to_b.to_b.to_c = new C();
936 try {
937 a.getB().getBfromB().to_c.to_d.ar[0][0] = 99;
938 Asserts.fail();
939 } catch (NullPointerException e) {
940 checkMessage(e, "a.getB().getBfromB().to_c.to_d.ar[0][0] = 99; // a.getB().getBfromB().to_c.to_d is null", e.getMessage(),
941 "Cannot read field \"ar\" because " +
942 "\"NullPointerExceptionTest$B.getBfromB().to_c.to_d\" is null");
943 }
944 a.to_b.to_b.to_c.to_d = new D();
945 try {
946 a.getB().getBfromB().to_c.to_d.ar[0][0] = 99;
947 Asserts.fail();
948 } catch (NullPointerException e) {
949 checkMessage(e, "a.getB().getBfromB().to_c.to_d.ar[0][0] = 99; // a.getB().getBfromB().to_c.to_d.ar is null", e.getMessage(),
950 "Cannot load from object array because " +
951 "\"NullPointerExceptionTest$B.getBfromB().to_c.to_d.ar\" is null");
952 }
953 try {
954 a.getB().getBfromB().getC().getD().ar[0][0] = 99;
955 Asserts.fail();
956 } catch (NullPointerException e) {
957 checkMessage(e, "a.getB().getBfromB().getC().getD().ar[0][0] = 99; // a.getB().getBfromB().getC().getD().ar is null", e.getMessage(),
958 "Cannot load from object array because " +
959 "\"NullPointerExceptionTest$C.getD().ar\" is null");
960 }
961 a.to_b.to_b.to_c.to_d.ar = new int[1][];
962 try {
963 a.getB().getBfromB().to_c.to_d.ar[0][0] = 99;
964 Asserts.fail();
965 } catch (NullPointerException e) {
966 checkMessage(e, "a.getB().getBfromB().to_c.to_d.ar[0][0] = 99; // a.getB().getBfromB().to_c.to_d.ar[0] is null", e.getMessage(),
967 "Cannot store to int array because " +
968 "\"NullPointerExceptionTest$B.getBfromB().to_c.to_d.ar[0]\" is null");
969 }
970 try {
971 a.getB().getBfromB().getC().getD().ar[0][0] = 99;
972 Asserts.fail();
973 } catch (NullPointerException e) {
974 checkMessage(e, "a.getB().getBfromB().getC().getD().ar[0][0] = 99; // a.getB().getBfromB().getC().getD().ar[0] is null", e.getMessage(),
975 "Cannot store to int array because " +
976 "\"NullPointerExceptionTest$C.getD().ar[0]\" is null");
977 }
978 }
979
980 // Helper method to cause test case.
981 private Object returnNull(String[][] dummy1, int[][][] dummy2, float dummy3) {
982 return null;
983 }
984
985 // Helper method to cause test case.
986 private NullPointerExceptionTest returnMeAsNull(Throwable dummy1, int dummy2, char dummy3) {
987 return null;
988 }
989
990 // Helper interface for test cases.
991 static interface DoubleArrayGen {
992 public double[] getArray();
993 }
994
995 // Helper class for test cases.
996 static class DoubleArrayGenImpl implements DoubleArrayGen {
997 @Override
998 public double[] getArray() {
999 return null;
1000 }
1001 }
1002
1003 // Helper class for test cases.
1004 static class NullPointerGenerator {
1005 public static Object nullReturner(boolean dummy1) {
1006 return null;
1007 }
1008
1009 public Object returnMyNull(double dummy1, long dummy2, short dummy3) {
1010 return null;
1011 }
1012 }
1013
1014 // Helper method to cause test case.
1015 public void ImplTestLoadedFromMethod(DoubleArrayGen gen) {
1016 try {
1017 (gen.getArray())[0] = 1.0;
1018 Asserts.fail();
1019 } catch (NullPointerException e) {
1020 checkMessage(e, "(gen.getArray())[0] = 1.0;", e.getMessage(),
1021 "Cannot store to double array because " +
1022 "the return value of \"NullPointerExceptionTest$DoubleArrayGen.getArray()\" is null");
1023 }
1024 }
1025
1026 public void testNullEntity() {
1027 int[][] a = new int[820][];
1028
1029 test_iload();
1030 test_lload();
1031 test_fload();
1032 // test_dload();
1033 test_aload();
1034 // aload_0: 'this'
1035 try {
1036 this.nullInstanceField.nullInstanceField = new NullPointerExceptionTest();
1037 Asserts.fail();
1038 } catch (NullPointerException e) {
1039 checkMessage(e, "this.nullInstanceField.nullInstanceField = new NullPointerExceptionTest();", e.getMessage(),
1040 "Cannot assign field \"nullInstanceField\" because \"this.nullInstanceField\" is null");
1041 }
1042
1043 // aconst_null
1044 try {
1045 throw null;
1046 } catch (NullPointerException e) {
1047 checkMessage(e, "throw null;", e.getMessage(),
1048 "Cannot throw exception because \"null\" is null");
1049 }
1050 // iconst_0
1051 try {
1052 a[0][0] = 77;
1053 Asserts.fail();
1054 } catch (NullPointerException e) {
1055 checkMessage(e, "a[0][0] = 77;", e.getMessage(),
1056 "Cannot store to int array because " +
1057 (hasDebugInfo ? "\"a[0]\"" : "\"<local1>[0]\"") + " is null");
1058 }
1059 // iconst_1
1060 try {
1061 a[1][0] = 77;
1062 Asserts.fail();
1063 } catch (NullPointerException e) {
1064 checkMessage(e, "a[1][0] = 77;", e.getMessage(),
1065 "Cannot store to int array because " +
1066 (hasDebugInfo ? "\"a[1]\"" : "\"<local1>[1]\"") + " is null");
1067 }
1068 // iconst_2
1069 try {
1070 a[2][0] = 77;
1071 Asserts.fail();
1072 } catch (NullPointerException e) {
1073 checkMessage(e, "a[2][0] = 77;", e.getMessage(),
1074 "Cannot store to int array because " +
1075 (hasDebugInfo ? "\"a[2]\"" : "\"<local1>[2]\"") + " is null");
1076 }
1077 // iconst_3
1078 try {
1079 a[3][0] = 77;
1080 Asserts.fail();
1081 } catch (NullPointerException e) {
1082 checkMessage(e, "a[3][0] = 77;", e.getMessage(),
1083 "Cannot store to int array because " +
1084 (hasDebugInfo ? "\"a[3]\"" : "\"<local1>[3]\"") + " is null");
1085 }
1086 // iconst_4
1087 try {
1088 a[4][0] = 77;
1089 Asserts.fail();
1090 } catch (NullPointerException e) {
1091 checkMessage(e, "a[4][0] = 77;", e.getMessage(),
1092 "Cannot store to int array because " +
1093 (hasDebugInfo ? "\"a[4]\"" : "\"<local1>[4]\"") + " is null");
1094 }
1095 // iconst_5
1096 try {
1097 a[5][0] = 77;
1098 Asserts.fail();
1099 } catch (NullPointerException e) {
1100 checkMessage(e, "a[5][0] = 77;", e.getMessage(),
1101 "Cannot store to int array because " +
1102 (hasDebugInfo ? "\"a[5]\"" : "\"<local1>[5]\"") + " is null");
1103 }
1104 // long --> iconst
1105 try {
1106 a[(int)0L][0] = 77;
1107 Asserts.fail();
1108 } catch (NullPointerException e) {
1109 checkMessage(e, "a[(int)0L][0] = 77;", e.getMessage(),
1110 "Cannot store to int array because " +
1111 (hasDebugInfo ? "\"a[0]\"" : "\"<local1>[0]\"") + " is null");
1112 }
1113 // bipush
1114 try {
1115 a[139 /*0x77*/][0] = 77;
1116 Asserts.fail();
1117 } catch (NullPointerException e) {
1118 checkMessage(e, "a[139][0] = 77;", e.getMessage(),
1119 "Cannot store to int array because " +
1120 (hasDebugInfo ? "\"a[139]\"" : "\"<local1>[139]\"") + " is null");
1121 }
1122 // sipush
1123 try {
1124 a[819 /*0x333*/][0] = 77;
1125 Asserts.fail();
1126 } catch (NullPointerException e) {
1127 checkMessage(e, "a[819][0] = 77;", e.getMessage(),
1128 "Cannot store to int array because " +
1129 (hasDebugInfo ? "\"a[819]\"" : "\"<local1>[819]\"") + " is null");
1130 }
1131
1132 // aaload, with recursive descend.
1133 testArrayChasing();
1134
1135 // getstatic
1136 try {
1137 boolean val = (((float[]) nullStaticField)[0] == 1.0f);
1138 Asserts.assertTrue(val);
1139 Asserts.fail();
1140 } catch (NullPointerException e) {
1141 checkMessage(e, "boolean val = (((float[]) nullStaticField)[0] == 1.0f);", e.getMessage(),
1142 "Cannot load from float array because \"NullPointerExceptionTest.nullStaticField\" is null");
1143 }
1144
1145 // getfield, with recursive descend.
1146 testPointerChasing();
1147
1148 // invokestatic
1149 try {
1150 char val = ((char[]) NullPointerGenerator.nullReturner(false))[0];
1151 System.out.println(val);
1152 Asserts.fail();
1153 } catch (NullPointerException e) {
1154 checkMessage(e, "char val = ((char[]) NullPointerGenerator.nullReturner(false))[0];", e.getMessage(),
1155 "Cannot load from char array because " +
1156 "the return value of \"NullPointerExceptionTest$NullPointerGenerator.nullReturner(boolean)\" is null");
1157 }
1158 // invokevirtual
1159 try {
1160 char val = ((char[]) (new NullPointerGenerator().returnMyNull(1, 1, (short) 1)))[0];
1161 System.out.println(val);
1162 Asserts.fail();
1163 } catch (NullPointerException e) {
1164 checkMessage(e, "char val = ((char[]) (new NullPointerGenerator().returnMyNull(1, 1, (short) 1)))[0];", e.getMessage(),
1165 "Cannot load from char array because " +
1166 "the return value of \"NullPointerExceptionTest$NullPointerGenerator.returnMyNull(double, long, short)\" is null");
1167 }
1168 // Call with array arguments.
1169 try {
1170 double val = ((double[]) returnNull(null, null, 1f))[0];
1171 System.out.println(val);
1172 Asserts.fail();
1173 } catch (NullPointerException e) {
1174 checkMessage(e, "double val = ((double[]) returnNull(null, null, 1f))[0];", e.getMessage(),
1175 "Cannot load from double array because " +
1176 "the return value of \"NullPointerExceptionTest.returnNull(String[][], int[][][], float)\" is null");
1177 }
1178 // invokespecial
1179 try {
1180 SubG g = new SubG();
1181 g.m2("Beginning");
1182 } catch (NullPointerException e) {
1183 checkMessage(e, "return super.m2(x).substring(2);", e.getMessage(),
1184 "Cannot invoke \"String.substring(int)\" because " +
1185 "the return value of \"G.m2(String)\" is null");
1186 }
1187 // invokeinterface
1188 ImplTestLoadedFromMethod(new DoubleArrayGenImpl());
1189 try {
1190 returnMeAsNull(null, 1, 'A').dag = new DoubleArrayGenImpl();
1191 Asserts.fail();
1192 } catch (NullPointerException e) {
1193 checkMessage(e, "returnMeAsNull(null, 1, 'A').dag = new DoubleArrayGenImpl();", e.getMessage(),
1194 "Cannot assign field \"dag\" because " +
1195 "the return value of \"NullPointerExceptionTest.returnMeAsNull(java.lang.Throwable, int, char)\" is null");
1196 }
1197 testMethodChasing();
1198
1199 // Mixed recursive descend.
1200 testMixedChasing();
1201 }
1202
1203 // Assure 64 parameters are printed as 'parameteri'.
1204 public String manyParameters(
1205 int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10,
1206 int i11, int i12, int i13, int i14, int i15, int i16, int i17, int i18, int i19, int i20,
1207 int i21, int i22, int i23, int i24, int i25, int i26, int i27, int i28, int i29, int i30,
1208 int i31, int i32, int i33, int i34, int i35, int i36, int i37, int i38, int i39, int i40,
1209 int i41, int i42, int i43, int i44, int i45, int i46, int i47, int i48, int i49, int i50,
1210 int i51, int i52, int i53, int i54, int i55, int i56, int i57, int i58, int i59, int i60,
1211 int i61, int i62, int i63, int i64, int i65, int i66, int i67, int i68, int i69, int i70) {
1212 String[][][][] ar5 = new String[1][1][1][1];
1213 int[][][] idx3 = new int[1][1][1];
1214 int[][] idx2 = new int[1][1];
1215 return ar5[i70]
1216 [idx2[i65][i64]]
1217 [idx3[i63][i62][i47]]
1218 [idx3[idx2[i33][i32]][i31][i17]]
1219 .substring(2);
1220 }
1221
1222 // The double placeholder takes two slots on the stack.
1223 public void testParametersTestMethod(A a, double placeholder, B b, Integer i) throws Exception {
1224 try {
1225 a.to_b.to_c.to_d.num = 99;
1226 Asserts.fail();
1227 } catch (NullPointerException e) {
1228 checkMessage(e, "a.to_b.to_c.to_d.num = 99; // to_c is null, a is a parameter.", e.getMessage(),
1229 "Cannot read field \"to_d\" because \"" +
1230 (hasDebugInfo ? "a" : "<parameter1>") + ".to_b.to_c\" is null");
1231 }
1232
1233 try {
1234 b.to_c.to_d.num = 99;
1235 Asserts.fail();
1236 } catch (NullPointerException e) {
1237 checkMessage(e, "b.to_c.to_d.num = 99; // b is null and b is a parameter.", e.getMessage(),
1238 "Cannot read field \"to_c\" because " +
1239 // We expect number '3' for the parameter.
1240 (hasDebugInfo ? "\"b\"" : "\"<parameter3>\"") + " is null");
1241 }
1242
1243
1244 try {
1245 @SuppressWarnings("unused")
1246 int my_i = i;
1247 } catch (NullPointerException e) {
1248 checkMessage(e, "int my_i = i; // i is a parameter of type Integer.", e.getMessage(),
1249 "Cannot invoke \"java.lang.Integer.intValue()\" because " +
1250 (hasDebugInfo ? "\"i\"" : "\"<parameter4>\"") + " is null");
1251 }
1252
1253 // If no debug information is available, only 64 parameters (this and i1 through i63)
1254 // will be reported in the message as 'parameteri'. Others will be reported as 'locali'.
1255 try {
1256 manyParameters(0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1257 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1258 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1259 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1260 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1261 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1262 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1263 } catch (NullPointerException e) {
1264 checkMessage(e, "return ar5[i70][idx2[i65][i64]][idx3[i63][i62][i47]][idx3[idx2[i33][i32]][i31][i17]].substring(2);", e.getMessage(),
1265 "Cannot invoke \"String.substring(int)\" because " +
1266 (hasDebugInfo ?
1267 "\"ar5[i70][idx2[i65][i64]][idx3[i63][i62][i47]][idx3[idx2[i33][i32]][i31][i17]]\"" :
1268 "\"<local71>[<local70>][<local73>[<local65>][<local64>]][<local72>[<parameter63>][<parameter62>]" +
1269 "[<parameter47>]][<local72>[<local73>[<parameter33>][<parameter32>]][<parameter31>][<parameter17>]]\"") +
1270 " is null");
1271 }
1272 }
1273
1274
1275 public void testParameters() throws Exception {
1276 A a = new A();
1277 a.to_b = new B();
1278 testParametersTestMethod(a, 0.0, null, null);
1279 }
1280
1281
1282 public void testCreation() throws Exception {
1283 // If allocated with new, the message should not be generated.
1284 Asserts.assertNull(new NullPointerException().getMessage());
1285 String msg = new String("A pointless message");
1286 Asserts.assertTrue(new NullPointerException(msg).getMessage() == msg);
1287
1288 // If fillInStackTrace is called a second time (first call is in
1289 // the constructor), the information to compute the extended
1290 // message is lost. Check we deal with this correctly.
1291
1292 // On explicit construction no message should be computed, also
1293 // after fillInStackTrace().
1294 Asserts.assertNull(new NullPointerException().fillInStackTrace().getMessage());
1295 Asserts.assertTrue(new NullPointerException(msg).fillInStackTrace().getMessage() == msg);
1296
1297 // Similar if the exception is assigned to a local.
1298 NullPointerException ex = new NullPointerException();
1299 Throwable t = ex.fillInStackTrace();
1300 Asserts.assertNull(t.getMessage());
1301
1302 ex = new NullPointerException(msg);
1303 t = ex.fillInStackTrace();
1304 Asserts.assertTrue(t.getMessage() == msg);
1305
1306 // An implicit exception should have the right message.
1307 F f = null;
1308 String expectedMessage =
1309 "Cannot assign field \"i\" because " +
1310 (hasDebugInfo ? "\"f\"" : "\"<local4>\"") + " is null";
1311 try {
1312 f.i = 17;
1313 } catch (NullPointerException e) {
1314 checkMessage(e, "f.i = 17;", e.getMessage(), expectedMessage);
1315 t = e.fillInStackTrace();
1316 }
1317 checkMessage(t, "e.fillInStackTrace()", t.getMessage(), expectedMessage);
1318
1319 // Make sure a new exception thrown while calling fillInStackTrace()
1320 // gets the correct message.
1321 ex = null;
1322 try {
1323 ex.fillInStackTrace();
1324 } catch (NullPointerException e) {
1325 checkMessage(e, "ex.fillInStackTrace()", e.getMessage(),
1326 "Cannot invoke \"java.lang.NullPointerException.fillInStackTrace()\" because " +
1327 (hasDebugInfo ? "\"ex\"" : "\"<local2>\"") + " is null");
1328 }
1329
1330 // setStackTrace does not affect computing the message.
1331 // Message and stack trace won't match, though.
1332 F f1 = null;
1333 F f2 = null;
1334 NullPointerException e1 = null;
1335 NullPointerException e2 = null;
1336 try {
1337 f1.i = 18;
1338 } catch (NullPointerException e) {
1339 checkMessage(e, "f1.i = 18;", e.getMessage(),
1340 "Cannot assign field \"i\" because " +
1341 (hasDebugInfo ? "\"f1\"" : "\"<local6>\"") + " is null");
1342 e1 = e;
1343 }
1344 try {
1345 f2.i = 19;
1346 } catch (NullPointerException e) {
1347 checkMessage(e, "f2.i = 19;", e.getMessage(),
1348 "Cannot assign field \"i\" because " +
1349 (hasDebugInfo ? "\"f2\"" : "\"<local7>\"") + " is null");
1350 e2 = e;
1351 }
1352 e1.setStackTrace(e2.getStackTrace());
1353 checkMessage(e1, "f1.i = 18;", e1.getMessage(),
1354 "Cannot assign field \"i\" because " +
1355 (hasDebugInfo ? "\"f1\"" : "\"<local6>\"") + " is null");
1356 checkMessage(e2, "f1.i = 18;", e2.getMessage(),
1357 "Cannot assign field \"i\" because " +
1358 (hasDebugInfo ? "\"f2\"" : "\"<local7>\"") + " is null");
1359
1360 // If created via reflection, the message should not be generated.
1361 ex = NullPointerException.class.getDeclaredConstructor().newInstance();
1362 Asserts.assertNull(ex.getMessage());
1363 }
1364
1365 public void testNative() throws Exception {
1366 // If NPE is thrown in a native method, the message should
1367 // not be generated.
1368 try {
1369 Array.getLength(null);
1370 Asserts.fail();
1371 } catch (NullPointerException e) {
1372 Asserts.assertNull(e.getMessage());
1373 }
1374 }
1375
1376 // Test we get the same message calling npe.getMessage() twice.
1377 @SuppressWarnings("null")
1378 public void testSameMessage() throws Exception {
1379 Object null_o = null;
1380 String expectedMsg =
1381 "Cannot invoke \"Object.hashCode()\" because " +
1382 (hasDebugInfo ? "\"null_o" : "\"<local1>") + "\" is null";
1383
1384 try {
1385 null_o.hashCode();
1386 Asserts.fail();
1387 } catch (NullPointerException e) {
1388 String msg1 = e.getMessage();
1389 checkMessage(e, "null_o.hashCode()", msg1, expectedMsg);
1390 String msg2 = e.getMessage();
1391 Asserts.assertTrue(msg1.equals(msg2));
1392 Asserts.assertTrue(msg1 == msg2);
1393 }
1394 }
1395
1396 @SuppressWarnings("null")
1397 public void testSerialization() throws Exception {
1398 // NPE without message.
1399 Object o1 = new NullPointerException();
1400 ByteArrayOutputStream bos1 = new ByteArrayOutputStream();
1401 ObjectOutputStream oos1 = new ObjectOutputStream(bos1);
1402 oos1.writeObject(o1);
1403 ByteArrayInputStream bis1 = new ByteArrayInputStream(bos1.toByteArray());
1404 ObjectInputStream ois1 = new ObjectInputStream(bis1);
1405 Exception ex1 = (Exception) ois1.readObject();
1406 Asserts.assertNull(ex1.getMessage());
1407
1408 // NPE with custom message.
1409 String msg2 = "A useless message";
1410 Object o2 = new NullPointerException(msg2);
1411 ByteArrayOutputStream bos2 = new ByteArrayOutputStream();
1412 ObjectOutputStream oos2 = new ObjectOutputStream(bos2);
1413 oos2.writeObject(o2);
1414 ByteArrayInputStream bis2 = new ByteArrayInputStream(bos2.toByteArray());
1415 ObjectInputStream ois2 = new ObjectInputStream(bis2);
1416 Exception ex2 = (Exception) ois2.readObject();
1417 Asserts.assertEquals(ex2.getMessage(), msg2);
1418
1419 // NPE with generated message.
1420 Object null_o3 = null;
1421 Object o3 = null;
1422 String msg3 = null;
1423 try {
1424 int hc = null_o3.hashCode();
1425 System.out.println(hc);
1426 Asserts.fail();
1427 } catch (NullPointerException npe3) {
1428 o3 = npe3;
1429 msg3 = npe3.getMessage();
1430 checkMessage(npe3, "int hc = null_o3.hashCode();", msg3,
1431 "Cannot invoke \"Object.hashCode()\" because " +
1432 (hasDebugInfo ? "\"null_o3\"" : "\"<local14>\"") + " is null");
1433 }
1434 ByteArrayOutputStream bos3 = new ByteArrayOutputStream();
1435 ObjectOutputStream oos3 = new ObjectOutputStream(bos3);
1436 oos3.writeObject(o3);
1437 ByteArrayInputStream bis3 = new ByteArrayInputStream(bos3.toByteArray());
1438 ObjectInputStream ois3 = new ObjectInputStream(bis3);
1439 Exception ex3 = (Exception) ois3.readObject();
1440 // It was decided that getMessage should not store the
1441 // message in Throwable.detailMessage or implement writeReplace(),
1442 // thus it can not be recovered by serialization.
1443 //Asserts.assertEquals(ex3.getMessage(), msg3);
1444 Asserts.assertEquals(ex3.getMessage(), null);
1445 }
1446
1447 static int index17 = 17;
1448 int getIndex17() { return 17; };
1449
1450 @SuppressWarnings({ "unused", "null" })
1451 public void testComplexMessages() {
1452 try {
1453 staticLongArray[0][0] = 2L;
1454 Asserts.fail();
1455 } catch (NullPointerException e) {
1456 checkMessage(e, "staticLongArray[0][0] = 2L;", e.getMessage(),
1457 "Cannot store to long array because " +
1458 "\"NullPointerExceptionTest.staticLongArray[0]\" is null");
1459 }
1460
1461 try {
1462 NullPointerExceptionTest obj = this;
1463 Object val = obj.dag.getArray().clone();
1464 Asserts.assertNull(val);
1465 Asserts.fail();
1466 } catch (NullPointerException e) {
1467 checkMessage(e, "Object val = obj.dag.getArray().clone();", e.getMessage(),
1468 "Cannot invoke \"NullPointerExceptionTest$DoubleArrayGen.getArray()\" because " +
1469 (hasDebugInfo ? "\"obj" : "\"<local1>") + ".dag\" is null");
1470 }
1471 try {
1472 int indexes[] = new int[1];
1473 NullPointerExceptionTest[] objs = new NullPointerExceptionTest[] {this};
1474 Object val = objs[indexes[0]].nullInstanceField.returnNull(null, null, 1f);
1475 Asserts.assertNull(val);
1476 Asserts.fail();
1477 } catch (NullPointerException e) {
1478 checkMessage(e, "Object val = objs[indexes[0]].nullInstanceField.returnNull(null, null, 1f);", e.getMessage(),
1479 "Cannot invoke \"NullPointerExceptionTest.returnNull(String[][], int[][][], float)\" because " +
1480 (hasDebugInfo ? "\"objs[indexes" : "\"<local2>[<local1>") + "[0]].nullInstanceField\" is null");
1481 }
1482
1483 try {
1484 int indexes[] = new int[1];
1485 NullPointerExceptionTest[][] objs =
1486 new NullPointerExceptionTest[][] {new NullPointerExceptionTest[] {this}};
1487 synchronized (objs[indexes[0]][0].nullInstanceField) {
1488 Asserts.fail();
1489 }
1490 } catch (NullPointerException e) {
1491 checkMessage(e, "synchronized (objs[indexes[0]][0].nullInstanceField) { ... }", e.getMessage(),
1492 "Cannot enter synchronized block because " +
1493 (hasDebugInfo ? "\"objs[indexes" : "\"<local2>[<local1>" ) + "[0]][0].nullInstanceField\" is null");
1494 }
1495
1496 try {
1497 // If we can get the value from more than one bci, we cannot know which one
1498 // is null. Make sure we don't print the wrong value.
1499 String s = null;
1500 @SuppressWarnings("unused")
1501 byte[] val = (rng.nextDouble() < 0.5 ? s : (new String[1])[0]).getBytes();
1502 } catch (NullPointerException e) {
1503 checkMessage(e, "byte[] val = (rng.nextDouble() < 0.5 ? s : (new String[1])[0]).getBytes();", e.getMessage(),
1504 "Cannot invoke \"String.getBytes()\"");
1505 }
1506
1507 try {
1508 // If we can get the value from more than one bci, we cannot know which one
1509 // is null. Make sure we don't print the wrong value. Also make sure if
1510 // we don't print the failed action we don't print a string at all.
1511 int[][] a = new int[1][];
1512 int[][] b = new int[2][];
1513 long index = 0;
1514 @SuppressWarnings("unused")
1515 int val = (rng.nextDouble() < 0.5 ? a[(int)index] : b[(int)index])[13];
1516 } catch (NullPointerException e) {
1517 checkMessage(e, "int val = (rng.nextDouble() < 0.5 ? a[(int)index] : b[(int)index])[13]", e.getMessage(),
1518 "Cannot load from int array");
1519 }
1520
1521 try {
1522 // If we can get the value from more than one bci, we cannot know which one
1523 // is null. Make sure we don't print the wrong value. Also make sure if
1524 // we don't print the failed action we don't print a string at all.
1525 int[][] a = new int[1][];
1526 int[][] b = new int[2][];
1527 long index = 0;
1528 int val = (rng.nextDouble() < 0.5 ? a : b)[(int)index][13];
1529 } catch (NullPointerException e) {
1530 checkMessage(e, "int val = (rng.nextDouble() < 0.5 ? a : b)[(int)index][13]", e.getMessage(),
1531 "Cannot load from int array because \"<array>[...]\" is null");
1532 }
1533
1534 try {
1535 C c1 = new C();
1536 C c2 = new C();
1537 (rng.nextDouble() < 0.5 ? c1 : c2).to_d.num = 77;
1538 } catch (NullPointerException e) {
1539 checkMessage(e, "(rng.nextDouble() < 0.5 ? c1 : c2).to_d.num = 77;", e.getMessage(),
1540 "Cannot assign field \"num\" because \"to_d\" is null");
1541 }
1542
1543 // Static variable as array index.
1544 try {
1545 staticLongArray[index17][0] = 2L;
1546 } catch (NullPointerException e) {
1547 checkMessage(e, "staticLongArray[index17][0] = 2L;", e.getMessage(),
1548 "Cannot store to long array because " +
1549 "\"NullPointerExceptionTest.staticLongArray[NullPointerExceptionTest.index17]\" is null");
1550 }
1551
1552 // Method call as array index.
1553 try {
1554 staticLongArray[getIndex17()][0] = 2L;
1555 } catch (NullPointerException e) {
1556 checkMessage(e, "staticLongArray[getIndex17()][0] = 2L;", e.getMessage(),
1557 "Cannot store to long array because " +
1558 "\"NullPointerExceptionTest.staticLongArray[NullPointerExceptionTest.getIndex17()]\" is null");
1559 }
1560
1561 // Unboxing.
1562 Integer a = null;
1563 try {
1564 int b = a;
1565 } catch (NullPointerException e) {
1566 checkMessage(e, "Integer a = null; int b = a;", e.getMessage(),
1567 "Cannot invoke \"java.lang.Integer.intValue()\" because " +
1568 (hasDebugInfo ? "\"a\"" : "\"<local1>\"") + " is null");
1569 }
1570
1571 // Unboxing by hand. Has the same message as above.
1572 try {
1573 int b = a.intValue();
1574 } catch (NullPointerException e) {
1575 checkMessage(e, "Integer a = null; int b = a.intValue();", e.getMessage(),
1576 "Cannot invoke \"java.lang.Integer.intValue()\" because " +
1577 (hasDebugInfo ? "\"a\"" : "\"<local1>\"") + " is null");
1578 }
1579 }
1580
1581 // Generates:
1582 // class E implements E0 {
1583 // public int throwNPE(F f) {
1584 // return f.i;
1585 // }
1586 // public void throwNPE_reuseStackSlot1(String s1) {
1587 // System.out.println(s1.substring(1));
1588 // String s1_2 = null; // Reuses slot 1.
1589 // System.out.println(s1_2.substring(1));
1590 // }
1591 // public void throwNPE_reuseStackSlot4(String s1, String s2, String s3, String s4) {
1592 // System.out.println(s4.substring(1));
1593 // String s4_2 = null; // Reuses slot 4.
1594 // System.out.println(s4_2.substring(1));
1595 // }
1596 // }
1597 //
1598 // This code was adapted from output of
1599 // java org.objectweb.asm.util.ASMifier E0.class
1600 static byte[] generateTestClass() {
1601 ClassWriter cw = new ClassWriter(0);
1602 MethodVisitor mv;
1603
1604 cw.visit(50, ACC_SUPER, "E", null, "java/lang/Object", new String[] { "E0" });
1605
1606 {
1607 mv = cw.visitMethod(0, "<init>", "()V", null, null);
1608 mv.visitCode();
1609 mv.visitVarInsn(ALOAD, 0);
1610 mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
1611 mv.visitInsn(RETURN);
1612 mv.visitMaxs(1, 1);
1613 mv.visitEnd();
1614 }
1615
1616 {
1617 mv = cw.visitMethod(ACC_PUBLIC, "throwNPE", "(LF;)I", null, null);
1618 mv.visitCode();
1619 Label label0 = new Label();
1620 mv.visitLabel(label0);
1621 mv.visitLineNumber(118, label0);
1622 mv.visitVarInsn(ALOAD, 1);
1623 mv.visitFieldInsn(GETFIELD, "F", "i", "I");
1624 mv.visitInsn(IRETURN);
1625 Label label1 = new Label();
1626 mv.visitLabel(label1);
1627 mv.visitLocalVariable("this", "LE;", null, label0, label1, 0);
1628 mv.visitLocalVariable("f", "LE;", null, label0, label1, 1);
1629 mv.visitMaxs(1, 2);
1630 mv.visitEnd();
1631 }
1632
1633 {
1634 mv = cw.visitMethod(ACC_PUBLIC, "throwNPE_reuseStackSlot1", "(Ljava/lang/String;)V", null, null);
1635 mv.visitCode();
1636 Label label0 = new Label();
1637 mv.visitLabel(label0);
1638 mv.visitLineNumber(7, label0);
1639 mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
1640 mv.visitVarInsn(ALOAD, 1);
1641 mv.visitInsn(ICONST_1);
1642 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "substring", "(I)Ljava/lang/String;", false);
1643 mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
1644 Label label1 = new Label();
1645 mv.visitLabel(label1);
1646 mv.visitLineNumber(8, label1);
1647 mv.visitInsn(ACONST_NULL);
1648 mv.visitVarInsn(ASTORE, 1);
1649 Label label2 = new Label();
1650 mv.visitLabel(label2);
1651 mv.visitLineNumber(9, label2);
1652 mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
1653 mv.visitVarInsn(ALOAD, 1);
1654 mv.visitInsn(ICONST_1);
1655 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "substring", "(I)Ljava/lang/String;", false);
1656 mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
1657 Label label3 = new Label();
1658 mv.visitLabel(label3);
1659 mv.visitLineNumber(10, label3);
1660 mv.visitInsn(RETURN);
1661 mv.visitMaxs(3, 3);
1662 mv.visitEnd();
1663 }
1664
1665 {
1666 mv = cw.visitMethod(ACC_PUBLIC, "throwNPE_reuseStackSlot4", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", null, null);
1667 mv.visitCode();
1668 Label label0 = new Label();
1669 mv.visitLabel(label0);
1670 mv.visitLineNumber(12, label0);
1671 mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
1672 mv.visitVarInsn(ALOAD, 4);
1673 mv.visitInsn(ICONST_1);
1674 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "substring", "(I)Ljava/lang/String;", false);
1675 mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
1676 Label label1 = new Label();
1677 mv.visitLabel(label1);
1678 mv.visitLineNumber(13, label1);
1679 mv.visitInsn(ACONST_NULL);
1680 mv.visitVarInsn(ASTORE, 4);
1681 Label label2 = new Label();
1682 mv.visitLabel(label2);
1683 mv.visitLineNumber(14, label2);
1684 mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
1685 mv.visitVarInsn(ALOAD, 4);
1686 mv.visitInsn(ICONST_1);
1687 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "substring", "(I)Ljava/lang/String;", false);
1688 mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
1689 Label label3 = new Label();
1690 mv.visitLabel(label3);
1691 mv.visitLineNumber(15, label3);
1692 mv.visitInsn(RETURN);
1693 mv.visitMaxs(3, 6);
1694 mv.visitEnd();
1695 }
1696
1697 cw.visitEnd();
1698
1699 return cw.toByteArray();
1700 }
1701
1702 // Assign to a parameter.
1703 // Without debug information, this will print "parameter1" if a NPE
1704 // is raised in the first line because null was passed to the method.
1705 // It will print "local1" if a NPE is raised in line three.
1706 public void assign_to_parameter(String s1) {
1707 System.out.println(s1.substring(1));
1708 s1 = null;
1709 System.out.println(s1.substring(2));
1710 }
1711
1712 // Tests that a class generated on the fly is handled properly.
1713 public void testGeneratedCode() throws Exception {
1714 byte[] classBytes = generateTestClass();
1715 Lookup lookup = lookup();
1716 Class<?> clazz = lookup.defineClass(classBytes);
1717 E0 e = (E0) clazz.getDeclaredConstructor().newInstance();
1718 try {
1719 e.throwNPE(null);
1720 } catch (NullPointerException ex) {
1721 checkMessage(ex, "return f.i;",
1722 ex.getMessage(),
1723 "Cannot read field \"i\" because \"f\" is null");
1724 }
1725
1726 // Optimized bytecode can reuse local variable slots for several
1727 // local variables.
1728 // If there is no variable name information, we print 'parameteri'
1729 // if a parameter maps to a local slot. Once a local slot has been
1730 // written, we don't know any more whether it was written as the
1731 // corresponding parameter, or whether another local has been
1732 // mapped to the slot. So we don't want to print 'parameteri' any
1733 // more, but 'locali'. Similary for 'this'.
1734
1735 // Expect message saying "parameter0".
1736 try {
1737 e.throwNPE_reuseStackSlot1(null);
1738 } catch (NullPointerException ex) {
1739 checkMessage(ex, "s1.substring(1)",
1740 ex.getMessage(),
1741 "Cannot invoke \"String.substring(int)\" because \"<parameter1>\" is null");
1742 }
1743 // Expect message saying "local0".
1744 try {
1745 e.throwNPE_reuseStackSlot1("aa");
1746 } catch (NullPointerException ex) {
1747 checkMessage(ex, "s1_2.substring(1)",
1748 ex.getMessage(),
1749 "Cannot invoke \"String.substring(int)\" because \"<local1>\" is null");
1750 }
1751 // Expect message saying "parameter4".
1752 try {
1753 e.throwNPE_reuseStackSlot4("aa", "bb", "cc", null);
1754 } catch (NullPointerException ex) {
1755 checkMessage(ex, "s4.substring(1)",
1756 ex.getMessage(),
1757 "Cannot invoke \"String.substring(int)\" because \"<parameter4>\" is null");
1758 }
1759 // Expect message saying "local4".
1760 try {
1761 e.throwNPE_reuseStackSlot4("aa", "bb", "cc", "dd");
1762 } catch (NullPointerException ex) {
1763 checkMessage(ex, "s4_2.substring(1)",
1764 ex.getMessage(),
1765 "Cannot invoke \"String.substring(int)\" because \"<local4>\" is null");
1766 }
1767
1768 // Unfortunately, with the fix for optimized code as described above
1769 // we don't write 'parameteri' any more after the parameter variable
1770 // has been assigned.
1771
1772 if (!hasDebugInfo) {
1773 // Expect message saying "parameter1".
1774 try {
1775 assign_to_parameter(null);
1776 } catch (NullPointerException ex) {
1777 checkMessage(ex, "s1.substring(1)",
1778 ex.getMessage(),
1779 "Cannot invoke \"String.substring(int)\" because \"<parameter1>\" is null");
1780 }
1781 // The message says "local1" although "parameter1" would be correct.
1782 try {
1783 assign_to_parameter("aaa");
1784 } catch (NullPointerException ex) {
1785 checkMessage(ex, "s1.substring(2)",
1786 ex.getMessage(),
1787 "Cannot invoke \"String.substring(int)\" because \"<local1>\" is null");
1788 }
1789 }
1790 }
1791 }
1792
1793 // Helper interface for test cases needed for generateTestClass().
1794 interface E0 {
1795 public int throwNPE(F f);
1796 public void throwNPE_reuseStackSlot1(String s1);
1797 public void throwNPE_reuseStackSlot4(String s1, String s2, String s3, String s4);
1798 }
1799
1800 // Helper class for test cases needed for generateTestClass().
1801 class F {
1802 int i;
1803 }
1804
1805 // For invokespecial test cases.
1806 class G {
1807 public String m2(String x) {
1808 return null;
1809 }
1810
1811 // This generates the following class:
1812 //
1813 // class Sub2G extends G {
1814 // public String m2(String x) {
1815 // super = null; // Possible in raw bytecode.
1816 // return super.m2(x).substring(2); // Uses invokespecial.
1817 // }
1818 // }
1819 //
1820 // This code was adapted from output of
1821 // java org.objectweb.asm.util.ASMifier Sub2G.class
1822 static byte[] generateSub2GTestClass() {
1823 ClassWriter cw = new ClassWriter(0);
1824 MethodVisitor mv;
1825
1826 cw.visit(50, ACC_SUPER, "Sub2G", null, "G", null);
1827
1828 {
1829 mv = cw.visitMethod(0, "<init>", "()V", null, null);
1830 mv.visitCode();
1831 mv.visitVarInsn(ALOAD, 0);
1832 mv.visitMethodInsn(INVOKESPECIAL, "G", "<init>", "()V", false);
1833 mv.visitInsn(RETURN);
1834 mv.visitMaxs(1, 1);
1835 mv.visitEnd();
1836 }
1837 {
1838 mv = cw.visitMethod(ACC_PUBLIC, "m2", "(Ljava/lang/String;)Ljava/lang/String;", null, null);
1839 mv.visitCode();
1840 mv.visitInsn(ACONST_NULL); // Will cause NPE.
1841 mv.visitVarInsn(ALOAD, 1);
1842 mv.visitMethodInsn(INVOKESPECIAL, "G", "m2", "(Ljava/lang/String;)Ljava/lang/String;", false);
1843 mv.visitInsn(ICONST_2);
1844 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "substring", "(I)Ljava/lang/String;", false);
1845 mv.visitInsn(ARETURN);
1846 mv.visitMaxs(2, 2);
1847 mv.visitEnd();
1848 }
1849
1850 cw.visitEnd();
1851
1852 return cw.toByteArray();
1853 }
1854 }
1855 class SubG extends G {
1856 public String m2(String x) {
1857 return super.m2(x).substring(2);
1858 }
1859 }