1 /*
   2  * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright (c) 2019 SAP SE. All rights reserved.
   4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5  *
   6  * This code is free software; you can redistribute it and/or modify it
   7  * under the terms of the GNU General Public License version 2 only, as
   8  * published by the Free Software Foundation.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  */
  24 
  25 /**
  26  * @test
  27  * @summary Test extended NullPointerException message for class
  28  *   files generated without debugging information. The message lists
  29  *   detailed information about the entity that is null.
  30  * @library /test/lib
  31  * @compile NullPointerExceptionTest.java
  32  * @run main NullPointerExceptionTest
  33  */
  34 /**
  35  * @test
  36  * @summary Test extended NullPointerException message for
  37  *   classfiles generated with debug information. In this case the name
  38  *   of the variable containing the array is printed.
  39  * @library /test/lib
  40  * @compile -g NullPointerExceptionTest.java
  41  * @run main/othervm -DhasDebugInfo NullPointerExceptionTest
  42  */
  43 
  44 import java.io.ByteArrayInputStream;
  45 import java.io.ByteArrayOutputStream;
  46 import java.io.ObjectInputStream;
  47 import java.io.ObjectOutputStream;
  48 import java.util.ArrayList;
  49 
  50 import jdk.test.lib.Asserts;
  51 
  52 /**
  53  * Tests NullPointerExceptions
  54  */
  55 public class NullPointerExceptionTest {
  56     // Some fields used in the test.
  57     static Object nullStaticField;
  58     NullPointerExceptionTest nullInstanceField;
  59     static int[][][][] staticArray;
  60     static long[][] staticLongArray = new long[1000][];
  61     DoubleArrayGen dag;
  62     ArrayList<String> names = new ArrayList<>();
  63     ArrayList<String> curr;
  64     static boolean hasDebugInfo = true;
  65 
  66     static {
  67         try {
  68             hasDebugInfo = System.getProperty("hasDebugInfo") != null;
  69         } catch (Throwable t) {
  70             throw new RuntimeException(t);
  71         }
  72 
  73         staticArray       = new int[1][][][];
  74         staticArray[0]    = new int[1][][];
  75         staticArray[0][0] = new int[1][];
  76     }
  77 
  78     public static void checkMessage(String expression,
  79                                     String obtainedMsg, String expectedMsg) {
  80         System.out.println();
  81         System.out.println(" source code: " + expression);
  82         System.out.println("  thrown msg: " + obtainedMsg);
  83         //System.out.println("expected msg: " + expectedMsg);
  84         //Asserts.assertEquals(obtainedMsg, expectedMsg);
  85     }
  86 
  87     public static void main(String[] args) throws Exception {
  88         NullPointerExceptionTest t = new NullPointerExceptionTest();
  89         t.testPointerChasing();
  90         t.testArrayChasing();
  91         t.testMethodChasing();
  92         t.testSameMessage();
  93         t.testCreationViaNew();
  94         t.testCreationViaReflection();
  95         t.testCreationViaSerialization();
  96         t.testLoadedFromLocalVariable1();
  97         t.testLoadedFromLocalVariable2();
  98         t.testLoadedFromLocalVariable3();
  99         t.testLoadedFromLocalVariable4();
 100         t.testLoadedFromLocalVariable5();
 101         t.testLoadedFromLocalVariable6();
 102         t.testLoadedFromLocalVariable7();
 103         t.testLoadedFromMethod1();
 104         t.testLoadedFromMethod2();
 105         t.testLoadedFromMethod3();
 106         t.testLoadedFromMethod4();
 107         t.testLoadedFromMethod5();
 108         t.testLoadedFromMethod6();
 109         t.testLoadedFromMethod7();
 110         t.testLoadedFromStaticField1();
 111         t.testLoadedFromStaticField2();
 112         t.testLoadedFromStaticField3();
 113         t.testLoadedFromStaticField4(0, 0);
 114         t.testLoadedFromStaticField5();
 115         t.testLoadedFromStaticField5a();
 116         t.testLoadedFromStaticField5b();
 117         t.testLoadedFromStaticField6();
 118         t.testLoadedFromInstanceField1();
 119         t.testLoadedFromInstanceField2();
 120         t.testLoadedFromInstanceField3();
 121         t.testLoadedFromInstanceField4();
 122         t.testLoadedFromInstanceField5();
 123         t.testLoadedFromInstanceField6();
 124         t.testInNative();
 125         t.testMissingLocalVariableTable();
 126         t.testNullMessages();
 127     }
 128 
 129     class A {
 130         public B to_b;
 131         public B getB() { return to_b; }
 132     }
 133 
 134     class B {
 135         public C to_c;
 136         public B to_b;
 137         public C getC() { return to_c; }
 138         public B getBfromB() { return to_b; }
 139     }
 140 
 141     class C {
 142         public D to_d;
 143         public D getD() { return to_d; }
 144     }
 145 
 146     class D {
 147         public int num;
 148     }
 149 
 150     public void testPointerChasing() {
 151         A a = null;
 152         try {
 153             a.to_b.to_c.to_d.num = 99;
 154             Asserts.fail();
 155         } catch (NullPointerException e) {
 156             checkMessage("a.to_b.to_c.to_d.num = 99 // a is null", e.getMessage(),
 157                          "while trying to read the field 'to_b' of a null object loaded from " +
 158                          (hasDebugInfo ? "local variable 'a'" : "a local variable at slot 1"));
 159         }
 160         a = new A();
 161         try {
 162             a.to_b.to_c.to_d.num = 99;
 163             Asserts.fail();
 164         } catch (NullPointerException e) {
 165             checkMessage("a.to_b.to_c.to_d.num = 99 // a.to_b is null", e.getMessage(),
 166                          "while trying to read the field 'to_c' of a null object loaded from field 'NullPointerExceptionTest$A.to_b' of an object loaded from " +
 167                          (hasDebugInfo ? "local variable 'a'" : "a local variable at slot 1"));
 168         }
 169         a.to_b = new B();
 170         try {
 171             a.to_b.to_c.to_d.num = 99;
 172             Asserts.fail();
 173         } catch (NullPointerException e) {
 174             checkMessage("a.to_b.to_c.to_d.num = 99 // a.to_b.to_c is null", e.getMessage(),
 175                          "while trying to read the field 'to_d' of a null object loaded from field 'NullPointerExceptionTest$B.to_c' of an object loaded from field 'NullPointerExceptionTest$A.to_b' of an object");
 176         }
 177         a.to_b.to_c = new C();
 178         try {
 179             a.to_b.to_c.to_d.num = 99;
 180             Asserts.fail();
 181         } catch (NullPointerException e) {
 182             checkMessage("a.to_b.to_c.to_d.num = 99 // a.to_b.to_c.to_d is null", e.getMessage(),
 183                          "while trying to write the field 'NullPointerExceptionTest$D.num' of a null object loaded from field 'NullPointerExceptionTest$C.to_d' of an object loaded from field 'NullPointerExceptionTest$B.to_c' of an object");
 184         }
 185     }
 186 
 187     public void testArrayChasing() {
 188         int[][][][][] a = null;
 189         try {
 190             a[0][0][0][0][0] = 99;
 191             Asserts.fail();
 192         } catch (NullPointerException e) {
 193             checkMessage("int[0][0][0][0][0] = 99 // a is null", e.getMessage(),
 194                          "while trying to load from a null object array loaded from " +
 195                          (hasDebugInfo ? "local variable 'a'" : "a local variable at slot 1"));
 196         }
 197         a = new int[1][][][][];
 198         try {
 199             a[0][0][0][0][0] = 99;
 200             Asserts.fail();
 201         } catch (NullPointerException e) {
 202             checkMessage("int[0][0][0][0][0] = 99 // a[0] is null", e.getMessage(),
 203                          "while trying to load from a null object array loaded from an array (which itself was loaded from " +
 204                          (hasDebugInfo ? "local variable 'a'" : "a local variable at slot 1") +
 205                          ") with an index loaded from a constant");
 206         }
 207         a[0] = new int[1][][][];
 208         try {
 209             a[0][0][0][0][0] = 99;
 210             Asserts.fail();
 211         } catch (NullPointerException e) {
 212             checkMessage("int[0][0][0][0][0] = 99 // a[0][0] is null", e.getMessage(),
 213                          "while trying to load from a null object array loaded from an array (which itself was loaded from an array) with an index loaded from a constant");
 214         }
 215         a[0][0] = new int[1][][];
 216         try {
 217             a[0][0][0][0][0] = 99;
 218             Asserts.fail();
 219         } catch (NullPointerException e) {
 220             checkMessage("int[0][0][0][0][0] = 99 // a[0][0][0] is null", e.getMessage(),
 221                          "while trying to load from a null object array loaded from an array (which itself was loaded from an array) with an index loaded from a constant");
 222         }
 223         a[0][0][0] = new int[1][];
 224         try {
 225             a[0][0][0][0][0] = 99;
 226             Asserts.fail();
 227         } catch (NullPointerException e) {
 228             checkMessage("int[0][0][0][0][0] = 99 // a[0][0][0][0] is null", e.getMessage(),
 229                          "while trying to store to a null int array loaded from an array (which itself was loaded from an array) with an index loaded from a constant");
 230         }
 231         a[0][0][0][0] = new int[1];
 232         try {
 233             a[0][0][0][0][0] = 99;
 234         } catch (NullPointerException e) {
 235             Asserts.fail();
 236         }
 237     }
 238 
 239     public void testMethodChasing() {
 240         A a = null;
 241         try {
 242             a.getB().getBfromB().getC().getD().num = 99;
 243             Asserts.fail();
 244         } catch (NullPointerException e) {
 245             checkMessage("a.getB().getBfromB().getC().getD().num = 99 // a is null", e.getMessage(),
 246                          "while trying to invoke the method 'NullPointerExceptionTest$A.getB()LNullPointerExceptionTest$B;' on a null reference loaded from " +
 247                          (hasDebugInfo ? "local variable 'a'" : "a local variable at slot 1"));
 248         }
 249         a = new A();
 250         try {
 251             a.getB().getBfromB().getC().getD().num = 99;
 252             Asserts.fail();
 253         } catch (NullPointerException e) {
 254             checkMessage("a.getB().getBfromB().getC().getD().num = 99 // a.getB() is null", e.getMessage(),
 255                          "while trying to invoke the method 'NullPointerExceptionTest$B.getBfromB()LNullPointerExceptionTest$B;' on a null reference returned from 'NullPointerExceptionTest$A.getB()LNullPointerExceptionTest$B;'");
 256         }
 257         a.to_b = new B();
 258         try {
 259             a.getB().getBfromB().getC().getD().num = 99;
 260             Asserts.fail();
 261         } catch (NullPointerException e) {
 262             checkMessage("a.getB().getBfromB().getC().getD().num = 99 // a.getB().getBfromB() is null", e.getMessage(),
 263                          "while trying to invoke the method 'NullPointerExceptionTest$B.getC()LNullPointerExceptionTest$C;' on a null reference returned from 'NullPointerExceptionTest$B.getBfromB()LNullPointerExceptionTest$B;'");
 264         }
 265         a.to_b.to_b = new B();
 266         try {
 267             a.getB().getBfromB().getC().getD().num = 99;
 268             Asserts.fail();
 269         } catch (NullPointerException e) {
 270             checkMessage("a.getB().getBfromB().getC().getD().num = 99 // a.getB().getBfromB().getC() is null", e.getMessage(),
 271                          "while trying to invoke the method 'NullPointerExceptionTest$C.getD()LNullPointerExceptionTest$D;' on a null reference returned from 'NullPointerExceptionTest$B.getC()LNullPointerExceptionTest$C;'");
 272         }
 273         a.to_b.to_b.to_c = new C();
 274         try {
 275             a.getB().getBfromB().getC().getD().num = 99;
 276             Asserts.fail();
 277         } catch (NullPointerException e) {
 278             checkMessage("a.getB().getBfromB().getC().getD().num = 99 // a.getB().getBfromB().getC().getD() is null", e.getMessage(),
 279                          "while trying to write the field 'NullPointerExceptionTest$D.num' of a null object returned from 'NullPointerExceptionTest$C.getD()LNullPointerExceptionTest$D;'");
 280         }
 281     }
 282 
 283     // Test we get the same message calling npe.getMessage() twice.
 284     public void testSameMessage() throws Exception {
 285         Object null_o = null;
 286         String expectedMsg =
 287             "while trying to invoke the method 'java.lang.Object.hashCode()I'" +
 288             " on a null reference loaded from " +
 289             (hasDebugInfo ? "local variable 'null_o'" : "a local variable at slot 1");
 290 
 291         try {
 292             null_o.hashCode();
 293             Asserts.fail();
 294         } catch (NullPointerException npe) {
 295             String msg1 = npe.getMessage();
 296             checkMessage("null_o.hashCode()", msg1, expectedMsg);
 297             String msg2 = npe.getMessage();
 298             Asserts.assertTrue(msg1.equals(msg2));
 299             // It was decided that getMessage should generate the
 300             // message anew on every call, so this does not hold any more.
 301             Asserts.assertFalse(msg1 == msg2);
 302         }
 303     }
 304 
 305     /**
 306      *
 307      */
 308     public void testCreationViaNew() {
 309         Asserts.assertNull(new NullPointerException().getMessage());
 310     }
 311 
 312     /**
 313      * @throws Exception
 314      */
 315     public void testCreationViaReflection() throws Exception {
 316         Exception ex = NullPointerException.class.getDeclaredConstructor().newInstance();
 317         Asserts.assertNull(ex.getMessage());
 318     }
 319 
 320     /**
 321      * @throws Exception
 322      */
 323     public void testCreationViaSerialization() throws Exception {
 324         // NPE without message.
 325         Object o1 = new NullPointerException();
 326         ByteArrayOutputStream bos1 = new ByteArrayOutputStream();
 327         ObjectOutputStream oos1 = new ObjectOutputStream(bos1);
 328         oos1.writeObject(o1);
 329         ByteArrayInputStream bis1 = new ByteArrayInputStream(bos1.toByteArray());
 330         ObjectInputStream ois1 = new ObjectInputStream(bis1);
 331         Exception ex1 = (Exception) ois1.readObject();
 332         Asserts.assertNull(ex1.getMessage());
 333 
 334         // NPE with custom message.
 335         String msg2 = "A useless message";
 336         Object o2 = new NullPointerException(msg2);
 337         ByteArrayOutputStream bos2 = new ByteArrayOutputStream();
 338         ObjectOutputStream oos2 = new ObjectOutputStream(bos2);
 339         oos2.writeObject(o2);
 340         ByteArrayInputStream bis2 = new ByteArrayInputStream(bos2.toByteArray());
 341         ObjectInputStream ois2 = new ObjectInputStream(bis2);
 342         Exception ex2 = (Exception) ois2.readObject();
 343         Asserts.assertEquals(ex2.getMessage(), msg2);
 344 
 345         // NPE with generated message.
 346         Object null_o3 = null;
 347         Object o3 = null;
 348         String msg3 = null;
 349         try {
 350             null_o3.hashCode();
 351             Asserts.fail();
 352         } catch (NullPointerException npe3) {
 353             o3 = npe3;
 354             msg3 = npe3.getMessage();
 355             checkMessage("null_o3.hashCode()", msg3, "while trying to invoke the method 'java.lang.Object.hashCode()I'" +
 356                                  " on a null reference loaded from " +
 357                                  (hasDebugInfo ? "local variable 'null_o3'" : "a local variable at slot 14"));
 358         }
 359         ByteArrayOutputStream bos3 = new ByteArrayOutputStream();
 360         ObjectOutputStream oos3 = new ObjectOutputStream(bos3);
 361         oos3.writeObject(o3);
 362         ByteArrayInputStream bis3 = new ByteArrayInputStream(bos3.toByteArray());
 363         ObjectInputStream ois3 = new ObjectInputStream(bis3);
 364         Exception ex3 = (Exception) ois3.readObject();
 365         // It was decided that getMessage should not store the
 366         // message in Throwable.detailMessage, thus it can not
 367         // be recovered by serialization.
 368         //Asserts.assertEquals(ex3.getMessage(), msg3);
 369         Asserts.assertEquals(ex3.getMessage(), null);
 370     }
 371 
 372     /**
 373      *
 374      */
 375     @SuppressWarnings("null")
 376     public void testLoadedFromLocalVariable1() {
 377         Object o = null;
 378 
 379         try {
 380             o.hashCode();
 381             Asserts.fail();
 382         } catch (NullPointerException e) {
 383             checkMessage("o.hashCode()", e.getMessage(), "while trying to invoke the method 'java.lang.Object.hashCode()I' on a null reference loaded from " + (hasDebugInfo ? "local variable 'o'" : "a local variable at slot 1"));
 384         }
 385     }
 386 
 387     /**
 388      *
 389      */
 390     @SuppressWarnings("null")
 391     public void testLoadedFromLocalVariable2() {
 392         Exception[] myVariable = null;
 393 
 394         try {
 395             Asserts.assertNull(myVariable[0]);
 396             Asserts.fail();
 397         } catch (NullPointerException e) {
 398             checkMessage("myVariable[0]", e.getMessage(), "while trying to load from a null object array loaded from " + (hasDebugInfo ? "local variable 'myVariable'" : "a local variable at slot 1"));
 399         }
 400     }
 401 
 402     /**
 403      *
 404      */
 405     @SuppressWarnings("null")
 406     public void testLoadedFromLocalVariable3() {
 407         Exception[] myVariable = null;
 408 
 409         try {
 410             myVariable[0] = null;
 411             Asserts.fail();
 412         } catch (NullPointerException e) {
 413             checkMessage("myVariable[0] = null", e.getMessage(), "while trying to store to a null object array loaded from " + (hasDebugInfo ? "local variable 'myVariable'" : "a local variable at slot 1"));
 414         }
 415     }
 416 
 417     /**
 418      *
 419      */
 420     @SuppressWarnings("null")
 421     public void testLoadedFromLocalVariable4() {
 422         Exception[] myVariable\u0096 = null;
 423 
 424         try {
 425             Asserts.assertTrue(myVariable\u0096.length == 0);
 426             Asserts.fail();
 427         } catch (NullPointerException e) {
 428             checkMessage("myVariable\u0096.length", e.getMessage(), "while trying to get the length of a null array loaded from " + (hasDebugInfo ? "local variable 'myVariable'" : "a local variable at slot 1"));
 429         }
 430     }
 431 
 432     /**
 433      * @throws Exception
 434      */
 435     @SuppressWarnings("null")
 436     public void testLoadedFromLocalVariable5() throws Exception {
 437         Exception myException = null;
 438 
 439         try {
 440             throw myException;
 441         } catch (NullPointerException e) {
 442             checkMessage("throw myException", e.getMessage(), "while trying to throw a null exception object loaded from " + (hasDebugInfo ? "local variable 'myException'" : "a local variable at slot 1"));
 443         }
 444     }
 445 
 446     /**
 447      *
 448      */
 449     @SuppressWarnings("null")
 450     public void testLoadedFromLocalVariable6() {
 451         byte[] myVariable = null;
 452         int my_index = 1;
 453 
 454         try {
 455             Asserts.assertTrue(myVariable[my_index] == 0);
 456             Asserts.fail();
 457         } catch (NullPointerException e) {
 458             checkMessage("myVariable[my_index]", e.getMessage(), "while trying to load from a null byte (or boolean) array loaded from " + (hasDebugInfo ? "local variable 'myVariable'" : "a local variable at slot 1"));
 459         }
 460     }
 461 
 462     /**
 463      *
 464      */
 465     @SuppressWarnings("null")
 466     public void testLoadedFromLocalVariable7() {
 467         byte[] myVariable = null;
 468 
 469         try {
 470             myVariable[System.out.hashCode()] = (byte) 0;
 471             Asserts.fail();
 472         } catch (NullPointerException e) {
 473             checkMessage("myVariable[System.out.hashCode()]", e.getMessage(), "while trying to store to a null byte (or boolean) array loaded from " + (hasDebugInfo ? "local variable 'myVariable'" : "a local variable at slot 1"));
 474         }
 475     }
 476 
 477     /**
 478      *
 479      */
 480     public void testLoadedFromMethod1() {
 481         try {
 482             Asserts.assertTrue(((char[]) NullPointerGenerator.nullReturner(false))[0] == 'A');
 483             Asserts.fail();
 484         } catch (NullPointerException e) {
 485             checkMessage("((char[]) NullPointerGenerator.nullReturner(false))[0]", e.getMessage(), "while trying to load from a null char array returned from 'NullPointerExceptionTest$NullPointerGenerator.nullReturner(Z)Ljava/lang/Object;'");
 486         }
 487     }
 488 
 489     /**
 490      *
 491      */
 492     public void testLoadedFromMethod2() {
 493         try {
 494             Asserts.assertTrue(((char[]) (new NullPointerGenerator().returnMyNull(1, 1, (short) 1)))[0] == 'a');
 495             Asserts.fail();
 496         } catch (NullPointerException e) {
 497             checkMessage("((char[]) (new NullPointerGenerator().returnMyNull(1, 1, (short) 1)))[0]", e.getMessage(), "while trying to load from a null char array returned from 'NullPointerExceptionTest$NullPointerGenerator.returnMyNull(DJS)Ljava/lang/Object;'");
 498         }
 499     }
 500 
 501     /**
 502      *
 503      */
 504     public void testLoadedFromMethod3() {
 505         try {
 506             Asserts.assertTrue(((double[]) returnNull(null, null, 1f))[0] == 1.0);
 507             Asserts.fail();
 508         } catch (NullPointerException e) {
 509             checkMessage("((double[]) returnNull(null, null, 1f))[0] ", e.getMessage(), "while trying to load from a null double array returned from 'NullPointerExceptionTest.returnNull([[Ljava/lang/String;[[[IF)Ljava/lang/Object;'");
 510         }
 511     }
 512 
 513     /**
 514      *
 515      */
 516     public void testLoadedFromMethod4() {
 517         ImplTestLoadedFromMethod4(new DoubleArrayGenImpl());
 518     }
 519 
 520     /**
 521      * @param gen
 522      */
 523     public void ImplTestLoadedFromMethod4(DoubleArrayGen gen) {
 524         try {
 525             (gen.getArray())[0] = 1.0;
 526             Asserts.fail();
 527         } catch (NullPointerException e) {
 528             checkMessage("(gen.getArray())[0]", e.getMessage(), "while trying to store to a null double array returned from 'NullPointerExceptionTest$DoubleArrayGen.getArray()[D'");
 529         }
 530     }
 531 
 532     /**
 533      *
 534      */
 535     public void testLoadedFromMethod5() {
 536         try {
 537             returnMeAsNull(null, 1, 'A').dag = null;
 538             Asserts.fail();
 539         } catch (NullPointerException e) {
 540             checkMessage("returnMeAsNull(null, 1, 'A').dag = null", e.getMessage(), "while trying to write the field 'NullPointerExceptionTest.dag' of a null object returned from 'NullPointerExceptionTest.returnMeAsNull(Ljava/lang/Throwable;IC)LNullPointerExceptionTest;'");
 541         }
 542         /*
 543         try {
 544             returnMeAsNull(null, 1, 'A').dag.dag = null;
 545             Asserts.fail();
 546         } catch (NullPointerException e) {
 547             checkMessage("returnMeAsNull(null, 1, 'A').dag.dag = null", e.getMessage(), "while trying to write the field 'NullPointerExceptionTest.dag' of a null object returned from 'NullPointerExceptionTest.returnMeAsNull(Ljava/lang/Throwable;IC)LNullPointerExceptionTest;'");
 548         }
 549         */
 550     }
 551 
 552     /**
 553      *
 554      */
 555     @SuppressWarnings("null")
 556     public void testLoadedFromMethod6() {
 557         short[] sa = null;
 558 
 559         try {
 560             Asserts.assertTrue(sa[0] == (short) 1);
 561             Asserts.fail();
 562         } catch (NullPointerException e) {
 563             checkMessage("sa[0]", e.getMessage(), "while trying to load from a null short array loaded from " + (hasDebugInfo ? "local variable 'sa'" : "a local variable at slot 1"));
 564         }
 565     }
 566 
 567     /**
 568      *
 569      */
 570     @SuppressWarnings("null")
 571     public void testLoadedFromMethod7() {
 572         short[] sa = null;
 573 
 574         try {
 575             sa[0] = 1;
 576             Asserts.fail();
 577         } catch (NullPointerException e) {
 578             checkMessage("sa[0] = 1", e.getMessage(), "while trying to store to a null short array loaded from " + (hasDebugInfo ? "local variable 'sa'" : "a local variable at slot 1"));
 579         }
 580     }
 581 
 582     /**
 583      *
 584      */
 585     public void testLoadedFromStaticField1() {
 586         try {
 587             Asserts.assertTrue(((float[]) nullStaticField)[0] == 1.0f);
 588             Asserts.fail();
 589         } catch (NullPointerException e) {
 590             checkMessage("((float[]) nullStaticField)[0]", e.getMessage(), "while trying to load from a null float array loaded from static field 'NullPointerExceptionTest.nullStaticField'");
 591         }
 592     }
 593 
 594     /**
 595      *
 596      */
 597     public void testLoadedFromStaticField2() {
 598         try {
 599             ((float[]) nullStaticField)[0] = 1.0f;
 600             Asserts.fail();
 601         } catch (NullPointerException e) {
 602             checkMessage("((float[]) nullStaticField)[0] = 1.0f", e.getMessage(), "while trying to store to a null float array loaded from static field 'NullPointerExceptionTest.nullStaticField'");
 603         }
 604     }
 605 
 606     /**
 607      *
 608      */
 609     public void testLoadedFromStaticField3() {
 610         try {
 611             Asserts.assertTrue(staticArray[0][0][0][0] == 1);
 612             Asserts.fail();
 613         } catch (NullPointerException e) {
 614             checkMessage("staticArray[0][0][0][0] // staticArray[0][0][0] is null.", e.getMessage(), "while trying to load from a null int array loaded from an array (which itself was loaded from an array) with an index loaded from a constant");
 615         }
 616     }
 617 
 618     /**
 619      *
 620      */
 621     public void testLoadedFromStaticField4(int myIdx, int pos) {
 622         try {
 623             staticArray[0][0][pos][myIdx] = 2;
 624             Asserts.fail();
 625         } catch (NullPointerException e) {
 626             checkMessage(" staticArray[0][0][pos][myIdx] = 2", e.getMessage(), "while trying to store to a null int array loaded from an array (which itself was loaded from an array) with an index loaded from " + (hasDebugInfo ? "local variable 'pos'" : "the parameter nr. 2 of the method"));
 627         }
 628     }
 629 
 630     /**
 631      *
 632      */
 633     public void testLoadedFromStaticField5() {
 634         try {
 635             Asserts.assertTrue(staticLongArray[0][0] == 1L);
 636         } catch (NullPointerException e) {
 637             checkMessage("staticLongArray[0][0]", e.getMessage(), "while trying to load from a null long array loaded from an array (which itself was loaded from static field 'NullPointerExceptionTest.staticLongArray') with an index loaded from a constant");
 638         }
 639     }
 640 
 641     /**
 642      * Test bipush for index.
 643      */
 644     public void testLoadedFromStaticField5a() {
 645         try {
 646             Asserts.assertTrue(staticLongArray[139 /*0x77*/][0] == 1L);
 647         } catch (NullPointerException e) {
 648             checkMessage("staticLongArray[139][0]", e.getMessage(), "while trying to load from a null long array loaded from an array (which itself was loaded from static field 'NullPointerExceptionTest.staticLongArray') with an index loaded from a constant");
 649         }
 650     }
 651 
 652     /**
 653      * Test sipush for index.
 654      */
 655     public void testLoadedFromStaticField5b() {
 656         try {
 657             Asserts.assertTrue(staticLongArray[819 /*0x333*/][0] == 1L);
 658         } catch (NullPointerException e) {
 659             checkMessage("staticLongArray[819][0]",  e.getMessage(), "while trying to load from a null long array loaded from an array (which itself was loaded from static field 'NullPointerExceptionTest.staticLongArray') with an index loaded from a constant");
 660         }
 661     }
 662 
 663     /**
 664      *
 665      */
 666     public void testLoadedFromStaticField6() {
 667         try {
 668             staticLongArray[0][0] = 2L;
 669             Asserts.fail();
 670         } catch (NullPointerException e) {
 671             checkMessage("staticLongArray[0][0] = 2L", e.getMessage(), "while trying to store to a null long array loaded from an array (which itself was loaded from static field 'NullPointerExceptionTest.staticLongArray') with an index loaded from a constant");
 672         }
 673     }
 674 
 675     /**
 676      *
 677      */
 678     public void testLoadedFromInstanceField1() {
 679         try {
 680             Asserts.assertTrue(this.nullInstanceField.nullInstanceField == null);
 681             Asserts.fail();
 682         } catch (NullPointerException e) {
 683             checkMessage("this.nullInstanceField.nullInstanceField", e.getMessage(), "while trying to read the field 'nullInstanceField' of a null object loaded from field 'NullPointerExceptionTest.nullInstanceField' of an object loaded from 'this'");
 684         }
 685     }
 686 
 687     /**
 688      *
 689      */
 690     public void testLoadedFromInstanceField2() {
 691         try {
 692             this.nullInstanceField.nullInstanceField = null;
 693             Asserts.fail();
 694         } catch (NullPointerException e) {
 695             checkMessage("this.nullInstanceField.nullInstanceField = null", e.getMessage(), "while trying to write the field 'NullPointerExceptionTest.nullInstanceField' of a null object loaded from field 'NullPointerExceptionTest.nullInstanceField' of an object loaded from 'this'");
 696         }
 697     }
 698 
 699     /**
 700      *
 701      */
 702     public void testLoadedFromInstanceField3() {
 703         NullPointerExceptionTest obj = this;
 704 
 705         try {
 706             Asserts.assertNull(obj.dag.getArray().clone());
 707             Asserts.fail();
 708         } catch (NullPointerException e) {
 709             checkMessage("obj.dag.getArray().clone()", e.getMessage(), "while trying to invoke the method 'NullPointerExceptionTest$DoubleArrayGen.getArray()[D' on a null reference loaded from field 'NullPointerExceptionTest.dag' of an object loaded from " + (hasDebugInfo ? "local variable 'obj'" : "a local variable at slot 1"));
 710         }
 711     }
 712 
 713     /**
 714      *
 715      */
 716     public void testLoadedFromInstanceField4() {
 717         int indexes[] = new int[1];
 718 
 719         NullPointerExceptionTest[] objs = new NullPointerExceptionTest[] {this};
 720 
 721         try {
 722             Asserts.assertNull(objs[indexes[0]].nullInstanceField.returnNull(null, null, 1f));
 723             Asserts.fail();
 724         } catch (NullPointerException e) {
 725             checkMessage("objs[indexes[0]].nullInstanceField.returnNull(null, null, 1f", e.getMessage(), "while trying to invoke the method 'NullPointerExceptionTest.returnNull([[Ljava/lang/String;[[[IF)Ljava/lang/Object;' on a null reference loaded from field 'NullPointerExceptionTest.nullInstanceField' of an object loaded from an array");
 726         }
 727     }
 728 
 729     /**
 730      *
 731      */
 732     public void testLoadedFromInstanceField5() {
 733         int indexes[] = new int[1];
 734 
 735         NullPointerExceptionTest[] objs = new NullPointerExceptionTest[] {this};
 736 
 737         try {
 738             Asserts.assertNull(objs[indexes[0]].nullInstanceField.toString().toCharArray().clone());
 739         } catch (NullPointerException e) {
 740             checkMessage("objs[indexes[0]].nullInstanceField.toString().toCharArray().clone()", e.getMessage(), "while trying to invoke the method 'java.lang.Object.toString()Ljava/lang/String;' on a null reference loaded from field 'NullPointerExceptionTest.nullInstanceField' of an object loaded from an array");
 741         }
 742     }
 743 
 744     /**
 745      *
 746      */
 747     public void testLoadedFromInstanceField6() {
 748         int indexes[] = new int[1];
 749 
 750         NullPointerExceptionTest[][] objs =
 751             new NullPointerExceptionTest[][] {new NullPointerExceptionTest[] {this}};
 752 
 753         try {
 754             // Check monitorenter only, since we cannot probe monitorexit from Java.
 755             synchronized (objs[indexes[0]][0].nullInstanceField) {
 756                 Asserts.fail();
 757             }
 758         } catch (NullPointerException e) {
 759             checkMessage("synchronized (objs[indexes[0]][0].nullInstanceField)", e.getMessage(), "while trying to enter a null monitor loaded from field 'NullPointerExceptionTest.nullInstanceField' of an object loaded from an array");
 760         }
 761     }
 762 
 763     /**
 764      * @throws ClassNotFoundException
 765      */
 766     public void testInNative() throws ClassNotFoundException {
 767         try {
 768             Class.forName(null);
 769             Asserts.fail();
 770         } catch (NullPointerException e) {
 771             Asserts.assertNull(e.getMessage());
 772         }
 773     }
 774 
 775     private Object returnNull(String[][] dummy1, int[][][] dummy2, float dummy3) {
 776         return null;
 777     }
 778 
 779     private NullPointerExceptionTest returnMeAsNull(Throwable dummy1, int dummy2, char dummy3){
 780         return null;
 781     }
 782 
 783     static interface DoubleArrayGen {
 784         public double[] getArray();
 785     }
 786 
 787     static class DoubleArrayGenImpl implements DoubleArrayGen {
 788         @Override
 789         public double[] getArray() {
 790             return null;
 791         }
 792     }
 793 
 794     static class NullPointerGenerator {
 795         public static Object nullReturner(boolean dummy1) {
 796             return null;
 797         }
 798 
 799         public Object returnMyNull(double dummy1, long dummy2, short dummy3) {
 800             return null;
 801         }
 802     }
 803 
 804     /**
 805      *
 806      */
 807     public void testMissingLocalVariableTable() {
 808         doTestMissingLocalVariableTable(names);
 809 
 810         String[] expectedHasDebugInfoGoodNames = new String[] {
 811             "while trying to invoke the method 'java.lang.Object.hashCode()I' on a null reference " +
 812                 "loaded from field 'NullPointerExceptionTest.nullInstanceField' " +
 813                 "of an object loaded from 'this'",
 814             "while trying to invoke the method 'java.lang.Object.hashCode()I' on a null reference loaded from " +
 815                 "local variable 'a1'",
 816             "while trying to invoke the method 'java.lang.Object.hashCode()I' on a null reference loaded from " +
 817                 "local variable 'o1'",
 818             "while trying to invoke the method 'java.lang.Object.hashCode()I' on a null reference loaded from " +
 819                 "local variable 'aa1'"
 820         };
 821 
 822         String[] expectedNoDebugInfoGoodNames = new String[] {
 823             "while trying to invoke the method 'java.lang.Object.hashCode()I' on a null reference " +
 824                 "loaded from field 'NullPointerExceptionTest.nullInstanceField' " +
 825                 "of an object loaded from 'this'",
 826             "while trying to invoke the method 'java.lang.Object.hashCode()I' on a null reference loaded from " +
 827                 "the parameter nr. 5 of the method",
 828             "while trying to invoke the method 'java.lang.Object.hashCode()I' on a null reference loaded from " +
 829                 "the parameter nr. 2 of the method",
 830             "while trying to invoke the method 'java.lang.Object.hashCode()I' on a null reference loaded from " +
 831                 "the parameter nr. 9 of the method"
 832         };
 833 
 834         String[] expectedNames;
 835         if (hasDebugInfo) {
 836             expectedNames = expectedHasDebugInfoGoodNames;
 837         } else {
 838             expectedNames = expectedNoDebugInfoGoodNames;
 839         }
 840 
 841         // The two lists of messages should have the same length.
 842         Asserts.assertEquals(names.size(), expectedNames.length);
 843 
 844         for (int i = 0; i < expectedNames.length; ++i) {
 845             // GLGLGL not for now Asserts.assertEquals(names.get(i), expectedNames[i]);
 846         }
 847     }
 848 
 849     private void doTestMissingLocalVariableTable(ArrayList<String> names) {
 850         curr = names;
 851         doTestMissingLocalVariableTable1();
 852         doTestMissingLocalVariableTable2(-1, null, false, 0.0, null, 0.1f, (byte) 0, (short) 0, null);
 853     }
 854 
 855     private void doTestMissingLocalVariableTable1() {
 856         try {
 857             this.nullInstanceField.hashCode();
 858             Asserts.fail();
 859         } catch (NullPointerException e) {
 860             curr.add(e.getMessage());
 861         }
 862     }
 863 
 864     private void doTestMissingLocalVariableTable2(long l1, Object o1, boolean z1, double d1, Object[] a1,
 865             float f1, byte b1, short s1, Object[][] aa1) {
 866         try {
 867             a1.hashCode();
 868             Asserts.fail();
 869         }
 870         catch (NullPointerException e) {
 871             curr.add(e.getMessage());
 872         }
 873 
 874         try {
 875             o1.hashCode();
 876             Asserts.fail();
 877         }
 878         catch (NullPointerException e) {
 879             curr.add(e.getMessage());
 880         }
 881 
 882         try {
 883             aa1.hashCode();
 884             Asserts.fail();
 885         }
 886         catch (NullPointerException e) {
 887             curr.add(e.getMessage());
 888         }
 889     }
 890 
 891     /**
 892      *
 893      */
 894     @SuppressWarnings("null")
 895     public void testNullMessages() {
 896         boolean[] za1 = null;
 897         byte[] ba1 = null;
 898         short[] sa1 = null;
 899         char[] ca1 = null;
 900         int[] ia1 = null;
 901         long[] la1 = null;
 902         float[] fa1 = null;
 903         double[] da1 = null;
 904         Object[] oa1 = null;
 905 
 906         Object[][] oa2 = new Object[2][];
 907         oa2[1] = oa1;
 908 
 909         try {
 910             System.out.println(oa2[1][0]);
 911             Asserts.fail();
 912         } catch (NullPointerException e) {
 913             checkMessage("oa2[1][0]", e.getMessage(),
 914                                  "while trying to load from a null object array loaded from an array " +
 915                                  "(which itself was loaded from " +
 916                                  (hasDebugInfo ? "local variable 'oa2'" : "a local variable at slot 10") + ") " +
 917                                  "with an index loaded from a constant");
 918         }
 919 
 920 
 921         try {
 922             System.out.println(za1[0]);
 923             Asserts.fail();
 924         } catch (NullPointerException e) {
 925             checkMessage("za1[0]", e.getMessage(),
 926                                  "while trying to load from a null byte (or boolean) array loaded from " +
 927                                  (hasDebugInfo ? "local variable 'za1'" : "a local variable at slot 1"));
 928         }
 929 
 930         try {
 931             System.out.println(ba1[0]);
 932             Asserts.fail();
 933         } catch (NullPointerException e) {
 934             checkMessage("ba1[0]", e.getMessage(),
 935                                  "while trying to load from a null byte (or boolean) array loaded from " +
 936                                  (hasDebugInfo ? "local variable 'ba1'" : "a local variable at slot 2"));
 937         }
 938 
 939         try {
 940             System.out.println(sa1[0]);
 941             Asserts.fail();
 942         } catch (NullPointerException e) {
 943             checkMessage("sa1[0]", e.getMessage(),
 944                                  "while trying to load from a null short array loaded from " +
 945                                  (hasDebugInfo ? "local variable 'sa1'" : "a local variable at slot 3"));
 946         }
 947 
 948         try {
 949             System.out.println(ca1[0]);
 950             Asserts.fail();
 951         } catch (NullPointerException e) {
 952             checkMessage("ca1[0]", e.getMessage(),
 953                                  "while trying to load from a null char array loaded from " +
 954                                  (hasDebugInfo ? "local variable 'ca1'" : "a local variable at slot 4"));
 955         }
 956 
 957         try {
 958             System.out.println(ia1[0]);
 959             Asserts.fail();
 960         } catch (NullPointerException e) {
 961             checkMessage("ia1[0]", e.getMessage(),
 962                                  "while trying to load from a null int array loaded from " +
 963                                  (hasDebugInfo ? "local variable 'ia1'" : "a local variable at slot 5"));
 964         }
 965 
 966         try {
 967             System.out.println(la1[0]);
 968             Asserts.fail();
 969         } catch (NullPointerException e) {
 970             checkMessage("la1[0]", e.getMessage(),
 971                                  "while trying to load from a null long array loaded from " +
 972                                  (hasDebugInfo ? "local variable 'la1'" : "a local variable at slot 6"));
 973         }
 974 
 975         try {
 976             System.out.println(fa1[0]);
 977             Asserts.fail();
 978         } catch (NullPointerException e) {
 979             checkMessage("fa1[0]", e.getMessage(),
 980                                  "while trying to load from a null float array loaded from " +
 981                                  (hasDebugInfo ? "local variable 'fa1'" : "a local variable at slot 7"));
 982         }
 983 
 984         try {
 985             System.out.println(da1[0]);
 986             Asserts.fail();
 987         } catch (NullPointerException e) {
 988             checkMessage("da1[0]", e.getMessage(),
 989                                  "while trying to load from a null double array loaded from " +
 990                                  (hasDebugInfo ? "local variable 'da1'" : "a local variable at slot 8"));
 991         }
 992 
 993         try {
 994             System.out.println(oa1[0]);
 995             Asserts.fail();
 996         } catch (NullPointerException e) {
 997             checkMessage("oa1[0]", e.getMessage(),
 998                                  "while trying to load from a null object array loaded from " +
 999                                  (hasDebugInfo ? "local variable 'oa1'" : "a local variable at slot 9"));
1000         }
1001 
1002         try {
1003             System.out.println(za1[0] = false);
1004             Asserts.fail();
1005         } catch (NullPointerException e) {
1006             checkMessage("za1[0] = false", e.getMessage(),
1007                                  "while trying to store to a null byte (or boolean) array loaded from " +
1008                                  (hasDebugInfo ? "local variable 'za1'" : "a local variable at slot 1"));
1009         }
1010 
1011         try {
1012             System.out.println(ba1[0] = 0);
1013             Asserts.fail();
1014         } catch (NullPointerException e) {
1015             checkMessage("ba1[0] = 0", e.getMessage(),
1016                                  "while trying to store to a null byte (or boolean) array loaded from " +
1017                                  (hasDebugInfo ? "local variable 'ba1'" : "a local variable at slot 2"));
1018         }
1019 
1020         try {
1021             System.out.println(sa1[0] = 0);
1022             Asserts.fail();
1023         } catch (NullPointerException e) {
1024             checkMessage("sa1[0] = 0", e.getMessage(),
1025                                  "while trying to store to a null short array loaded from " +
1026                                  (hasDebugInfo ? "local variable 'sa1'" : "a local variable at slot 3"));
1027         }
1028 
1029         try {
1030             System.out.println(ca1[0] = 0);
1031             Asserts.fail();
1032         } catch (NullPointerException e) {
1033             checkMessage("ca1[0] = 0", e.getMessage(),
1034                                  "while trying to store to a null char array loaded from " +
1035                                  (hasDebugInfo ? "local variable 'ca1'" : "a local variable at slot 4"));
1036         }
1037 
1038         try {
1039             System.out.println(ia1[0] = 0);
1040             Asserts.fail();
1041         } catch (NullPointerException e) {
1042             checkMessage("ia1[0] = 0", e.getMessage(),
1043                                  "while trying to store to a null int array loaded from " +
1044                                  (hasDebugInfo ? "local variable 'ia1'" : "a local variable at slot 5"));
1045         }
1046 
1047         try {
1048             System.out.println(la1[0] = 0);
1049             Asserts.fail();
1050         } catch (NullPointerException e) {
1051             checkMessage("la1[0] = 0", e.getMessage(),
1052                                  "while trying to store to a null long array loaded from " +
1053                                  (hasDebugInfo ? "local variable 'la1'" : "a local variable at slot 6"));
1054         }
1055 
1056         try {
1057             System.out.println(fa1[0] = 0);
1058             Asserts.fail();
1059         } catch (NullPointerException e) {
1060             checkMessage("fa1[0] = 0", e.getMessage(),
1061                                  "while trying to store to a null float array loaded from " +
1062                                  (hasDebugInfo ? "local variable 'fa1'" : "a local variable at slot 7"));
1063         }
1064 
1065         try {
1066             System.out.println(da1[0] = 0);
1067             Asserts.fail();
1068         } catch (NullPointerException e) {
1069             checkMessage("da1[0] = 0", e.getMessage(),
1070                                  "while trying to store to a null double array loaded from " +
1071                                  (hasDebugInfo ? "local variable 'da1'" : "a local variable at slot 8"));
1072         }
1073 
1074         try {
1075             System.out.println(oa1[0] = null);
1076             Asserts.fail();
1077         } catch (NullPointerException e) {
1078             checkMessage("oa1[0] = null", e.getMessage(),
1079                                  "while trying to store to a null object array loaded from " +
1080                                  (hasDebugInfo ? "local variable 'oa1'" : "a local variable at slot 9"));
1081         }
1082 
1083         try {
1084             System.out.println(nullInstanceField.nullInstanceField);
1085             Asserts.fail();
1086         } catch (NullPointerException e) {
1087             checkMessage("nullInstanceField.nullInstanceField", e.getMessage(),
1088                                  "while trying to read the field 'nullInstanceField' of a null object loaded " +
1089                                  "from field 'NullPointerExceptionTest.nullInstanceField' of an object " +
1090                                  "loaded from 'this'");
1091         }
1092 
1093         try {
1094             System.out.println(nullInstanceField.nullInstanceField = null);
1095             Asserts.fail();
1096         } catch (NullPointerException e) {
1097             checkMessage("nullInstanceField.nullInstanceField = null", e.getMessage(),
1098                                  "while trying to write the field 'NullPointerExceptionTest.nullInstanceField' " +
1099                                  "of a null object loaded from field 'NullPointerExceptionTest.nullInstanceField' " +
1100                                  "of an object loaded from 'this'");
1101         }
1102 
1103         try {
1104             System.out.println(za1.length);
1105             Asserts.fail();
1106         } catch (NullPointerException e) {
1107             checkMessage("za1.length", e.getMessage(),
1108                                  "while trying to get the length of a null array loaded from " +
1109                                  (hasDebugInfo ? "local variable 'za1'" : "a local variable at slot 1"));
1110         }
1111 
1112         try {
1113             throw null;
1114         } catch (NullPointerException e) {
1115             checkMessage("throw null", e.getMessage(),
1116                                  "while trying to throw a null exception object loaded " +
1117                                  "from a constant");
1118         }
1119 
1120         try {
1121             synchronized (nullInstanceField) {
1122                 // desired
1123             }
1124         } catch (NullPointerException e) {
1125             checkMessage("synchronized (nullInstanceField)", e.getMessage(),
1126                                  "while trying to enter a null monitor loaded from field " +
1127                                  "'NullPointerExceptionTest.nullInstanceField' of an object loaded from " +
1128                                  "'this'");
1129         }
1130 
1131         try {
1132             nullInstanceField.testCreationViaNew();
1133             Asserts.fail();
1134         } catch (NullPointerException e) {
1135             checkMessage("nullInstanceField.testCreationViaNew()", e.getMessage(),
1136                                  "while trying to invoke the method 'NullPointerExceptionTest.testCreationViaNew()V' on a null reference " +
1137                                  "loaded from field 'NullPointerExceptionTest.nullInstanceField' of an " +
1138                                  "object loaded from 'this'");
1139         }
1140 
1141         try {
1142             nullInstanceField.testNullMessages();
1143             Asserts.fail();
1144         } catch (NullPointerException e) {
1145             checkMessage("nullInstanceField.testNullMessages()", e.getMessage(),
1146                                  "while trying to invoke the method 'NullPointerExceptionTest.testNullMessages()V' on a null reference " +
1147                                  "loaded from field 'NullPointerExceptionTest.nullInstanceField' of an " +
1148                                  "object loaded from 'this'");
1149         }
1150 
1151         try {
1152             // If we can get the value from more than one bci, we cannot know which one.
1153             (Math.random() < 0.5 ? oa1 : (new Object[1])[0]).equals("");
1154         } catch (NullPointerException e) {
1155             checkMessage("(Math.random() < 0.5 ? oa1 : (new Object[1])[0]).equals(\"\")", e.getMessage(),
1156                                  "while trying to invoke the method 'java.lang.Object.equals(Ljava/lang/Object;)Z' on a null reference");
1157         }
1158     }
1159 }