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