45 * @library /test/lib
46 * @compile NullPointerExceptionTest.java
47 * @run main/othervm -XX:MaxJavaStackTraceDepth=1 -XX:+ShowCodeDetailsInExceptionMessages NullPointerExceptionTest
48 */
49
50 import java.io.ByteArrayInputStream;
51 import java.io.ByteArrayOutputStream;
52 import java.io.ObjectInputStream;
53 import java.io.ObjectOutputStream;
54 import java.lang.invoke.MethodHandles.Lookup;
55 import java.util.ArrayList;
56
57 import jdk.internal.org.objectweb.asm.ClassWriter;
58 import jdk.internal.org.objectweb.asm.Label;
59 import jdk.internal.org.objectweb.asm.MethodVisitor;
60 import jdk.test.lib.Asserts;
61
62 import static java.lang.invoke.MethodHandles.lookup;
63 import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC;
64 import static jdk.internal.org.objectweb.asm.Opcodes.ACC_SUPER;
65 import static jdk.internal.org.objectweb.asm.Opcodes.ALOAD;
66 import static jdk.internal.org.objectweb.asm.Opcodes.GETFIELD;
67 import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESPECIAL;
68 import static jdk.internal.org.objectweb.asm.Opcodes.IRETURN;
69 import static jdk.internal.org.objectweb.asm.Opcodes.RETURN;
70
71 /**
72 * Tests NullPointerExceptions
73 */
74 public class NullPointerExceptionTest {
75
76 // Some fields used in the test.
77 static Object nullStaticField;
78 NullPointerExceptionTest nullInstanceField;
79 static int[][][][] staticArray;
80 static long[][] staticLongArray = new long[1000][];
81 DoubleArrayGen dag;
82 ArrayList<String> names = new ArrayList<>();
83 ArrayList<String> curr;
84 static boolean hasDebugInfo = false;
85
86 static {
87 staticArray = new int[1][][][];
1406 checkMessage(e, "Integer a = null; int b = a;", e.getMessage(),
1407 "Cannot invoke 'java.lang.Integer.intValue()' because " +
1408 (hasDebugInfo ? "'a'" : "'<local1>'") + " is null.");
1409 }
1410
1411 // Unboxing by hand. Has the same message as above.
1412 try {
1413 int b = a.intValue();
1414 } catch (NullPointerException e) {
1415 checkMessage(e, "Integer a = null; int b = a.intValue();", e.getMessage(),
1416 "Cannot invoke 'java.lang.Integer.intValue()' because " +
1417 (hasDebugInfo ? "'a'" : "'<local1>'") + " is null.");
1418 }
1419 }
1420
1421 // Generates:
1422 // class E implements E0 {
1423 // public int throwNPE(F f) {
1424 // return f.i;
1425 // }
1426 // }
1427 static byte[] generateTestClass() {
1428 ClassWriter cw = new ClassWriter(0);
1429 MethodVisitor mv;
1430
1431 cw.visit(50, ACC_SUPER, "E", null, "java/lang/Object", new String[] { "E0" });
1432
1433 {
1434 mv = cw.visitMethod(0, "<init>", "()V", null, null);
1435 mv.visitCode();
1436 mv.visitVarInsn(ALOAD, 0);
1437 mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
1438 mv.visitInsn(RETURN);
1439 mv.visitMaxs(1, 1);
1440 mv.visitEnd();
1441 }
1442
1443 {
1444 mv = cw.visitMethod(ACC_PUBLIC, "throwNPE", "(LF;)I", null, null);
1445 mv.visitCode();
1446 Label label0 = new Label();
1447 mv.visitLabel(label0);
1448 mv.visitLineNumber(118, label0);
1449 mv.visitVarInsn(ALOAD, 1);
1450 mv.visitFieldInsn(GETFIELD, "F", "i", "I");
1451 mv.visitInsn(IRETURN);
1452 Label label1 = new Label();
1453 mv.visitLabel(label1);
1454 mv.visitLocalVariable("this", "LE;", null, label0, label1, 0);
1455 mv.visitLocalVariable("f", "LE;", null, label0, label1, 1);
1456 mv.visitMaxs(1, 2);
1457 mv.visitEnd();
1458 }
1459 cw.visitEnd();
1460
1461 return cw.toByteArray();
1462 }
1463
1464 // Tests that a class generated on the fly is handled properly.
1465 public void testGeneratedCode() throws Exception {
1466 byte[] classBytes = generateTestClass();
1467 Lookup lookup = lookup();
1468 Class<?> clazz = lookup.defineClass(classBytes);
1469 E0 e = (E0) clazz.getDeclaredConstructor().newInstance();
1470 try {
1471 e.throwNPE(null);
1472 } catch (NullPointerException ex) {
1473 checkMessage(ex, "return f.i;",
1474 ex.getMessage(),
1475 "Cannot read field 'i' because 'f' is null.");
1476 }
1477 }
1478 }
1479
1480 // Helper interface for test cases needed for generateTestClass().
1481 interface E0 {
1482 public int throwNPE(F f);
1483 }
1484
1485 // Helper class for test cases needed for generateTestClass().
1486 class F {
1487 int i;
1488 }
|
45 * @library /test/lib
46 * @compile NullPointerExceptionTest.java
47 * @run main/othervm -XX:MaxJavaStackTraceDepth=1 -XX:+ShowCodeDetailsInExceptionMessages NullPointerExceptionTest
48 */
49
50 import java.io.ByteArrayInputStream;
51 import java.io.ByteArrayOutputStream;
52 import java.io.ObjectInputStream;
53 import java.io.ObjectOutputStream;
54 import java.lang.invoke.MethodHandles.Lookup;
55 import java.util.ArrayList;
56
57 import jdk.internal.org.objectweb.asm.ClassWriter;
58 import jdk.internal.org.objectweb.asm.Label;
59 import jdk.internal.org.objectweb.asm.MethodVisitor;
60 import jdk.test.lib.Asserts;
61
62 import static java.lang.invoke.MethodHandles.lookup;
63 import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC;
64 import static jdk.internal.org.objectweb.asm.Opcodes.ACC_SUPER;
65 import static jdk.internal.org.objectweb.asm.Opcodes.ACONST_NULL;
66 import static jdk.internal.org.objectweb.asm.Opcodes.ALOAD;
67 import static jdk.internal.org.objectweb.asm.Opcodes.ASTORE;
68 import static jdk.internal.org.objectweb.asm.Opcodes.GETFIELD;
69 import static jdk.internal.org.objectweb.asm.Opcodes.GETSTATIC;
70 import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_1;
71 import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESPECIAL;
72 import static jdk.internal.org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
73 import static jdk.internal.org.objectweb.asm.Opcodes.IRETURN;
74 import static jdk.internal.org.objectweb.asm.Opcodes.RETURN;
75
76 /**
77 * Tests NullPointerExceptions
78 */
79 public class NullPointerExceptionTest {
80
81 // Some fields used in the test.
82 static Object nullStaticField;
83 NullPointerExceptionTest nullInstanceField;
84 static int[][][][] staticArray;
85 static long[][] staticLongArray = new long[1000][];
86 DoubleArrayGen dag;
87 ArrayList<String> names = new ArrayList<>();
88 ArrayList<String> curr;
89 static boolean hasDebugInfo = false;
90
91 static {
92 staticArray = new int[1][][][];
1411 checkMessage(e, "Integer a = null; int b = a;", e.getMessage(),
1412 "Cannot invoke 'java.lang.Integer.intValue()' because " +
1413 (hasDebugInfo ? "'a'" : "'<local1>'") + " is null.");
1414 }
1415
1416 // Unboxing by hand. Has the same message as above.
1417 try {
1418 int b = a.intValue();
1419 } catch (NullPointerException e) {
1420 checkMessage(e, "Integer a = null; int b = a.intValue();", e.getMessage(),
1421 "Cannot invoke 'java.lang.Integer.intValue()' because " +
1422 (hasDebugInfo ? "'a'" : "'<local1>'") + " is null.");
1423 }
1424 }
1425
1426 // Generates:
1427 // class E implements E0 {
1428 // public int throwNPE(F f) {
1429 // return f.i;
1430 // }
1431 // public void throwNPE_reuseStackSlot1(String s1) {
1432 // System.out.println(s1.substring(1));
1433 // String s1_2 = null; // Reuses slot 1.
1434 // System.out.println(s1_2.substring(1));
1435 // }
1436 // public void throwNPE_reuseStackSlot4(String s1, String s2, String s3, String s4) {
1437 // System.out.println(s4.substring(1));
1438 // String s4_2 = null; // Reuses slot 4.
1439 // System.out.println(s4_2.substring(1));
1440 // }
1441 // }
1442 static byte[] generateTestClass() {
1443 ClassWriter cw = new ClassWriter(0);
1444 MethodVisitor mv;
1445
1446 cw.visit(50, ACC_SUPER, "E", null, "java/lang/Object", new String[] { "E0" });
1447
1448 {
1449 mv = cw.visitMethod(0, "<init>", "()V", null, null);
1450 mv.visitCode();
1451 mv.visitVarInsn(ALOAD, 0);
1452 mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
1453 mv.visitInsn(RETURN);
1454 mv.visitMaxs(1, 1);
1455 mv.visitEnd();
1456 }
1457
1458 {
1459 mv = cw.visitMethod(ACC_PUBLIC, "throwNPE", "(LF;)I", null, null);
1460 mv.visitCode();
1461 Label label0 = new Label();
1462 mv.visitLabel(label0);
1463 mv.visitLineNumber(118, label0);
1464 mv.visitVarInsn(ALOAD, 1);
1465 mv.visitFieldInsn(GETFIELD, "F", "i", "I");
1466 mv.visitInsn(IRETURN);
1467 Label label1 = new Label();
1468 mv.visitLabel(label1);
1469 mv.visitLocalVariable("this", "LE;", null, label0, label1, 0);
1470 mv.visitLocalVariable("f", "LE;", null, label0, label1, 1);
1471 mv.visitMaxs(1, 2);
1472 mv.visitEnd();
1473 }
1474
1475 {
1476 mv = cw.visitMethod(ACC_PUBLIC, "throwNPE_reuseStackSlot1", "(Ljava/lang/String;)V", null, null);
1477 mv.visitCode();
1478 Label label0 = new Label();
1479 mv.visitLabel(label0);
1480 mv.visitLineNumber(7, label0);
1481 mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
1482 mv.visitVarInsn(ALOAD, 1);
1483 mv.visitInsn(ICONST_1);
1484 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "substring", "(I)Ljava/lang/String;", false);
1485 mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
1486 Label label1 = new Label();
1487 mv.visitLabel(label1);
1488 mv.visitLineNumber(8, label1);
1489 mv.visitInsn(ACONST_NULL);
1490 mv.visitVarInsn(ASTORE, 1);
1491 Label label2 = new Label();
1492 mv.visitLabel(label2);
1493 mv.visitLineNumber(9, label2);
1494 mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
1495 mv.visitVarInsn(ALOAD, 1);
1496 mv.visitInsn(ICONST_1);
1497 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "substring", "(I)Ljava/lang/String;", false);
1498 mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
1499 Label label3 = new Label();
1500 mv.visitLabel(label3);
1501 mv.visitLineNumber(10, label3);
1502 mv.visitInsn(RETURN);
1503 mv.visitMaxs(3, 3);
1504 mv.visitEnd();
1505 }
1506
1507 {
1508 mv = cw.visitMethod(ACC_PUBLIC, "throwNPE_reuseStackSlot4", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", null, null);
1509 mv.visitCode();
1510 Label label0 = new Label();
1511 mv.visitLabel(label0);
1512 mv.visitLineNumber(12, label0);
1513 mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
1514 mv.visitVarInsn(ALOAD, 4);
1515 mv.visitInsn(ICONST_1);
1516 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "substring", "(I)Ljava/lang/String;", false);
1517 mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
1518 Label label1 = new Label();
1519 mv.visitLabel(label1);
1520 mv.visitLineNumber(13, label1);
1521 mv.visitInsn(ACONST_NULL);
1522 mv.visitVarInsn(ASTORE, 4);
1523 Label label2 = new Label();
1524 mv.visitLabel(label2);
1525 mv.visitLineNumber(14, label2);
1526 mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
1527 mv.visitVarInsn(ALOAD, 4);
1528 mv.visitInsn(ICONST_1);
1529 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "substring", "(I)Ljava/lang/String;", false);
1530 mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
1531 Label label3 = new Label();
1532 mv.visitLabel(label3);
1533 mv.visitLineNumber(15, label3);
1534 mv.visitInsn(RETURN);
1535 mv.visitMaxs(3, 6);
1536 mv.visitEnd();
1537 }
1538
1539 cw.visitEnd();
1540
1541 return cw.toByteArray();
1542 }
1543
1544 // Assign to a parameter.
1545 // Without debug information, this will print "parameter1" if a NPE
1546 // is raised in the first line because null was passed to the method.
1547 // It will print "local1" if a NPE is raised in line three.
1548 public void assign_to_parameter(String s1) {
1549 System.out.println(s1.substring(1));
1550 s1 = null;
1551 System.out.println(s1.substring(2));
1552 }
1553
1554 // Tests that a class generated on the fly is handled properly.
1555 public void testGeneratedCode() throws Exception {
1556 byte[] classBytes = generateTestClass();
1557 Lookup lookup = lookup();
1558 Class<?> clazz = lookup.defineClass(classBytes);
1559 E0 e = (E0) clazz.getDeclaredConstructor().newInstance();
1560 try {
1561 e.throwNPE(null);
1562 } catch (NullPointerException ex) {
1563 checkMessage(ex, "return f.i;",
1564 ex.getMessage(),
1565 "Cannot read field 'i' because 'f' is null.");
1566 }
1567
1568 // Optimized bytecode can reuse local variable slots for several
1569 // local variables.
1570 // If there is no variable name information, we print 'parameteri'
1571 // if a parameter maps to a local slot. Once a local slot has been
1572 // written, we don't know any more whether it was written as the
1573 // corresponding parameter, or whether another local has been
1574 // mapped to the slot. So we don't want to print 'parameteri' any
1575 // more, but 'locali'. Similary for 'this'.
1576
1577 // Expect message saying "parameter0".
1578 try {
1579 e.throwNPE_reuseStackSlot1(null);
1580 } catch (NullPointerException ex) {
1581 checkMessage(ex, "s1.substring(1)",
1582 ex.getMessage(),
1583 "Cannot invoke 'String.substring(int)' because '<parameter1>' is null.");
1584 }
1585 // Expect message saying "local0".
1586 try {
1587 e.throwNPE_reuseStackSlot1("aa");
1588 } catch (NullPointerException ex) {
1589 checkMessage(ex, "s1_2.substring(1)",
1590 ex.getMessage(),
1591 "Cannot invoke 'String.substring(int)' because '<local1>' is null.");
1592 }
1593 // Expect message saying "parameter4".
1594 try {
1595 e.throwNPE_reuseStackSlot4("aa", "bb", "cc", null);
1596 } catch (NullPointerException ex) {
1597 checkMessage(ex, "s4.substring(1)",
1598 ex.getMessage(),
1599 "Cannot invoke 'String.substring(int)' because '<parameter4>' is null.");
1600 }
1601 // Expect message saying "local4".
1602 try {
1603 e.throwNPE_reuseStackSlot4("aa", "bb", "cc", "dd");
1604 } catch (NullPointerException ex) {
1605 checkMessage(ex, "s4_2.substring(1)",
1606 ex.getMessage(),
1607 "Cannot invoke 'String.substring(int)' because '<local4>' is null.");
1608 }
1609
1610 // Unfortunately, with the fix for optimized code as described above
1611 // we don't write 'parameteri' any more after the parameter variable
1612 // has been assigned.
1613
1614 if (!hasDebugInfo) {
1615 // Expect message saying "parameter1".
1616 try {
1617 assign_to_parameter(null);
1618 } catch (NullPointerException ex) {
1619 checkMessage(ex, "s1.substring(1)",
1620 ex.getMessage(),
1621 "Cannot invoke 'String.substring(int)' because '<parameter1>' is null.");
1622 }
1623 // The message says "local1" although "parameter1" would be correct.
1624 try {
1625 assign_to_parameter("aaa");
1626 } catch (NullPointerException ex) {
1627 checkMessage(ex, "s1.substring(2)",
1628 ex.getMessage(),
1629 "Cannot invoke 'String.substring(int)' because '<local1>' is null.");
1630 }
1631 }
1632 }
1633 }
1634
1635 // Helper interface for test cases needed for generateTestClass().
1636 interface E0 {
1637 public int throwNPE(F f);
1638 public void throwNPE_reuseStackSlot1(String s1);
1639 public void throwNPE_reuseStackSlot4(String s1, String s2, String s3, String s4);
1640 }
1641
1642 // Helper class for test cases needed for generateTestClass().
1643 class F {
1644 int i;
1645 }
|