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 8248476 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 8248476 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 the stack trace was set by the user, the message should not be 1285 // created. 1286 // This holds for explicitly crated NPEs, but also for implicilty 1287 // thrown ones. 1288 System.out.println(new NullPointerException().fillInStackTrace().getMessage()); 1289 System.out.println(new NullPointerException(msg).fillInStackTrace().getMessage()); 1290 1291 Asserts.assertNull(new NullPointerException().fillInStackTrace().getMessage()); 1292 Asserts.assertTrue(new NullPointerException(msg).fillInStackTrace().getMessage() == msg); 1293 1294 NullPointerException ex = new NullPointerException(); 1295 Throwable t = ex.fillInStackTrace(); 1296 1297 Asserts.assertNull(t.getMessage()); 1298 1299 ex = new NullPointerException(msg); 1300 t = ex.fillInStackTrace(); 1301 Asserts.assertTrue(t.getMessage() == msg); 1302 1303 F f = null; 1304 try { 1305 f.i = 17; 1306 } catch (NullPointerException e) { 1307 checkMessage(e, "f.i = 17;", e.getMessage(), 1308 "Cannot assign field \"i\" because " + 1309 (hasDebugInfo ? "\"f\"" : "\"<local4>\"") + " is null"); 1310 t = e.fillInStackTrace(); 1311 } 1312 checkMessage(t, "e.fillInStackTrace()", t.getMessage(), null); 1313 1314 // Make sure a new exception thrown when calling fillInStackTrace() 1315 // gets the correct message. 1316 ex = null; 1317 try { 1318 ex.fillInStackTrace(); 1319 } catch (NullPointerException e) { 1320 checkMessage(e, "ex.fillInStackTrace()", e.getMessage(), 1321 "Cannot invoke \"java.lang.NullPointerException.fillInStackTrace()\" because " + 1322 (hasDebugInfo ? "\"ex\"" : "\"<local2>\"") + " is null"); 1323 } 1324 1325 // setStackTrace does not affect computing the message. 1326 // Message and stack trace won't match, though. 1327 F f1 = null; 1328 F f2 = null; 1329 NullPointerException e1 = null; 1330 NullPointerException e2 = null; 1331 try { 1332 f1.i = 18; 1333 } catch (NullPointerException e) { 1334 checkMessage(e, "f1.i = 18;", e.getMessage(), 1335 "Cannot assign field \"i\" because " + 1336 (hasDebugInfo ? "\"f1\"" : "\"<local5>\"") + " is null"); 1337 e1 = e; 1338 } 1339 try { 1340 f2.i = 19; 1341 } catch (NullPointerException e) { 1342 checkMessage(e, "f2.i = 19;", e.getMessage(), 1343 "Cannot assign field \"i\" because " + 1344 (hasDebugInfo ? "\"f2\"" : "\"<local6>\"") + " is null"); 1345 e2 = e; 1346 } 1347 e1.setStackTrace(e2.getStackTrace()); 1348 checkMessage(e1, "f1.i = 18;", e1.getMessage(), 1349 "Cannot assign field \"i\" because " + 1350 (hasDebugInfo ? "\"f1\"" : "\"<local5>\"") + " is null"); 1351 1352 // If created via reflection, the message should not be generated. 1353 ex = NullPointerException.class.getDeclaredConstructor().newInstance(); 1354 Asserts.assertNull(ex.getMessage()); 1355 } 1356 1357 public void testNative() throws Exception { 1358 // If NPE is thrown in a native method, the message should 1359 // not be generated. 1360 try { 1361 Class.forName(null); 1362 Asserts.fail(); 1363 } catch (NullPointerException e) { 1364 Asserts.assertNull(e.getMessage()); 1365 } 1366 1367 } 1368 1369 // Test we get the same message calling npe.getMessage() twice. 1370 @SuppressWarnings("null") 1371 public void testSameMessage() throws Exception { 1372 Object null_o = null; 1373 String expectedMsg = 1374 "Cannot invoke \"Object.hashCode()\" because " + 1375 (hasDebugInfo ? "\"null_o" : "\"<local1>") + "\" is null"; 1376 1377 try { 1378 null_o.hashCode(); 1379 Asserts.fail(); 1380 } catch (NullPointerException e) { 1381 String msg1 = e.getMessage(); 1382 checkMessage(e, "null_o.hashCode()", msg1, expectedMsg); 1383 String msg2 = e.getMessage(); 1384 Asserts.assertTrue(msg1.equals(msg2)); 1385 // It was decided that getMessage should generate the 1386 // message anew on every call, so this does not hold. 1387 //Asserts.assertTrue(msg1 == msg2); 1388 Asserts.assertFalse(msg1 == msg2); 1389 } 1390 } 1391 1392 @SuppressWarnings("null") 1393 public void testSerialization() throws Exception { 1394 // NPE without message. 1395 Object o1 = new NullPointerException(); 1396 ByteArrayOutputStream bos1 = new ByteArrayOutputStream(); 1397 ObjectOutputStream oos1 = new ObjectOutputStream(bos1); 1398 oos1.writeObject(o1); 1399 ByteArrayInputStream bis1 = new ByteArrayInputStream(bos1.toByteArray()); 1400 ObjectInputStream ois1 = new ObjectInputStream(bis1); 1401 Exception ex1 = (Exception) ois1.readObject(); 1402 Asserts.assertNull(ex1.getMessage()); 1403 1404 // NPE with custom message. 1405 String msg2 = "A useless message"; 1406 Object o2 = new NullPointerException(msg2); 1407 ByteArrayOutputStream bos2 = new ByteArrayOutputStream(); 1408 ObjectOutputStream oos2 = new ObjectOutputStream(bos2); 1409 oos2.writeObject(o2); 1410 ByteArrayInputStream bis2 = new ByteArrayInputStream(bos2.toByteArray()); 1411 ObjectInputStream ois2 = new ObjectInputStream(bis2); 1412 Exception ex2 = (Exception) ois2.readObject(); 1413 Asserts.assertEquals(ex2.getMessage(), msg2); 1414 1415 // NPE with generated message. 1416 Object null_o3 = null; 1417 Object o3 = null; 1418 String msg3 = null; 1419 try { 1420 int hc = null_o3.hashCode(); 1421 System.out.println(hc); 1422 Asserts.fail(); 1423 } catch (NullPointerException npe3) { 1424 o3 = npe3; 1425 msg3 = npe3.getMessage(); 1426 checkMessage(npe3, "int hc = null_o3.hashCode();", msg3, 1427 "Cannot invoke \"Object.hashCode()\" because " + 1428 (hasDebugInfo ? "\"null_o3\"" : "\"<local14>\"") + " is null"); 1429 } 1430 ByteArrayOutputStream bos3 = new ByteArrayOutputStream(); 1431 ObjectOutputStream oos3 = new ObjectOutputStream(bos3); 1432 oos3.writeObject(o3); 1433 ByteArrayInputStream bis3 = new ByteArrayInputStream(bos3.toByteArray()); 1434 ObjectInputStream ois3 = new ObjectInputStream(bis3); 1435 Exception ex3 = (Exception) ois3.readObject(); 1436 // It was decided that getMessage should not store the 1437 // message in Throwable.detailMessage or implement writeReplace(), 1438 // thus it can not be recovered by serialization. 1439 //Asserts.assertEquals(ex3.getMessage(), msg3); 1440 Asserts.assertEquals(ex3.getMessage(), null); 1441 } 1442 1443 static int index17 = 17; 1444 int getIndex17() { return 17; }; 1445 1446 @SuppressWarnings({ "unused", "null" }) 1447 public void testComplexMessages() { 1448 try { 1449 staticLongArray[0][0] = 2L; 1450 Asserts.fail(); 1451 } catch (NullPointerException e) { 1452 checkMessage(e, "staticLongArray[0][0] = 2L;", e.getMessage(), 1453 "Cannot store to long array because " + 1454 "\"NullPointerExceptionTest.staticLongArray[0]\" is null"); 1455 } 1456 1457 try { 1458 NullPointerExceptionTest obj = this; 1459 Object val = obj.dag.getArray().clone(); 1460 Asserts.assertNull(val); 1461 Asserts.fail(); 1462 } catch (NullPointerException e) { 1463 checkMessage(e, "Object val = obj.dag.getArray().clone();", e.getMessage(), 1464 "Cannot invoke \"NullPointerExceptionTest$DoubleArrayGen.getArray()\" because " + 1465 (hasDebugInfo ? "\"obj" : "\"<local1>") + ".dag\" is null"); 1466 } 1467 try { 1468 int indexes[] = new int[1]; 1469 NullPointerExceptionTest[] objs = new NullPointerExceptionTest[] {this}; 1470 Object val = objs[indexes[0]].nullInstanceField.returnNull(null, null, 1f); 1471 Asserts.assertNull(val); 1472 Asserts.fail(); 1473 } catch (NullPointerException e) { 1474 checkMessage(e, "Object val = objs[indexes[0]].nullInstanceField.returnNull(null, null, 1f);", e.getMessage(), 1475 "Cannot invoke \"NullPointerExceptionTest.returnNull(String[][], int[][][], float)\" because " + 1476 (hasDebugInfo ? "\"objs[indexes" : "\"<local2>[<local1>") + "[0]].nullInstanceField\" is null"); 1477 } 1478 1479 try { 1480 int indexes[] = new int[1]; 1481 NullPointerExceptionTest[][] objs = 1482 new NullPointerExceptionTest[][] {new NullPointerExceptionTest[] {this}}; 1483 synchronized (objs[indexes[0]][0].nullInstanceField) { 1484 Asserts.fail(); 1485 } 1486 } catch (NullPointerException e) { 1487 checkMessage(e, "synchronized (objs[indexes[0]][0].nullInstanceField) { ... }", e.getMessage(), 1488 "Cannot enter synchronized block because " + 1489 (hasDebugInfo ? "\"objs[indexes" : "\"<local2>[<local1>" ) + "[0]][0].nullInstanceField\" is null"); 1490 } 1491 1492 try { 1493 // If we can get the value from more than one bci, we cannot know which one 1494 // is null. Make sure we don't print the wrong value. 1495 String s = null; 1496 @SuppressWarnings("unused") 1497 byte[] val = (rng.nextDouble() < 0.5 ? s : (new String[1])[0]).getBytes(); 1498 } catch (NullPointerException e) { 1499 checkMessage(e, "byte[] val = (rng.nextDouble() < 0.5 ? s : (new String[1])[0]).getBytes();", e.getMessage(), 1500 "Cannot invoke \"String.getBytes()\""); 1501 } 1502 1503 try { 1504 // If we can get the value from more than one bci, we cannot know which one 1505 // is null. Make sure we don't print the wrong value. Also make sure if 1506 // we don't print the failed action we don't print a string at all. 1507 int[][] a = new int[1][]; 1508 int[][] b = new int[2][]; 1509 long index = 0; 1510 @SuppressWarnings("unused") 1511 int val = (rng.nextDouble() < 0.5 ? a[(int)index] : b[(int)index])[13]; 1512 } catch (NullPointerException e) { 1513 checkMessage(e, "int val = (rng.nextDouble() < 0.5 ? a[(int)index] : b[(int)index])[13]", e.getMessage(), 1514 "Cannot load from int array"); 1515 } 1516 1517 try { 1518 // If we can get the value from more than one bci, we cannot know which one 1519 // is null. Make sure we don't print the wrong value. Also make sure if 1520 // we don't print the failed action we don't print a string at all. 1521 int[][] a = new int[1][]; 1522 int[][] b = new int[2][]; 1523 long index = 0; 1524 int val = (rng.nextDouble() < 0.5 ? a : b)[(int)index][13]; 1525 } catch (NullPointerException e) { 1526 checkMessage(e, "int val = (rng.nextDouble() < 0.5 ? a : b)[(int)index][13]", e.getMessage(), 1527 "Cannot load from int array because \"<array>[...]\" is null"); 1528 } 1529 1530 try { 1531 C c1 = new C(); 1532 C c2 = new C(); 1533 (rng.nextDouble() < 0.5 ? c1 : c2).to_d.num = 77; 1534 } catch (NullPointerException e) { 1535 checkMessage(e, "(rng.nextDouble() < 0.5 ? c1 : c2).to_d.num = 77;", e.getMessage(), 1536 "Cannot assign field \"num\" because \"to_d\" is null"); 1537 } 1538 1539 // Static variable as array index. 1540 try { 1541 staticLongArray[index17][0] = 2L; 1542 } catch (NullPointerException e) { 1543 checkMessage(e, "staticLongArray[index17][0] = 2L;", e.getMessage(), 1544 "Cannot store to long array because " + 1545 "\"NullPointerExceptionTest.staticLongArray[NullPointerExceptionTest.index17]\" is null"); 1546 } 1547 1548 // Method call as array index. 1549 try { 1550 staticLongArray[getIndex17()][0] = 2L; 1551 } catch (NullPointerException e) { 1552 checkMessage(e, "staticLongArray[getIndex17()][0] = 2L;", e.getMessage(), 1553 "Cannot store to long array because " + 1554 "\"NullPointerExceptionTest.staticLongArray[NullPointerExceptionTest.getIndex17()]\" is null"); 1555 } 1556 1557 // Unboxing. 1558 Integer a = null; 1559 try { 1560 int b = a; 1561 } catch (NullPointerException e) { 1562 checkMessage(e, "Integer a = null; int b = a;", e.getMessage(), 1563 "Cannot invoke \"java.lang.Integer.intValue()\" because " + 1564 (hasDebugInfo ? "\"a\"" : "\"<local1>\"") + " is null"); 1565 } 1566 1567 // Unboxing by hand. Has the same message as above. 1568 try { 1569 int b = a.intValue(); 1570 } catch (NullPointerException e) { 1571 checkMessage(e, "Integer a = null; int b = a.intValue();", e.getMessage(), 1572 "Cannot invoke \"java.lang.Integer.intValue()\" because " + 1573 (hasDebugInfo ? "\"a\"" : "\"<local1>\"") + " is null"); 1574 } 1575 } 1576 1577 // Generates: 1578 // class E implements E0 { 1579 // public int throwNPE(F f) { 1580 // return f.i; 1581 // } 1582 // public void throwNPE_reuseStackSlot1(String s1) { 1583 // System.out.println(s1.substring(1)); 1584 // String s1_2 = null; // Reuses slot 1. 1585 // System.out.println(s1_2.substring(1)); 1586 // } 1587 // public void throwNPE_reuseStackSlot4(String s1, String s2, String s3, String s4) { 1588 // System.out.println(s4.substring(1)); 1589 // String s4_2 = null; // Reuses slot 4. 1590 // System.out.println(s4_2.substring(1)); 1591 // } 1592 // } 1593 // 1594 // This code was adapted from output of 1595 // java jdk.internal.org.objectweb.asm.util.ASMifier E0.class 1596 static byte[] generateTestClass() { 1597 ClassWriter cw = new ClassWriter(0); 1598 MethodVisitor mv; 1599 1600 cw.visit(50, ACC_SUPER, "E", null, "java/lang/Object", new String[] { "E0" }); 1601 1602 { 1603 mv = cw.visitMethod(0, "<init>", "()V", null, null); 1604 mv.visitCode(); 1605 mv.visitVarInsn(ALOAD, 0); 1606 mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false); 1607 mv.visitInsn(RETURN); 1608 mv.visitMaxs(1, 1); 1609 mv.visitEnd(); 1610 } 1611 1612 { 1613 mv = cw.visitMethod(ACC_PUBLIC, "throwNPE", "(LF;)I", null, null); 1614 mv.visitCode(); 1615 Label label0 = new Label(); 1616 mv.visitLabel(label0); 1617 mv.visitLineNumber(118, label0); 1618 mv.visitVarInsn(ALOAD, 1); 1619 mv.visitFieldInsn(GETFIELD, "F", "i", "I"); 1620 mv.visitInsn(IRETURN); 1621 Label label1 = new Label(); 1622 mv.visitLabel(label1); 1623 mv.visitLocalVariable("this", "LE;", null, label0, label1, 0); 1624 mv.visitLocalVariable("f", "LE;", null, label0, label1, 1); 1625 mv.visitMaxs(1, 2); 1626 mv.visitEnd(); 1627 } 1628 1629 { 1630 mv = cw.visitMethod(ACC_PUBLIC, "throwNPE_reuseStackSlot1", "(Ljava/lang/String;)V", null, null); 1631 mv.visitCode(); 1632 Label label0 = new Label(); 1633 mv.visitLabel(label0); 1634 mv.visitLineNumber(7, label0); 1635 mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); 1636 mv.visitVarInsn(ALOAD, 1); 1637 mv.visitInsn(ICONST_1); 1638 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "substring", "(I)Ljava/lang/String;", false); 1639 mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); 1640 Label label1 = new Label(); 1641 mv.visitLabel(label1); 1642 mv.visitLineNumber(8, label1); 1643 mv.visitInsn(ACONST_NULL); 1644 mv.visitVarInsn(ASTORE, 1); 1645 Label label2 = new Label(); 1646 mv.visitLabel(label2); 1647 mv.visitLineNumber(9, label2); 1648 mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); 1649 mv.visitVarInsn(ALOAD, 1); 1650 mv.visitInsn(ICONST_1); 1651 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "substring", "(I)Ljava/lang/String;", false); 1652 mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); 1653 Label label3 = new Label(); 1654 mv.visitLabel(label3); 1655 mv.visitLineNumber(10, label3); 1656 mv.visitInsn(RETURN); 1657 mv.visitMaxs(3, 3); 1658 mv.visitEnd(); 1659 } 1660 1661 { 1662 mv = cw.visitMethod(ACC_PUBLIC, "throwNPE_reuseStackSlot4", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", null, null); 1663 mv.visitCode(); 1664 Label label0 = new Label(); 1665 mv.visitLabel(label0); 1666 mv.visitLineNumber(12, label0); 1667 mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); 1668 mv.visitVarInsn(ALOAD, 4); 1669 mv.visitInsn(ICONST_1); 1670 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "substring", "(I)Ljava/lang/String;", false); 1671 mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); 1672 Label label1 = new Label(); 1673 mv.visitLabel(label1); 1674 mv.visitLineNumber(13, label1); 1675 mv.visitInsn(ACONST_NULL); 1676 mv.visitVarInsn(ASTORE, 4); 1677 Label label2 = new Label(); 1678 mv.visitLabel(label2); 1679 mv.visitLineNumber(14, label2); 1680 mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); 1681 mv.visitVarInsn(ALOAD, 4); 1682 mv.visitInsn(ICONST_1); 1683 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "substring", "(I)Ljava/lang/String;", false); 1684 mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); 1685 Label label3 = new Label(); 1686 mv.visitLabel(label3); 1687 mv.visitLineNumber(15, label3); 1688 mv.visitInsn(RETURN); 1689 mv.visitMaxs(3, 6); 1690 mv.visitEnd(); 1691 } 1692 1693 cw.visitEnd(); 1694 1695 return cw.toByteArray(); 1696 } 1697 1698 // Assign to a parameter. 1699 // Without debug information, this will print "parameter1" if a NPE 1700 // is raised in the first line because null was passed to the method. 1701 // It will print "local1" if a NPE is raised in line three. 1702 public void assign_to_parameter(String s1) { 1703 System.out.println(s1.substring(1)); 1704 s1 = null; 1705 System.out.println(s1.substring(2)); 1706 } 1707 1708 // Tests that a class generated on the fly is handled properly. 1709 public void testGeneratedCode() throws Exception { 1710 byte[] classBytes = generateTestClass(); 1711 Lookup lookup = lookup(); 1712 Class<?> clazz = lookup.defineClass(classBytes); 1713 E0 e = (E0) clazz.getDeclaredConstructor().newInstance(); 1714 try { 1715 e.throwNPE(null); 1716 } catch (NullPointerException ex) { 1717 checkMessage(ex, "return f.i;", 1718 ex.getMessage(), 1719 "Cannot read field \"i\" because \"f\" is null"); 1720 } 1721 1722 // Optimized bytecode can reuse local variable slots for several 1723 // local variables. 1724 // If there is no variable name information, we print 'parameteri' 1725 // if a parameter maps to a local slot. Once a local slot has been 1726 // written, we don't know any more whether it was written as the 1727 // corresponding parameter, or whether another local has been 1728 // mapped to the slot. So we don't want to print 'parameteri' any 1729 // more, but 'locali'. Similary for 'this'. 1730 1731 // Expect message saying "parameter0". 1732 try { 1733 e.throwNPE_reuseStackSlot1(null); 1734 } catch (NullPointerException ex) { 1735 checkMessage(ex, "s1.substring(1)", 1736 ex.getMessage(), 1737 "Cannot invoke \"String.substring(int)\" because \"<parameter1>\" is null"); 1738 } 1739 // Expect message saying "local0". 1740 try { 1741 e.throwNPE_reuseStackSlot1("aa"); 1742 } catch (NullPointerException ex) { 1743 checkMessage(ex, "s1_2.substring(1)", 1744 ex.getMessage(), 1745 "Cannot invoke \"String.substring(int)\" because \"<local1>\" is null"); 1746 } 1747 // Expect message saying "parameter4". 1748 try { 1749 e.throwNPE_reuseStackSlot4("aa", "bb", "cc", null); 1750 } catch (NullPointerException ex) { 1751 checkMessage(ex, "s4.substring(1)", 1752 ex.getMessage(), 1753 "Cannot invoke \"String.substring(int)\" because \"<parameter4>\" is null"); 1754 } 1755 // Expect message saying "local4". 1756 try { 1757 e.throwNPE_reuseStackSlot4("aa", "bb", "cc", "dd"); 1758 } catch (NullPointerException ex) { 1759 checkMessage(ex, "s4_2.substring(1)", 1760 ex.getMessage(), 1761 "Cannot invoke \"String.substring(int)\" because \"<local4>\" is null"); 1762 } 1763 1764 // Unfortunately, with the fix for optimized code as described above 1765 // we don't write 'parameteri' any more after the parameter variable 1766 // has been assigned. 1767 1768 if (!hasDebugInfo) { 1769 // Expect message saying "parameter1". 1770 try { 1771 assign_to_parameter(null); 1772 } catch (NullPointerException ex) { 1773 checkMessage(ex, "s1.substring(1)", 1774 ex.getMessage(), 1775 "Cannot invoke \"String.substring(int)\" because \"<parameter1>\" is null"); 1776 } 1777 // The message says "local1" although "parameter1" would be correct. 1778 try { 1779 assign_to_parameter("aaa"); 1780 } catch (NullPointerException ex) { 1781 checkMessage(ex, "s1.substring(2)", 1782 ex.getMessage(), 1783 "Cannot invoke \"String.substring(int)\" because \"<local1>\" is null"); 1784 } 1785 } 1786 } 1787 } 1788 1789 // Helper interface for test cases needed for generateTestClass(). 1790 interface E0 { 1791 public int throwNPE(F f); 1792 public void throwNPE_reuseStackSlot1(String s1); 1793 public void throwNPE_reuseStackSlot4(String s1, String s2, String s3, String s4); 1794 } 1795 1796 // Helper class for test cases needed for generateTestClass(). 1797 class F { 1798 int i; 1799 } 1800 1801 // For invokespecial test cases. 1802 class G { 1803 public String m2(String x) { 1804 return null; 1805 } 1806 1807 // This generates the following class: 1808 // 1809 // class Sub2G extends G { 1810 // public String m2(String x) { 1811 // super = null; // Possible in raw bytecode. 1812 // return super.m2(x).substring(2); // Uses invokespecial. 1813 // } 1814 // } 1815 // 1816 // This code was adapted from output of 1817 // java jdk.internal.org.objectweb.asm.util.ASMifier Sub2G.class 1818 static byte[] generateSub2GTestClass() { 1819 ClassWriter cw = new ClassWriter(0); 1820 MethodVisitor mv; 1821 1822 cw.visit(50, ACC_SUPER, "Sub2G", null, "G", null); 1823 1824 { 1825 mv = cw.visitMethod(0, "<init>", "()V", null, null); 1826 mv.visitCode(); 1827 mv.visitVarInsn(ALOAD, 0); 1828 mv.visitMethodInsn(INVOKESPECIAL, "G", "<init>", "()V", false); 1829 mv.visitInsn(RETURN); 1830 mv.visitMaxs(1, 1); 1831 mv.visitEnd(); 1832 } 1833 { 1834 mv = cw.visitMethod(ACC_PUBLIC, "m2", "(Ljava/lang/String;)Ljava/lang/String;", null, null); 1835 mv.visitCode(); 1836 mv.visitInsn(ACONST_NULL); // Will cause NPE. 1837 mv.visitVarInsn(ALOAD, 1); 1838 mv.visitMethodInsn(INVOKESPECIAL, "G", "m2", "(Ljava/lang/String;)Ljava/lang/String;", false); 1839 mv.visitInsn(ICONST_2); 1840 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "substring", "(I)Ljava/lang/String;", false); 1841 mv.visitInsn(ARETURN); 1842 mv.visitMaxs(2, 2); 1843 mv.visitEnd(); 1844 } 1845 1846 cw.visitEnd(); 1847 1848 return cw.toByteArray(); 1849 } 1850 } 1851 class SubG extends G { 1852 public String m2(String x) { 1853 return super.m2(x).substring(2); 1854 } 1855 }