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