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