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