8144552: java/lang/StackWalker/LocalsAndOperands.java fails with java.lang.NullPointerException
authorbchristi
Fri, 08 Jan 2016 13:14:30 -0800
changeset 34934 7fbff68dbc12
parent 34933 09a3dab8e1f9
child 34935 b1a31c11e8ea
8144552: java/lang/StackWalker/LocalsAndOperands.java fails with java.lang.NullPointerException Summary: Update test case to expect null Reviewed-by: mchung, dfuchs
jdk/src/java.base/share/classes/java/lang/LiveStackFrame.java
jdk/test/java/lang/StackWalker/LocalsAndOperands.java
--- a/jdk/src/java.base/share/classes/java/lang/LiveStackFrame.java	Fri Jan 08 17:39:00 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/LiveStackFrame.java	Fri Jan 08 13:14:30 2016 -0800
@@ -61,6 +61,9 @@
      * local variable array is an {@link PrimitiveValue} object;
      * otherwise, the element is an {@code Object}.
      *
+     * <p>The returned array may contain null entries if a local variable is not
+     * live.
+     *
      * @return  the local variable array of this stack frame.
      */
     public Object[] getLocals();
--- a/jdk/test/java/lang/StackWalker/LocalsAndOperands.java	Fri Jan 08 17:39:00 2016 +0100
+++ b/jdk/test/java/lang/StackWalker/LocalsAndOperands.java	Fri Jan 08 13:14:30 2016 -0800
@@ -86,29 +86,43 @@
                 System.out.println("frame: " + f);
                 Object[] locals = (Object[]) getLocals.invoke(f);
                 for (int i = 0; i < locals.length; i++) {
-                    System.out.format("local %d: %s type %s%n", i, locals[i], type(locals[i]));
+                    System.out.format("  local %d: %s type %s\n", i, locals[i], type(locals[i]));
+
+                    // check for non-null locals in LocalsAndOperands.test()
+                    if (f.getClassName().equals("LocalsAndOperands") &&
+                            f.getMethodName().equals("test")) {
+                        if (locals[i] == null) {
+                            throw new RuntimeException("kept-alive locals should not be null");
+                        }
+                    }
                 }
 
                 Object[] operands = (Object[]) getOperands.invoke(f);
                 for (int i = 0; i < operands.length; i++) {
-                    System.out.format("operand %d: %s type %s%n", i, operands[i], type(operands[i]));
+                    System.out.format("  operand %d: %s type %s%n", i, operands[i],
+                                      type(operands[i]));
                 }
 
                 Object[] monitors = (Object[]) getMonitors.invoke(f);
                 for (int i = 0; i < monitors.length; i++) {
-                    System.out.format("monitor %d: %s%n", i, monitors[i]);
+                    System.out.format("  monitor %d: %s%n", i, monitors[i]);
                 }
             }
         } else {
             for (StackFrame f : frames) {
-                if (liveStackFrameClass.isInstance(f))
+                if (liveStackFrameClass.isInstance(f)) {
                     throw new RuntimeException("should not be LiveStackFrame");
+                }
             }
         }
+        // Use local variables so they stay alive
+        System.out.println("Stayin' alive: "+x+" "+c+" "+hi+" "+l+" "+d);
     }
 
     String type(Object o) throws Exception {
-        if (primitiveValueClass.isInstance(o)) {
+        if (o == null) {
+            return "null";
+        } else if (primitiveValueClass.isInstance(o)) {
             char c = (char)primitiveType.invoke(o);
             return String.valueOf(c);
         } else {