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