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