8152893: StackWalker#getCallerClass is not filtering hidden/ reflection frames when walker is configured to show hidden /reflection frames
Reviewed-by: mchung
--- a/jdk/src/java.base/share/classes/java/lang/StackStreamFactory.java Fri Jun 03 16:31:13 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/StackStreamFactory.java Fri Jun 03 17:01:23 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -680,7 +680,8 @@
// 1: caller-sensitive method
// 2: caller class
while (n < 2 && (caller = nextFrame()) != null) {
- if (isMethodHandleFrame(caller)) continue;
+ if (isMethodHandleFrame(caller)) { continue; }
+ if (isReflectionFrame(caller)) { continue; }
frames[n++] = caller;
}
if (frames[1] == null) {
--- a/jdk/src/java.base/share/classes/java/lang/StackWalker.java Fri Jun 03 16:31:13 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/StackWalker.java Fri Jun 03 17:01:23 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -468,23 +468,23 @@
* Gets the {@code Class} object of the caller invoking the method
* that calls this {@code getCallerClass} method.
*
- * <p> Reflection frames, {@link java.lang.invoke.MethodHandle} and
+ * <p> Reflection frames, {@link java.lang.invoke.MethodHandle}, and
* hidden frames are filtered regardless of the
* {@link Option#SHOW_REFLECT_FRAMES SHOW_REFLECT_FRAMES}
* and {@link Option#SHOW_HIDDEN_FRAMES SHOW_HIDDEN_FRAMES} options
- * this {@code StackWalker} has been configured.
+ * this {@code StackWalker} has been configured with.
*
* <p> This method throws {@code UnsupportedOperationException}
- * if this {@code StackWalker} is not configured with
- * {@link Option#RETAIN_CLASS_REFERENCE RETAIN_CLASS_REFERENCE} option,
+ * if this {@code StackWalker} is not configured with the
+ * {@link Option#RETAIN_CLASS_REFERENCE RETAIN_CLASS_REFERENCE} option.
* This method should be called when a caller frame is present. If
- * it is called from the last frame on the stack;
+ * it is called from the last frame on the stack,
* {@code IllegalStateException} will be thrown.
*
* @apiNote
* For example, {@code Util::getResourceBundle} loads a resource bundle
* on behalf of the caller. It calls this {@code getCallerClass} method
- * to find the method calling {@code Util::getResourceBundle} and use the caller's
+ * to find the method calling {@code Util::getResourceBundle} and uses the caller's
* class loader to load the resource bundle. The caller class in this example
* is the {@code MyTool} class.
*
@@ -519,7 +519,7 @@
* When the {@code getCallerClass} method is called from a method that
* is the last frame on the stack,
* for example, {@code static public void main} method launched by the
- * {@code java} launcher or a method invoked from a JNI attached thread.
+ * {@code java} launcher, or a method invoked from a JNI attached thread,
* {@code IllegalStateException} is thrown.
*
* @return {@code Class} object of the caller's caller invoking this method.
--- a/jdk/test/java/lang/StackWalker/GetCallerClassTest.java Fri Jun 03 16:31:13 2016 -0700
+++ b/jdk/test/java/lang/StackWalker/GetCallerClassTest.java Fri Jun 03 17:01:23 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8140450
+ * @bug 8140450 8152893
* @summary Basic test for StackWalker.getCallerClass()
* @run main/othervm GetCallerClassTest
* @run main/othervm GetCallerClassTest sm
@@ -41,6 +41,7 @@
import java.security.Policy;
import java.security.ProtectionDomain;
import java.util.Arrays;
+import java.util.EnumSet;
import java.util.List;
public class GetCallerClassTest {
@@ -65,16 +66,20 @@
}
new GetCallerClassTest(StackWalker.getInstance(), true).test();
new GetCallerClassTest(StackWalker.getInstance(RETAIN_CLASS_REFERENCE), false).test();
+ new GetCallerClassTest(StackWalker.getInstance(EnumSet.of(RETAIN_CLASS_REFERENCE,
+ SHOW_HIDDEN_FRAMES)), false).test();
}
public void test() {
new TopLevelCaller().run();
+ new LambdaTest().run();
new Nested().createNestedCaller().run();
new InnerClassCaller().run();
new ReflectionTest().run();
List<Thread> threads = Arrays.asList(
new Thread(new TopLevelCaller()),
+ new Thread(new LambdaTest()),
new Thread(new Nested().createNestedCaller()),
new Thread(new InnerClassCaller()),
new Thread(new ReflectionTest())
@@ -149,7 +154,7 @@
public static void assertEquals(Class<?> c, Class<?> expected) {
if (expected != c) {
- throw new RuntimeException(c + " != " + expected);
+ throw new RuntimeException("Got " + c + ", but expected " + expected);
}
}
@@ -172,6 +177,28 @@
}
}
+ class LambdaTest implements Runnable {
+ public void run() {
+ Runnable lambdaRunnable = () -> {
+ try {
+ Class<?> c = walker.getCallerClass();
+
+ assertEquals(c, LambdaTest.class);
+ if (expectUOE) { // Should have thrown
+ throw new RuntimeException("Didn't get expected exception");
+ }
+ } catch (Throwable e) {
+ if (expectUOE && causeIsUOE(e)) {
+ return; /* expected */
+ }
+ System.err.println("Unexpected exception:");
+ throw new RuntimeException(e);
+ }
+ };
+ lambdaRunnable.run();
+ }
+ }
+
class Nested {
NestedClassCaller createNestedCaller() { return new NestedClassCaller(); }
class NestedClassCaller implements Runnable {