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