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