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