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