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