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