< prev index next >

test/hotspot/jtreg/runtime/exceptionMsgs/NullPointerException/NullPointerExceptionTest.java

Print this page
rev 59936 : 8248476: No helpful NullPointerException message after calling fillInStackTrace
Summary: reported by christoph.dreis@freenet.de
Reviewed-by:


  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  */
  24 
  25 /**
  26  * @test
  27  * @key randomness
  28  * @summary Test extended NullPointerException message for
  29  *   classfiles generated with debug information. In this case the name
  30  *   of the variable containing the array is printed.
  31  * @bug 8218628
  32  * @modules java.base/java.lang:open
  33  *          java.base/jdk.internal.org.objectweb.asm
  34  * @library /test/lib
  35  * @compile -g NullPointerExceptionTest.java
  36  * @run main/othervm -XX:MaxJavaStackTraceDepth=1 -XX:+ShowCodeDetailsInExceptionMessages NullPointerExceptionTest hasDebugInfo
  37  */
  38 /**
  39  * @test
  40  * @key randomness
  41  * @summary Test extended NullPointerException message for class
  42  *   files generated without debugging information. The message lists
  43  *   detailed information about the entity that is null.
  44  * @bug 8218628
  45  * @modules java.base/java.lang:open
  46  *          java.base/jdk.internal.org.objectweb.asm
  47  * @library /test/lib
  48  * @compile NullPointerExceptionTest.java
  49  * @run main/othervm -XX:MaxJavaStackTraceDepth=1 -XX:+ShowCodeDetailsInExceptionMessages NullPointerExceptionTest
  50  */
  51 
  52 import java.io.ByteArrayInputStream;
  53 import java.io.ByteArrayOutputStream;
  54 import java.io.ObjectInputStream;
  55 import java.io.ObjectOutputStream;
  56 import java.lang.invoke.MethodHandles.Lookup;
  57 import java.util.ArrayList;
  58 import java.util.Random;
  59 
  60 import jdk.internal.org.objectweb.asm.ClassWriter;
  61 import jdk.internal.org.objectweb.asm.Label;
  62 import jdk.internal.org.objectweb.asm.MethodVisitor;
  63 import jdk.test.lib.Asserts;
  64 import jdk.test.lib.Utils;


  88     static Object nullStaticField;
  89     NullPointerExceptionTest nullInstanceField;
  90     static int[][][][] staticArray;
  91     static long[][] staticLongArray = new long[1000][];
  92     DoubleArrayGen dag;
  93     ArrayList<String> names = new ArrayList<>();
  94     ArrayList<String> curr;
  95     static boolean hasDebugInfo = false;
  96     static final Random rng = Utils.getRandomInstance();
  97 
  98     static {
  99         staticArray       = new int[1][][][];
 100         staticArray[0]    = new int[1][][];
 101         staticArray[0][0] = new int[1][];
 102     }
 103 
 104     public static void checkMessage(Throwable t, String expression,
 105                                     String obtainedMsg, String expectedMsg) {
 106         System.out.println("\nSource code:\n  " + expression + "\n\nOutput:");
 107         t.printStackTrace(System.out);



 108         if (obtainedMsg != expectedMsg && // E.g. both are null.
 109             !obtainedMsg.equals(expectedMsg)) {
 110             System.out.println("expected msg: " + expectedMsg);
 111             Asserts.assertEquals(expectedMsg, obtainedMsg);
 112         }
 113         System.out.println("\n----");
 114     }
 115 
 116     public static void main(String[] args) throws Exception {
 117         NullPointerExceptionTest t = new NullPointerExceptionTest();
 118         if (args.length > 0) {
 119             hasDebugInfo = true;
 120         }
 121 
 122         System.out.println("Tests for the first part of the message:");
 123         System.out.println("========================================\n");
 124 
 125         // Test the message printed for the failed action.
 126         t.testFailedAction();
 127 


1264                                "\"<local71>[<local70>][<local73>[<local65>][<local64>]][<local72>[<parameter63>][<parameter62>]" +
1265                                   "[<parameter47>]][<local72>[<local73>[<parameter33>][<parameter32>]][<parameter31>][<parameter17>]]\"") +
1266                              " is null");
1267             }
1268     }
1269 
1270 
1271     public void testParameters() throws Exception {
1272         A a = new A();
1273         a.to_b = new B();
1274         testParametersTestMethod(a, 0.0, null, null);
1275     }
1276 
1277 
1278     public void testCreation() throws Exception {
1279         // If allocated with new, the message should not be generated.
1280         Asserts.assertNull(new NullPointerException().getMessage());
1281         String msg = new String("A pointless message");
1282         Asserts.assertTrue(new NullPointerException(msg).getMessage() == msg);
1283 








































































1284         // If created via reflection, the message should not be generated.
1285         Exception ex = NullPointerException.class.getDeclaredConstructor().newInstance();
1286         Asserts.assertNull(ex.getMessage());
1287     }
1288 
1289     public void testNative() throws Exception {
1290         // If NPE is thrown in a native method, the message should
1291         // not be generated.
1292         try {
1293             Class.forName(null);
1294             Asserts.fail();
1295         } catch (NullPointerException e) {
1296             Asserts.assertNull(e.getMessage());
1297         }
1298 
1299     }
1300 
1301     // Test we get the same message calling npe.getMessage() twice.
1302     @SuppressWarnings("null")
1303     public void testSameMessage() throws Exception {
1304         Object null_o = null;
1305         String expectedMsg =
1306             "Cannot invoke \"Object.hashCode()\" because " +
1307             (hasDebugInfo ? "\"null_o" : "\"<local1>") + "\" is null";
1308 
1309         try {
1310             null_o.hashCode();
1311             Asserts.fail();
1312         } catch (NullPointerException e) {
1313             String msg1 = e.getMessage();
1314             checkMessage(e, "null_o.hashCode()", msg1, expectedMsg);
1315             String msg2 = e.getMessage();
1316             Asserts.assertTrue(msg1.equals(msg2));
1317             // It was decided that getMessage should generate the
1318             // message anew on every call, so this does not hold.
1319             //Asserts.assertTrue(msg1 == msg2);
1320             Asserts.assertFalse(msg1 == msg2);
1321         }
1322     }
1323 
1324     @SuppressWarnings("null")
1325     public void testSerialization() throws Exception {
1326         // NPE without message.
1327         Object o1 = new NullPointerException();
1328         ByteArrayOutputStream bos1 = new ByteArrayOutputStream();
1329         ObjectOutputStream oos1 = new ObjectOutputStream(bos1);
1330         oos1.writeObject(o1);
1331         ByteArrayInputStream bis1 = new ByteArrayInputStream(bos1.toByteArray());
1332         ObjectInputStream ois1 = new ObjectInputStream(bis1);
1333         Exception ex1 = (Exception) ois1.readObject();
1334         Asserts.assertNull(ex1.getMessage());
1335 
1336         // NPE with custom message.
1337         String msg2 = "A useless message";
1338         Object o2 = new NullPointerException(msg2);
1339         ByteArrayOutputStream bos2 = new ByteArrayOutputStream();
1340         ObjectOutputStream oos2 = new ObjectOutputStream(bos2);




  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;


  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 


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 excpectedMessage =
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(), excpectedMessage);
1314             t = e.fillInStackTrace();
1315         }
1316         checkMessage(t, "e.fillInStackTrace()", t.getMessage(), excpectedMessage);
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);


< prev index next >