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
  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
  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 created via reflection, the message should not be generated.
1285         Exception ex = NullPointerException.class.getDeclaredConstructor().newInstance();
1286         Asserts.assertNull(ex.getMessage());
1287     }
1288 
1289     public void testNative() throws Exception {
1290         // If NPE is thrown in a native method, the message should
1291         // not be generated.
1292         try {
1293             Class.forName(null);
1294             Asserts.fail();
1295         } catch (NullPointerException e) {
1296             Asserts.assertNull(e.getMessage());
1297         }
1298 
1299     }
1300 
1301     // Test we get the same message calling npe.getMessage() twice.
1302     @SuppressWarnings("null")
1303     public void testSameMessage() throws Exception {
1304         Object null_o = null;
1305         String expectedMsg =
1306             "Cannot invoke \"Object.hashCode()\" because " +
1307             (hasDebugInfo ? "\"null_o" : "\"<local1>") + "\" is null";
1308 
1309         try {
1310             null_o.hashCode();
1311             Asserts.fail();
1312         } catch (NullPointerException e) {
1313             String msg1 = e.getMessage();
1314             checkMessage(e, "null_o.hashCode()", msg1, expectedMsg);
1315             String msg2 = e.getMessage();
1316             Asserts.assertTrue(msg1.equals(msg2));
1317             // It was decided that getMessage should generate the
1318             // message anew on every call, so this does not hold.
1319             //Asserts.assertTrue(msg1 == msg2);
1320             Asserts.assertFalse(msg1 == msg2);
1321         }
1322     }
1323 
1324     @SuppressWarnings("null")
1325     public void testSerialization() throws Exception {
1326         // NPE without message.
1327         Object o1 = new NullPointerException();
1328         ByteArrayOutputStream bos1 = new ByteArrayOutputStream();
1329         ObjectOutputStream oos1 = new ObjectOutputStream(bos1);
1330         oos1.writeObject(o1);
1331         ByteArrayInputStream bis1 = new ByteArrayInputStream(bos1.toByteArray());
1332         ObjectInputStream ois1 = new ObjectInputStream(bis1);
1333         Exception ex1 = (Exception) ois1.readObject();
1334         Asserts.assertNull(ex1.getMessage());
1335 
1336         // NPE with custom message.
1337         String msg2 = "A useless message";
1338         Object o2 = new NullPointerException(msg2);
1339         ByteArrayOutputStream bos2 = new ByteArrayOutputStream();
1340         ObjectOutputStream oos2 = new ObjectOutputStream(bos2);
1341         oos2.writeObject(o2);
1342         ByteArrayInputStream bis2 = new ByteArrayInputStream(bos2.toByteArray());
1343         ObjectInputStream ois2 = new ObjectInputStream(bis2);
1344         Exception ex2 = (Exception) ois2.readObject();
1345         Asserts.assertEquals(ex2.getMessage(), msg2);
1346 
1347         // NPE with generated message.
1348         Object null_o3 = null;
1349         Object o3 = null;
1350         String msg3 = null;
1351         try {
1352             int hc = null_o3.hashCode();
1353             System.out.println(hc);
1354             Asserts.fail();
1355         } catch (NullPointerException npe3) {
1356             o3 = npe3;
1357             msg3 = npe3.getMessage();
1358             checkMessage(npe3, "int hc = null_o3.hashCode();", msg3,
1359                          "Cannot invoke \"Object.hashCode()\" because " +
1360                          (hasDebugInfo ? "\"null_o3\"" : "\"<local14>\"") + " is null");
1361         }
1362         ByteArrayOutputStream bos3 = new ByteArrayOutputStream();
1363         ObjectOutputStream oos3 = new ObjectOutputStream(bos3);
1364         oos3.writeObject(o3);
1365         ByteArrayInputStream bis3 = new ByteArrayInputStream(bos3.toByteArray());
1366         ObjectInputStream ois3 = new ObjectInputStream(bis3);
1367         Exception ex3 = (Exception) ois3.readObject();
1368         // It was decided that getMessage should not store the
1369         // message in Throwable.detailMessage or implement writeReplace(),
1370         // thus it can not be recovered by serialization.
1371         //Asserts.assertEquals(ex3.getMessage(), msg3);
1372         Asserts.assertEquals(ex3.getMessage(), null);
1373     }
1374 
1375     static int index17 = 17;
1376     int getIndex17() { return 17; };
1377 
1378     @SuppressWarnings({ "unused", "null" })
1379     public void testComplexMessages() {
1380         try {
1381             staticLongArray[0][0] = 2L;
1382             Asserts.fail();
1383         } catch (NullPointerException e) {
1384             checkMessage(e, "staticLongArray[0][0] = 2L;", e.getMessage(),
1385                          "Cannot store to long array because " +
1386                          "\"NullPointerExceptionTest.staticLongArray[0]\" is null");
1387         }
1388 
1389         try {
1390             NullPointerExceptionTest obj = this;
1391             Object val = obj.dag.getArray().clone();
1392             Asserts.assertNull(val);
1393             Asserts.fail();
1394         } catch (NullPointerException e) {
1395             checkMessage(e, "Object val = obj.dag.getArray().clone();", e.getMessage(),
1396                          "Cannot invoke \"NullPointerExceptionTest$DoubleArrayGen.getArray()\" because " +
1397                          (hasDebugInfo ? "\"obj" : "\"<local1>") + ".dag\" is null");
1398         }
1399         try {
1400             int indexes[] = new int[1];
1401             NullPointerExceptionTest[] objs = new NullPointerExceptionTest[] {this};
1402             Object val = objs[indexes[0]].nullInstanceField.returnNull(null, null, 1f);
1403             Asserts.assertNull(val);
1404             Asserts.fail();
1405         } catch (NullPointerException e) {
1406             checkMessage(e, "Object val = objs[indexes[0]].nullInstanceField.returnNull(null, null, 1f);", e.getMessage(),
1407                          "Cannot invoke \"NullPointerExceptionTest.returnNull(String[][], int[][][], float)\" because " +
1408                          (hasDebugInfo ? "\"objs[indexes" : "\"<local2>[<local1>") + "[0]].nullInstanceField\" is null");
1409         }
1410 
1411         try {
1412             int indexes[] = new int[1];
1413             NullPointerExceptionTest[][] objs =
1414                 new NullPointerExceptionTest[][] {new NullPointerExceptionTest[] {this}};
1415             synchronized (objs[indexes[0]][0].nullInstanceField) {
1416                 Asserts.fail();
1417             }
1418         } catch (NullPointerException e) {
1419             checkMessage(e, "synchronized (objs[indexes[0]][0].nullInstanceField) { ... }", e.getMessage(),
1420                          "Cannot enter synchronized block because " +
1421                          (hasDebugInfo ? "\"objs[indexes" : "\"<local2>[<local1>" ) + "[0]][0].nullInstanceField\" is null");
1422         }
1423 
1424         try {
1425             // If we can get the value from more than one bci, we cannot know which one
1426             // is null. Make sure we don't print the wrong value.
1427             String s = null;
1428             @SuppressWarnings("unused")
1429             byte[] val = (rng.nextDouble() < 0.5 ? s : (new String[1])[0]).getBytes();
1430         } catch (NullPointerException e) {
1431             checkMessage(e, "byte[] val = (rng.nextDouble() < 0.5 ? s : (new String[1])[0]).getBytes();", e.getMessage(),
1432                          "Cannot invoke \"String.getBytes()\"");
1433         }
1434 
1435         try {
1436             // If we can get the value from more than one bci, we cannot know which one
1437             // is null. Make sure we don't print the wrong value.  Also make sure if
1438             // we don't print the failed action we don't print a string at all.
1439             int[][] a = new int[1][];
1440             int[][] b = new int[2][];
1441             long index = 0;
1442             @SuppressWarnings("unused")
1443             int val = (rng.nextDouble() < 0.5 ? a[(int)index] : b[(int)index])[13];
1444         } catch (NullPointerException e) {
1445             checkMessage(e, "int val = (rng.nextDouble() < 0.5 ? a[(int)index] : b[(int)index])[13]", e.getMessage(),
1446                          "Cannot load from int array");
1447         }
1448 
1449         try {
1450             // If we can get the value from more than one bci, we cannot know which one
1451             // is null. Make sure we don't print the wrong value.  Also make sure if
1452             // we don't print the failed action we don't print a string at all.
1453             int[][] a = new int[1][];
1454             int[][] b = new int[2][];
1455             long index = 0;
1456             int val = (rng.nextDouble() < 0.5 ? a : b)[(int)index][13];
1457         } catch (NullPointerException e) {
1458             checkMessage(e, "int val = (rng.nextDouble() < 0.5 ? a : b)[(int)index][13]", e.getMessage(),
1459                          "Cannot load from int array because \"<array>[...]\" is null");
1460         }
1461 
1462         try {
1463             C c1 = new C();
1464             C c2 = new C();
1465             (rng.nextDouble() < 0.5 ? c1 : c2).to_d.num = 77;
1466         } catch (NullPointerException e) {
1467             checkMessage(e, "(rng.nextDouble() < 0.5 ? c1 : c2).to_d.num = 77;", e.getMessage(),
1468                          "Cannot assign field \"num\" because \"to_d\" is null");
1469         }
1470 
1471         // Static variable as array index.
1472         try {
1473             staticLongArray[index17][0] = 2L;
1474         }  catch (NullPointerException e) {
1475             checkMessage(e, "staticLongArray[index17][0] = 2L;",  e.getMessage(),
1476                          "Cannot store to long array because " +
1477                          "\"NullPointerExceptionTest.staticLongArray[NullPointerExceptionTest.index17]\" is null");
1478         }
1479 
1480         // Method call as array index.
1481         try {
1482             staticLongArray[getIndex17()][0] = 2L;
1483         }  catch (NullPointerException e) {
1484             checkMessage(e, "staticLongArray[getIndex17()][0] = 2L;",  e.getMessage(),
1485                          "Cannot store to long array because " +
1486                          "\"NullPointerExceptionTest.staticLongArray[NullPointerExceptionTest.getIndex17()]\" is null");
1487         }
1488 
1489         // Unboxing.
1490         Integer a = null;
1491         try {
1492             int b = a;
1493         }  catch (NullPointerException e) {
1494             checkMessage(e, "Integer a = null; int b = a;",  e.getMessage(),
1495                          "Cannot invoke \"java.lang.Integer.intValue()\" because " +
1496                          (hasDebugInfo ? "\"a\"" : "\"<local1>\"") + " is null");
1497         }
1498 
1499         // Unboxing by hand. Has the same message as above.
1500         try {
1501             int b = a.intValue();
1502         }  catch (NullPointerException e) {
1503             checkMessage(e, "Integer a = null; int b = a.intValue();",  e.getMessage(),
1504                          "Cannot invoke \"java.lang.Integer.intValue()\" because " +
1505                          (hasDebugInfo ? "\"a\"" : "\"<local1>\"") + " is null");
1506         }
1507     }
1508 
1509     // Generates:
1510     // class E implements E0 {
1511     //     public int throwNPE(F f) {
1512     //         return f.i;
1513     //     }
1514     //     public void throwNPE_reuseStackSlot1(String s1) {
1515     //         System.out.println(s1.substring(1));
1516     //         String s1_2 = null; // Reuses slot 1.
1517     //         System.out.println(s1_2.substring(1));
1518     //     }
1519     //     public void throwNPE_reuseStackSlot4(String s1, String s2, String s3, String s4) {
1520     //         System.out.println(s4.substring(1));
1521     //         String s4_2 = null;  // Reuses slot 4.
1522     //         System.out.println(s4_2.substring(1));
1523     //     }
1524     // }
1525     //
1526     // This code was adapted from output of
1527     //   java jdk.internal.org.objectweb.asm.util.ASMifier E0.class
1528     static byte[] generateTestClass() {
1529         ClassWriter cw = new ClassWriter(0);
1530         MethodVisitor mv;
1531 
1532         cw.visit(50, ACC_SUPER, "E", null, "java/lang/Object", new String[] { "E0" });
1533 
1534         {
1535             mv = cw.visitMethod(0, "<init>", "()V", null, null);
1536             mv.visitCode();
1537             mv.visitVarInsn(ALOAD, 0);
1538             mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
1539             mv.visitInsn(RETURN);
1540             mv.visitMaxs(1, 1);
1541             mv.visitEnd();
1542         }
1543 
1544         {
1545             mv = cw.visitMethod(ACC_PUBLIC, "throwNPE", "(LF;)I", null, null);
1546             mv.visitCode();
1547             Label label0 = new Label();
1548             mv.visitLabel(label0);
1549             mv.visitLineNumber(118, label0);
1550             mv.visitVarInsn(ALOAD, 1);
1551             mv.visitFieldInsn(GETFIELD, "F", "i", "I");
1552             mv.visitInsn(IRETURN);
1553             Label label1 = new Label();
1554             mv.visitLabel(label1);
1555             mv.visitLocalVariable("this", "LE;", null, label0, label1, 0);
1556             mv.visitLocalVariable("f", "LE;", null, label0, label1, 1);
1557             mv.visitMaxs(1, 2);
1558             mv.visitEnd();
1559         }
1560 
1561         {
1562             mv = cw.visitMethod(ACC_PUBLIC, "throwNPE_reuseStackSlot1", "(Ljava/lang/String;)V", null, null);
1563             mv.visitCode();
1564             Label label0 = new Label();
1565             mv.visitLabel(label0);
1566             mv.visitLineNumber(7, label0);
1567             mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
1568             mv.visitVarInsn(ALOAD, 1);
1569             mv.visitInsn(ICONST_1);
1570             mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "substring", "(I)Ljava/lang/String;", false);
1571             mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
1572             Label label1 = new Label();
1573             mv.visitLabel(label1);
1574             mv.visitLineNumber(8, label1);
1575             mv.visitInsn(ACONST_NULL);
1576             mv.visitVarInsn(ASTORE, 1);
1577             Label label2 = new Label();
1578             mv.visitLabel(label2);
1579             mv.visitLineNumber(9, label2);
1580             mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
1581             mv.visitVarInsn(ALOAD, 1);
1582             mv.visitInsn(ICONST_1);
1583             mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "substring", "(I)Ljava/lang/String;", false);
1584             mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
1585             Label label3 = new Label();
1586             mv.visitLabel(label3);
1587             mv.visitLineNumber(10, label3);
1588             mv.visitInsn(RETURN);
1589             mv.visitMaxs(3, 3);
1590             mv.visitEnd();
1591         }
1592 
1593         {
1594             mv = cw.visitMethod(ACC_PUBLIC, "throwNPE_reuseStackSlot4", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", null, null);
1595             mv.visitCode();
1596             Label label0 = new Label();
1597             mv.visitLabel(label0);
1598             mv.visitLineNumber(12, label0);
1599             mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
1600             mv.visitVarInsn(ALOAD, 4);
1601             mv.visitInsn(ICONST_1);
1602             mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "substring", "(I)Ljava/lang/String;", false);
1603             mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
1604             Label label1 = new Label();
1605             mv.visitLabel(label1);
1606             mv.visitLineNumber(13, label1);
1607             mv.visitInsn(ACONST_NULL);
1608             mv.visitVarInsn(ASTORE, 4);
1609             Label label2 = new Label();
1610             mv.visitLabel(label2);
1611             mv.visitLineNumber(14, label2);
1612             mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
1613             mv.visitVarInsn(ALOAD, 4);
1614             mv.visitInsn(ICONST_1);
1615             mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "substring", "(I)Ljava/lang/String;", false);
1616             mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
1617             Label label3 = new Label();
1618             mv.visitLabel(label3);
1619             mv.visitLineNumber(15, label3);
1620             mv.visitInsn(RETURN);
1621             mv.visitMaxs(3, 6);
1622             mv.visitEnd();
1623         }
1624 
1625         cw.visitEnd();
1626 
1627         return cw.toByteArray();
1628     }
1629 
1630     // Assign to a parameter.
1631     // Without debug information, this will print "parameter1" if a NPE
1632     // is raised in the first line because null was passed to the method.
1633     // It will print "local1" if a NPE is raised in line three.
1634     public void assign_to_parameter(String s1) {
1635         System.out.println(s1.substring(1));
1636         s1 = null;
1637         System.out.println(s1.substring(2));
1638     }
1639 
1640     // Tests that a class generated on the fly is handled properly.
1641     public void testGeneratedCode() throws Exception {
1642         byte[] classBytes = generateTestClass();
1643         Lookup lookup = lookup();
1644         Class<?> clazz = lookup.defineClass(classBytes);
1645         E0 e = (E0) clazz.getDeclaredConstructor().newInstance();
1646         try {
1647             e.throwNPE(null);
1648         } catch (NullPointerException ex) {
1649             checkMessage(ex, "return f.i;",
1650                          ex.getMessage(),
1651                          "Cannot read field \"i\" because \"f\" is null");
1652         }
1653 
1654         // Optimized bytecode can reuse local variable slots for several
1655         // local variables.
1656         // If there is no variable name information, we print 'parameteri'
1657         // if a parameter maps to a local slot. Once a local slot has been
1658         // written, we don't know any more whether it was written as the
1659         // corresponding parameter, or whether another local has been
1660         // mapped to the slot. So we don't want to print 'parameteri' any
1661         // more, but 'locali'. Similary for 'this'.
1662 
1663         // Expect message saying "parameter0".
1664         try {
1665             e.throwNPE_reuseStackSlot1(null);
1666         } catch (NullPointerException ex) {
1667             checkMessage(ex, "s1.substring(1)",
1668                          ex.getMessage(),
1669                          "Cannot invoke \"String.substring(int)\" because \"<parameter1>\" is null");
1670         }
1671         // Expect message saying "local0".
1672         try {
1673             e.throwNPE_reuseStackSlot1("aa");
1674         } catch (NullPointerException ex) {
1675             checkMessage(ex, "s1_2.substring(1)",
1676                          ex.getMessage(),
1677                          "Cannot invoke \"String.substring(int)\" because \"<local1>\" is null");
1678         }
1679         // Expect message saying "parameter4".
1680         try {
1681             e.throwNPE_reuseStackSlot4("aa", "bb", "cc", null);
1682         } catch (NullPointerException ex) {
1683             checkMessage(ex, "s4.substring(1)",
1684                          ex.getMessage(),
1685                          "Cannot invoke \"String.substring(int)\" because \"<parameter4>\" is null");
1686         }
1687         // Expect message saying "local4".
1688         try {
1689             e.throwNPE_reuseStackSlot4("aa", "bb", "cc", "dd");
1690         } catch (NullPointerException ex) {
1691             checkMessage(ex, "s4_2.substring(1)",
1692                          ex.getMessage(),
1693                          "Cannot invoke \"String.substring(int)\" because \"<local4>\" is null");
1694         }
1695 
1696         // Unfortunately, with the fix for optimized code as described above
1697         // we don't write 'parameteri' any more after the parameter variable
1698         // has been assigned.
1699 
1700         if (!hasDebugInfo) {
1701             // Expect message saying "parameter1".
1702             try {
1703                 assign_to_parameter(null);
1704             } catch (NullPointerException ex) {
1705                 checkMessage(ex, "s1.substring(1)",
1706                              ex.getMessage(),
1707                              "Cannot invoke \"String.substring(int)\" because \"<parameter1>\" is null");
1708             }
1709             // The message says "local1" although "parameter1" would be correct.
1710             try {
1711                 assign_to_parameter("aaa");
1712             } catch (NullPointerException ex) {
1713                 checkMessage(ex, "s1.substring(2)",
1714                              ex.getMessage(),
1715                              "Cannot invoke \"String.substring(int)\" because \"<local1>\" is null");
1716             }
1717         }
1718     }
1719 }
1720 
1721 // Helper interface for test cases needed for generateTestClass().
1722 interface E0 {
1723     public int  throwNPE(F f);
1724     public void throwNPE_reuseStackSlot1(String s1);
1725     public void throwNPE_reuseStackSlot4(String s1, String s2, String s3, String s4);
1726 }
1727 
1728 // Helper class for test cases needed for generateTestClass().
1729 class F {
1730     int i;
1731 }
1732 
1733 // For invokespecial test cases.
1734 class G {
1735     public String m2(String x) {
1736         return null;
1737     }
1738 
1739     // This generates the following class:
1740     //
1741     // class Sub2G extends G {
1742     //   public String m2(String x) {
1743     //       super = null;  // Possible in raw bytecode.
1744     //       return super.m2(x).substring(2);  // Uses invokespecial.
1745     //   }
1746     // }
1747     //
1748     // This code was adapted from output of
1749     //   java jdk.internal.org.objectweb.asm.util.ASMifier Sub2G.class
1750     static byte[] generateSub2GTestClass() {
1751         ClassWriter cw = new ClassWriter(0);
1752         MethodVisitor mv;
1753 
1754         cw.visit(50, ACC_SUPER, "Sub2G", null, "G", null);
1755 
1756         {
1757             mv = cw.visitMethod(0, "<init>", "()V", null, null);
1758             mv.visitCode();
1759             mv.visitVarInsn(ALOAD, 0);
1760             mv.visitMethodInsn(INVOKESPECIAL, "G", "<init>", "()V", false);
1761             mv.visitInsn(RETURN);
1762             mv.visitMaxs(1, 1);
1763             mv.visitEnd();
1764         }
1765         {
1766             mv = cw.visitMethod(ACC_PUBLIC, "m2", "(Ljava/lang/String;)Ljava/lang/String;", null, null);
1767             mv.visitCode();
1768             mv.visitInsn(ACONST_NULL);   // Will cause NPE.
1769             mv.visitVarInsn(ALOAD, 1);
1770             mv.visitMethodInsn(INVOKESPECIAL, "G", "m2", "(Ljava/lang/String;)Ljava/lang/String;", false);
1771             mv.visitInsn(ICONST_2);
1772             mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "substring", "(I)Ljava/lang/String;", false);
1773             mv.visitInsn(ARETURN);
1774             mv.visitMaxs(2, 2);
1775             mv.visitEnd();
1776         }
1777 
1778         cw.visitEnd();
1779 
1780         return cw.toByteArray();
1781     }
1782 }
1783 class SubG extends G {
1784     public String m2(String x) {
1785         return super.m2(x).substring(2);
1786     }
1787 }