--- a/jdk/make/mapfiles/libjava/mapfile-vers Tue Nov 24 04:46:04 2015 +0000
+++ b/jdk/make/mapfiles/libjava/mapfile-vers Tue Nov 24 10:12:32 2015 -0800
@@ -138,14 +138,9 @@
Java_java_lang_Double_longBitsToDouble;
Java_java_lang_Double_doubleToRawLongBits;
Java_java_lang_reflect_Proxy_defineClass0;
+ Java_java_lang_Shutdown_runAllFinalizers;
Java_java_lang_Float_intBitsToFloat;
Java_java_lang_Float_floatToRawIntBits;
- Java_java_lang_StackFrameInfo_fillInStackFrames;
- Java_java_lang_StackFrameInfo_setMethodInfo;
- Java_java_lang_StackStreamFactory_checkStackWalkModes;
- Java_java_lang_StackStreamFactory_00024AbstractStackWalker_callStackWalk;
- Java_java_lang_StackStreamFactory_00024AbstractStackWalker_fetchStackFrames;
- Java_java_lang_Shutdown_runAllFinalizers;
Java_java_lang_StrictMath_IEEEremainder;
Java_java_lang_StrictMath_acos;
Java_java_lang_StrictMath_asin;
--- a/jdk/src/java.base/share/classes/java/lang/LiveStackFrame.java Tue Nov 24 04:46:04 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,226 +0,0 @@
-/*
- * Copyright (c) 2015, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package java.lang;
-
-import java.lang.StackWalker.StackFrame;
-import java.util.EnumSet;
-import java.util.Set;
-
-import static java.lang.StackWalker.ExtendedOption.LOCALS_AND_OPERANDS;
-
-/**
- * <em>UNSUPPORTED</em> This interface is intended to be package-private
- * or move to an internal package.<p>
- *
- * {@code LiveStackFrame} represents a frame storing data and partial results.
- * Each frame has its own array of local variables (JVMS section 2.6.1),
- * its own operand stack (JVMS section 2.6.2) for a method invocation.
- *
- * @jvms 2.6 Frames
- */
-/* package-private */
-interface LiveStackFrame extends StackFrame {
- /**
- * Return the monitors held by this stack frame. This method returns
- * an empty array if no monitor is held by this stack frame.
- *
- * @return the monitors held by this stack frames
- */
- public Object[] getMonitors();
-
- /**
- * Gets the local variable array of this stack frame.
- *
- * <p>A single local variable can hold a value of type boolean, byte, char,
- * short, int, float, reference or returnAddress. A pair of local variables
- * can hold a value of type long or double. In other words,
- * a value of type long or type double occupies two consecutive local
- * variables. For a value of primitive type, the element in the
- * local variable array is an {@link PrimitiveValue} object;
- * otherwise, the element is an {@code Object}.
- *
- * @return the local variable array of this stack frame.
- */
- public Object[] getLocals();
-
- /**
- * Gets the operand stack of this stack frame.
- *
- * <p>
- * The 0-th element of the returned array represents the top of the operand stack.
- * This method returns an empty array if the operand stack is empty.
- *
- * <p>Each entry on the operand stack can hold a value of any Java Virtual
- * Machine Type.
- * For a value of primitive type, the element in the returned array is
- * an {@link PrimitiveValue} object; otherwise, the element is the {@code Object}
- * on the operand stack.
- *
- * @return the operand stack of this stack frame.
- */
- public Object[] getStack();
-
- /**
- * <em>UNSUPPORTED</em> This interface is intended to be package-private
- * or move to an internal package.<p>
- *
- * Represents a local variable or an entry on the operand whose value is
- * of primitive type.
- */
- public abstract class PrimitiveValue {
- /**
- * Returns the base type of this primitive value, one of
- * {@code B, D, C, F, I, J, S, Z}.
- *
- * @return Name of a base type
- * @jvms table 4.3-A
- */
- abstract char type();
-
- /**
- * Returns the boolean value if this primitive value is of type boolean.
- * @return the boolean value if this primitive value is of type boolean.
- *
- * @throws UnsupportedOperationException if this primitive value is not
- * of type boolean.
- */
- public boolean booleanValue() {
- throw new UnsupportedOperationException("this primitive of type " + type());
- }
-
- /**
- * Returns the int value if this primitive value is of type int.
- * @return the int value if this primitive value is of type int.
- *
- * @throws UnsupportedOperationException if this primitive value is not
- * of type int.
- */
- public int intValue() {
- throw new UnsupportedOperationException("this primitive of type " + type());
- }
-
- /**
- * Returns the long value if this primitive value is of type long.
- * @return the long value if this primitive value is of type long.
- *
- * @throws UnsupportedOperationException if this primitive value is not
- * of type long.
- */
- public long longValue() {
- throw new UnsupportedOperationException("this primitive of type " + type());
- }
-
- /**
- * Returns the char value if this primitive value is of type char.
- * @return the char value if this primitive value is of type char.
- *
- * @throws UnsupportedOperationException if this primitive value is not
- * of type char.
- */
- public char charValue() {
- throw new UnsupportedOperationException("this primitive of type " + type());
- }
-
- /**
- * Returns the byte value if this primitive value is of type byte.
- * @return the byte value if this primitive value is of type byte.
- *
- * @throws UnsupportedOperationException if this primitive value is not
- * of type byte.
- */
- public byte byteValue() {
- throw new UnsupportedOperationException("this primitive of type " + type());
- }
-
- /**
- * Returns the short value if this primitive value is of type short.
- * @return the short value if this primitive value is of type short.
- *
- * @throws UnsupportedOperationException if this primitive value is not
- * of type short.
- */
- public short shortValue() {
- throw new UnsupportedOperationException("this primitive of type " + type());
- }
-
- /**
- * Returns the float value if this primitive value is of type float.
- * @return the float value if this primitive value is of type float.
- *
- * @throws UnsupportedOperationException if this primitive value is not
- * of type float.
- */
- public float floatValue() {
- throw new UnsupportedOperationException("this primitive of type " + type());
- }
-
- /**
- * Returns the double value if this primitive value is of type double.
- * @return the double value if this primitive value is of type double.
- *
- * @throws UnsupportedOperationException if this primitive value is not
- * of type double.
- */
- public double doubleValue() {
- throw new UnsupportedOperationException("this primitive of type " + type());
- }
- }
-
-
- /**
- * Gets {@code StackWalker} that can get locals and operands.
- *
- * @throws SecurityException if the security manager is present and
- * denies access to {@code RuntimePermission("liveStackFrames")}
- */
- public static StackWalker getStackWalker() {
- return getStackWalker(EnumSet.noneOf(StackWalker.Option.class));
- }
-
- /**
- * Gets a {@code StackWalker} instance with the given options specifying
- * the stack frame information it can access, and which will traverse at most
- * the given {@code maxDepth} number of stack frames. If no option is
- * specified, this {@code StackWalker} obtains the method name and
- * the class name with all
- * {@linkplain StackWalker.Option#SHOW_HIDDEN_FRAMES hidden frames} skipped.
- * The returned {@code StackWalker} can get locals and operands.
- *
- * @param options stack walk {@link StackWalker.Option options}
- *
- * @throws SecurityException if the security manager is present and
- * it denies access to {@code RuntimePermission("liveStackFrames")}; or
- * or if the given {@code options} contains
- * {@link StackWalker.Option#RETAIN_CLASS_REFERENCE Option.RETAIN_CLASS_REFERENCE}
- * and it denies access to {@code StackFramePermission("retainClassReference")}.
- */
- public static StackWalker getStackWalker(Set<StackWalker.Option> options) {
- SecurityManager sm = System.getSecurityManager();
- if (sm != null) {
- sm.checkPermission(new RuntimePermission("liveStackFrames"));
- }
- return StackWalker.newInstance(options, LOCALS_AND_OPERANDS);
- }
-}
--- a/jdk/src/java.base/share/classes/java/lang/LiveStackFrameInfo.java Tue Nov 24 04:46:04 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,271 +0,0 @@
-/*
- * Copyright (c) 2015, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package java.lang;
-
-import java.lang.StackWalker.Option;
-import java.util.EnumSet;
-import java.util.Set;
-
-import static java.lang.StackWalker.ExtendedOption.*;
-
-final class LiveStackFrameInfo extends StackFrameInfo implements LiveStackFrame {
- private static Object[] EMPTY_ARRAY = new Object[0];
-
- LiveStackFrameInfo(StackWalker walker) {
- super(walker);
- }
-
- // These fields are initialized by the VM if ExtendedOption.LOCALS_AND_OPERANDS is set
- private Object[] monitors = EMPTY_ARRAY;
- private Object[] locals = EMPTY_ARRAY;
- private Object[] operands = EMPTY_ARRAY;
-
- @Override
- public Object[] getMonitors() {
- return monitors;
- }
-
- @Override
- public Object[] getLocals() {
- return locals;
- }
-
- @Override
- public Object[] getStack() {
- return operands;
- }
-
- /*
- * Convert primitive value to {@code Primitive} object to represent
- * a local variable or an element on the operand stack of primitive type.
- */
- static PrimitiveValue asPrimitive(boolean value) {
- return new BooleanPrimitive(value);
- }
-
- static PrimitiveValue asPrimitive(int value) {
- return new IntPrimitive(value);
- }
-
- static PrimitiveValue asPrimitive(short value) {
- return new ShortPrimitive(value);
- }
-
- static PrimitiveValue asPrimitive(char value) {
- return new CharPrimitive(value);
- }
-
- static PrimitiveValue asPrimitive(byte value) {
- return new BytePrimitive(value);
- }
-
- static PrimitiveValue asPrimitive(long value) {
- return new LongPrimitive(value);
- }
-
- static PrimitiveValue asPrimitive(float value) {
- return new FloatPrimitive(value);
- }
-
- static PrimitiveValue asPrimitive(double value) {
- return new DoublePrimitive(value);
- }
-
- private static class IntPrimitive extends PrimitiveValue {
- final int value;
- IntPrimitive(int value) {
- this.value = value;
- }
-
- @Override
- public char type() {
- return 'I';
- }
-
- @Override
- public int intValue() {
- return value;
- }
-
- @Override
- public String toString() {
- return String.valueOf(value);
- }
- }
-
- private static class ShortPrimitive extends PrimitiveValue {
- final short value;
- ShortPrimitive(short value) {
- this.value = value;
- }
-
- @Override
- public char type() {
- return 'S';
- }
-
- @Override
- public short shortValue() {
- return value;
- }
-
- @Override
- public String toString() {
- return String.valueOf(value);
- }
- }
-
- private static class BooleanPrimitive extends PrimitiveValue {
- final boolean value;
- BooleanPrimitive(boolean value) {
- this.value = value;
- }
-
- @Override
- public char type() {
- return 'Z';
- }
-
- @Override
- public boolean booleanValue() {
- return value;
- }
-
- @Override
- public String toString() {
- return String.valueOf(value);
- }
- }
-
- private static class CharPrimitive extends PrimitiveValue {
- final char value;
- CharPrimitive(char value) {
- this.value = value;
- }
-
- @Override
- public char type() {
- return 'C';
- }
-
- @Override
- public char charValue() {
- return value;
- }
-
- @Override
- public String toString() {
- return String.valueOf(value);
- }
- }
-
- private static class BytePrimitive extends PrimitiveValue {
- final byte value;
- BytePrimitive(byte value) {
- this.value = value;
- }
-
- @Override
- public char type() {
- return 'B';
- }
-
- @Override
- public byte byteValue() {
- return value;
- }
-
- @Override
- public String toString() {
- return String.valueOf(value);
- }
- }
-
- private static class LongPrimitive extends PrimitiveValue {
- final long value;
- LongPrimitive(long value) {
- this.value = value;
- }
-
- @Override
- public char type() {
- return 'J';
- }
-
- @Override
- public long longValue() {
- return value;
- }
-
- @Override
- public String toString() {
- return String.valueOf(value);
- }
- }
-
- private static class FloatPrimitive extends PrimitiveValue {
- final float value;
- FloatPrimitive(float value) {
- this.value = value;
- }
-
- @Override
- public char type() {
- return 'F';
- }
-
- @Override
- public float floatValue() {
- return value;
- }
-
- @Override
- public String toString() {
- return String.valueOf(value);
- }
- }
-
- private static class DoublePrimitive extends PrimitiveValue {
- final double value;
- DoublePrimitive(double value) {
- this.value = value;
- }
-
- @Override
- public char type() {
- return 'D';
- }
-
- @Override
- public double doubleValue() {
- return value;
- }
-
- @Override
- public String toString() {
- return String.valueOf(value);
- }
- }
-}
--- a/jdk/src/java.base/share/classes/java/lang/StackFrameInfo.java Tue Nov 24 04:46:04 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,136 +0,0 @@
-/*
- * Copyright (c) 2015, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package java.lang;
-
-import jdk.internal.misc.JavaLangInvokeAccess;
-import jdk.internal.misc.SharedSecrets;
-
-import static java.lang.StackWalker.Option.*;
-import java.lang.StackWalker.StackFrame;
-import java.util.Optional;
-import java.util.OptionalInt;
-
-class StackFrameInfo implements StackFrame {
- private final static JavaLangInvokeAccess jlInvokeAccess =
- SharedSecrets.getJavaLangInvokeAccess();
-
- // -XX:+MemberNameInStackFrame will initialize MemberName and all other fields;
- // otherwise, VM will set the hidden fields (injected by the VM).
- // -XX:+MemberNameInStackFrame is temporary to enable performance measurement
- //
- // Footprint improvement: MemberName::clazz and MemberName::name
- // can replace StackFrameInfo::declaringClass and StackFrameInfo::methodName
- // Currently VM sets StackFrameInfo::methodName instead of expanding MemberName::name
-
- final StackWalker walker;
- final Class<?> declaringClass;
- final Object memberName;
- final int bci;
-
- // methodName, fileName, and lineNumber will be lazily set by the VM
- // when first requested.
- private String methodName;
- private String fileName = null; // default for unavailable filename
- private int lineNumber = -1; // default for unavailable lineNumber
-
- /*
- * Create StackFrameInfo for StackFrameTraverser and LiveStackFrameTraverser
- * to use
- */
- StackFrameInfo(StackWalker walker) {
- this.walker = walker;
- this.declaringClass = null;
- this.bci = -1;
- this.memberName = jlInvokeAccess.newMemberName();
- }
-
- @Override
- public String getClassName() {
- return declaringClass.getName();
- }
-
- @Override
- public Class<?> getDeclaringClass() {
- walker.ensureAccessEnabled(RETAIN_CLASS_REFERENCE);
- return declaringClass;
- }
-
- // Call the VM to set methodName, lineNumber, and fileName
- private synchronized void ensureMethodInfoInitialized() {
- if (methodName == null) {
- setMethodInfo();
- }
- }
-
- @Override
- public String getMethodName() {
- ensureMethodInfoInitialized();
- return methodName;
- }
-
- @Override
- public Optional<String> getFileName() {
- ensureMethodInfoInitialized();
- return fileName != null ? Optional.of(fileName) : Optional.empty();
- }
-
- @Override
- public OptionalInt getLineNumber() {
- ensureMethodInfoInitialized();
- return lineNumber > 0 ? OptionalInt.of(lineNumber) : OptionalInt.empty();
- }
-
- @Override
- public boolean isNativeMethod() {
- ensureMethodInfoInitialized();
- return lineNumber == -2;
- }
-
- @Override
- public String toString() {
- ensureMethodInfoInitialized();
- // similar format as StackTraceElement::toString
- if (isNativeMethod()) {
- return getClassName() + "." + getMethodName() + "(Native Method)";
- } else {
- // avoid allocating Optional objects
- return getClassName() + "." + getMethodName() +
- "(" + (fileName != null ? fileName : "Unknown Source") +
- (lineNumber > 0 ? ":" + lineNumber : " bci:" + bci) + ")";
- }
- }
-
- /**
- * Lazily initialize method name, file name, line number
- */
- private native void setMethodInfo();
-
- /**
- * Fill in source file name and line number of the given StackFrame array.
- */
- static native void fillInStackFrames(int startIndex,
- Object[] stackframes,
- int fromIndex, int toIndex);
-}
--- a/jdk/src/java.base/share/classes/java/lang/StackFramePermission.java Tue Nov 24 04:46:04 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2015, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package java.lang;
-
-/**
- * Permission to access {@link StackWalker.StackFrame}.
- *
- * @see java.lang.StackWalker.Option#RETAIN_CLASS_REFERENCE
- * @see StackWalker.StackFrame#getDeclaringClass()
- */
-public class StackFramePermission extends java.security.BasicPermission {
- private static final long serialVersionUID = 2841894854386706014L;
-
- /**
- * Creates a new {@code StackFramePermission} object.
- *
- * @param name Permission name. Must be "retainClassReference".
- *
- * @throws IllegalArgumentException if {@code name} is invalid.
- * @throws NullPointerException if {@code name} is {@code null}.
- */
- public StackFramePermission(String name) {
- super(name);
- if (!name.equals("retainClassReference")) {
- throw new IllegalArgumentException("name: " + name);
- }
- }
-}
--- a/jdk/src/java.base/share/classes/java/lang/StackStreamFactory.java Tue Nov 24 04:46:04 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1106 +0,0 @@
-/*
- * Copyright (c) 2015, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package java.lang;
-
-import sun.misc.VM;
-
-import java.io.PrintStream;
-import java.lang.StackWalker.Option;
-import java.lang.StackWalker.StackFrame;
-
-import java.lang.annotation.Native;
-import java.lang.reflect.Method;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.Arrays;
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.NoSuchElementException;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import java.util.Spliterator;
-import java.util.function.Consumer;
-import java.util.function.Function;
-import java.util.stream.Stream;
-import java.util.stream.StreamSupport;
-
-import static java.lang.StackStreamFactory.WalkerState.*;
-
-/**
- * StackStreamFactory class provides static factory methods
- * to get different kinds of stack walker/traverser.
- *
- * AbstractStackWalker provides the basic stack walking support
- * fetching stack frames from VM in batches.
- *
- * AbstractStackWalker subclass is specialized for a specific kind of stack traversal
- * to avoid overhead of Stream/Lambda
- * 1. Support traversing Stream<StackFrame>
- * 2. StackWalker::getCallerClass
- * 3. Throwable::init and Throwable::getStackTrace
- * 4. AccessControlContext getting ProtectionDomain
- */
-final class StackStreamFactory {
- private StackStreamFactory() {}
-
- // Stack walk implementation classes to be excluded during stack walking
- // lazily add subclasses when they are loaded.
- private final static Set<Class<?>> stackWalkImplClasses = init();
-
- private static final int SMALL_BATCH = 8;
- private static final int BATCH_SIZE = 32;
- private static final int LARGE_BATCH_SIZE = 256;
- private static final int MIN_BATCH_SIZE = SMALL_BATCH;
-
- // These flags must match the values maintained in the VM
- @Native private static final int DEFAULT_MODE = 0x0;
- @Native private static final int FILL_CLASS_REFS_ONLY = 0x2;
- @Native private static final int FILTER_FILL_IN_STACKTRACE = 0x10;
- @Native private static final int SHOW_HIDDEN_FRAMES = 0x20; // LambdaForms are hidden by the VM
- @Native private static final int FILL_LIVE_STACK_FRAMES = 0x100;
-
- /*
- * For Throwable to use StackWalker, set useNewThrowable to true.
- * Performance work and extensive testing is needed to replace the
- * VM built-in backtrace filled in Throwable with the StackWalker.
- */
- final static boolean useNewThrowable = getProperty("stackwalk.newThrowable", false);
- final static boolean isDebug = getProperty("stackwalk.debug", false);
-
- static <T> StackFrameTraverser<T>
- makeStackTraverser(StackWalker walker, Function<? super Stream<StackFrame>, ? extends T> function)
- {
- if (walker.hasLocalsOperandsOption())
- return new LiveStackInfoTraverser<T>(walker, function);
- else
- return new StackFrameTraverser<T>(walker, function);
- }
-
- /**
- * Gets a stack stream to find caller class.
- */
- static CallerClassFinder makeCallerFinder(StackWalker walker) {
- return new CallerClassFinder(walker);
- }
-
- static boolean useStackTrace(Throwable t) {
- if (t instanceof VirtualMachineError)
- return false;
-
- return VM.isBooted() && StackStreamFactory.useNewThrowable;
- }
-
- /*
- * This should only be used by Throwable::<init>.
- */
- static StackTrace makeStackTrace(Throwable ex) {
- return StackTrace.dump(ex);
- }
-
- /*
- * This creates StackTrace for Thread::dumpThread to use.
- */
- static StackTrace makeStackTrace() {
- return StackTrace.dump();
- }
-
- enum WalkerState {
- NEW, // the stream is new and stack walking has not started
- OPEN, // the stream is open when it is being traversed.
- CLOSED; // the stream is closed when the stack walking is done
- }
-
- static abstract class AbstractStackWalker<T> {
- protected final StackWalker walker;
- protected final Thread thread;
- protected final int maxDepth;
- protected final long mode;
- protected int depth; // traversed stack depth
- protected FrameBuffer frameBuffer; // buffer for VM to fill in
- protected long anchor;
-
- // buffers to fill in stack frame information
- protected AbstractStackWalker(StackWalker walker, int mode) {
- this(walker, mode, Integer.MAX_VALUE);
- }
- protected AbstractStackWalker(StackWalker walker, int mode, int maxDepth) {
- this.thread = Thread.currentThread();
- this.mode = toStackWalkMode(walker, mode);
- this.walker = walker;
- this.maxDepth = maxDepth;
- this.depth = 0;
- }
-
- private int toStackWalkMode(StackWalker walker, int mode) {
- int newMode = mode;
- if (walker.hasOption(Option.SHOW_HIDDEN_FRAMES) &&
- !fillCallerClassOnly(newMode) /* don't show hidden frames for getCallerClass */)
- newMode |= SHOW_HIDDEN_FRAMES;
- if (walker.hasLocalsOperandsOption())
- newMode |= FILL_LIVE_STACK_FRAMES;
- return newMode;
- }
-
- private boolean fillCallerClassOnly(int mode) {
- return (mode|FILL_CLASS_REFS_ONLY) != FILL_CLASS_REFS_ONLY;
- }
- /**
- * A callback method to consume the stack frames. This method is invoked
- * once stack walking begins (i.e. it is only invoked when walkFrames is called).
- *
- * Each specialized AbstractStackWalker subclass implements the consumeFrames method
- * to control the following:
- * 1. fetch the subsequent batches of stack frames
- * 2. reuse or expand the allocated buffers
- * 3. create specialized StackFrame objects
- *
- * @return the number of consumed frames
- */
- protected abstract T consumeFrames();
-
- /**
- * Initialize FrameBuffer. Subclass should implement this method to
- * create its custom frame buffers.
- */
- protected abstract void initFrameBuffer();
-
- /**
- * Returns the suggested next batch size.
- *
- * Subclass should override this method to change the batch size
- *
- * @param lastBatchFrameCount number of frames in the last batch; or zero
- * @return suggested batch size
- */
- protected abstract int batchSize(int lastBatchFrameCount);
-
- /*
- * Returns the next batch size, always >= minimum batch size (32)
- *
- * Subclass may override this method if the minimum batch size is different.
- */
- protected int getNextBatchSize() {
- int lastBatchSize = depth == 0 ? 0 : frameBuffer.curBatchFrameCount();
- int nextBatchSize = batchSize(lastBatchSize);
- if (isDebug) {
- System.err.println("last batch size = " + lastBatchSize +
- " next batch size = " + nextBatchSize);
- }
- return nextBatchSize >= MIN_BATCH_SIZE ? nextBatchSize : MIN_BATCH_SIZE;
- }
-
- /*
- * Checks if this stream is in the given state. Otherwise, throws IllegalStateException.
- *
- * VM also validates this stream if it's anchored for stack walking
- * when stack frames are fetched for each batch.
- */
- final void checkState(WalkerState state) {
- if (thread != Thread.currentThread()) {
- throw new IllegalStateException("Invalid thread walking this stack stream: " +
- Thread.currentThread().getName() + " " + thread.getName());
- }
- switch (state) {
- case NEW:
- if (this.anchor != 0) {
- throw new IllegalStateException("This stack stream is being reused.");
- }
- break;
- case OPEN:
- if (this.anchor <= 0) {
- throw new IllegalStateException("This stack stream is not valid for walking");
- }
- break;
- case CLOSED:
- if (this.anchor != -1L) {
- throw new IllegalStateException("This stack stream is not closed.");
- }
- }
- }
-
- /*
- * Close this stream. This stream becomes invalid to walk.
- */
- private void close() {
- this.anchor = -1L;
- }
-
- /*
- * Walks stack frames until {@link #consumeFrames} is done consuming
- * the frames it is interested in.
- */
- final T walk() {
- checkState(NEW);
- try {
- // VM will need to stablize the stack before walking. It will invoke
- // the AbstractStackWalker::doStackWalk method once it fetches the first batch.
- // the callback will be invoked within the scope of the callStackWalk frame.
- return beginStackWalk();
- } finally {
- close(); // done traversal; close the stream
- }
- }
-
- private boolean skipReflectionFrames() {
- return !walker.hasOption(Option.SHOW_REFLECT_FRAMES) &&
- !walker.hasOption(Option.SHOW_HIDDEN_FRAMES);
- }
-
- /*
- * Returns {@code Class} object at the current frame;
- * or {@code null} if no more frame. If advanceToNextBatch is true,
- * it will only fetch the next batch.
- */
- final Class<?> peekFrame() {
- while (frameBuffer.isActive() && depth < maxDepth) {
- if (frameBuffer.isEmpty()) {
- // fetch another batch of stack frames
- getNextBatch();
- } else {
- Class<?> c = frameBuffer.get();
- if (skipReflectionFrames() && isReflectionFrame(c)) {
- if (isDebug)
- System.err.println(" skip: frame " + frameBuffer.getIndex() + " " + c);
-
- frameBuffer.next();
- depth++;
- continue;
- } else {
- return c;
- }
- }
- }
- return null;
- }
-
- /*
- * This method is only invoked by VM.
- *
- * It will invoke the consumeFrames method to start the stack walking
- * with the first batch of stack frames. Each specialized AbstractStackWalker
- * subclass implements the consumeFrames method to control the following:
- * 1. fetch the subsequent batches of stack frames
- * 2. reuse or expand the allocated buffers
- * 3. create specialized StackFrame objects
- */
- private Object doStackWalk(long anchor, int skipFrames, int batchSize,
- int bufStartIndex, int bufEndIndex) {
- checkState(NEW);
-
- frameBuffer.check(skipFrames);
-
- if (isDebug) {
- System.err.format("doStackWalk: skip %d start %d end %d%n",
- skipFrames, bufStartIndex, bufEndIndex);
- }
-
- this.anchor = anchor; // set anchor for this bulk stack frame traversal
- frameBuffer.setBatch(bufStartIndex, bufEndIndex);
-
- // traverse all frames and perform the action on the stack frames, if specified
- return consumeFrames();
- }
-
- /*
- * Get next batch of stack frames.
- */
- private int getNextBatch() {
- int nextBatchSize = Math.min(maxDepth - depth, getNextBatchSize());
- if (!frameBuffer.isActive() || nextBatchSize <= 0) {
- if (isDebug) {
- System.out.format(" more stack walk done%n");
- }
- frameBuffer.freeze(); // stack walk done
- return 0;
- }
-
- return fetchStackFrames(nextBatchSize);
- }
-
- /*
- * This method traverses the next stack frame and returns the Class
- * invoking that stack frame.
- *
- * This method can only be called during the walk method. This is intended
- * to be used to walk the stack frames in one single invocation and
- * this stack stream will be invalidated once walk is done.
- *
- * @see #tryNextFrame
- */
- final Class<?> nextFrame() {
- if (!hasNext()) {
- return null;
- }
-
- Class<?> c = frameBuffer.next();
- depth++;
- return c;
- }
-
- /*
- * Returns true if there is next frame to be traversed.
- * This skips hidden frames unless this StackWalker has
- * {@link Option#SHOW_REFLECT_FRAMES}
- */
- final boolean hasNext() {
- return peekFrame() != null;
- }
-
- /**
- * Begin stack walking - pass the allocated arrays to the VM to fill in
- * stack frame information.
- *
- * VM first anchors the frame of the current thread. A traversable stream
- * on this thread's stack will be opened. The VM will fetch the first batch
- * of stack frames and call AbstractStackWalker::doStackWalk to invoke the
- * stack walking function on each stack frame.
- *
- * If all fetched stack frames are traversed, AbstractStackWalker::fetchStackFrames will
- * fetch the next batch of stack frames to continue.
- */
- private T beginStackWalk() {
- // initialize buffers for VM to fill the stack frame info
- initFrameBuffer();
-
- return callStackWalk(mode, 0,
- frameBuffer.curBatchFrameCount(),
- frameBuffer.startIndex(),
- frameBuffer.classes,
- frameBuffer.stackFrames);
- }
-
- /*
- * Fetches stack frames.
- *
- * @params batchSize number of elements of the frame buffers for this batch
- * @returns number of frames fetched in this batch
- */
- private int fetchStackFrames(int batchSize) {
- int startIndex = frameBuffer.startIndex();
- frameBuffer.resize(startIndex, batchSize);
-
- int endIndex = fetchStackFrames(mode, anchor, batchSize,
- startIndex,
- frameBuffer.classes,
- frameBuffer.stackFrames);
- if (isDebug) {
- System.out.format(" more stack walk requesting %d got %d to %d frames%n",
- batchSize, frameBuffer.startIndex(), endIndex);
- }
- int numFrames = endIndex - startIndex;
- if (numFrames == 0) {
- frameBuffer.freeze(); // done stack walking
- } else {
- frameBuffer.setBatch(startIndex, endIndex);
- }
- return numFrames;
- }
-
- /**
- * Begins stack walking. This method anchors this frame and invokes
- * AbstractStackWalker::doStackWalk after fetching the firt batch of stack frames.
- *
- * @param mode mode of stack walking
- * @param skipframes number of frames to be skipped before filling the frame buffer.
- * @param batchSize the batch size, max. number of elements to be filled in the frame buffers.
- * @param startIndex start index of the frame buffers to be filled.
- * @param classes Classes buffer of the stack frames
- * @param frames StackFrame buffer, or null
- * @return Result of AbstractStackWalker::doStackWalk
- */
- private native T callStackWalk(long mode, int skipframes,
- int batchSize, int startIndex,
- Class<?>[] classes,
- StackFrame[] frames);
-
- /**
- * Fetch the next batch of stack frames.
- *
- * @param mode mode of stack walking
- * @param anchor
- * @param batchSize the batch size, max. number of elements to be filled in the frame buffers.
- * @param startIndex start index of the frame buffers to be filled.
- * @param classes Classes buffer of the stack frames
- * @param frames StackFrame buffer, or null
- *
- * @return the end index to the frame buffers
- */
- private native int fetchStackFrames(long mode, long anchor,
- int batchSize, int startIndex,
- Class<?>[] classes,
- StackFrame[] frames);
-
-
- /*
- * Frame buffer
- *
- * Each specialized AbstractStackWalker subclass may subclass the FrameBuffer.
- */
- class FrameBuffer {
- static final int START_POS = 2; // 0th and 1st elements are reserved
-
- // buffers for VM to fill stack frame info
- int currentBatchSize; // current batch size
- Class<?>[] classes; // caller class for fast path
-
- StackFrame[] stackFrames;
-
- int origin; // index to the current traversed stack frame
- int fence; // index to the last frame in the current batch
-
- FrameBuffer(int initialBatchSize) {
- if (initialBatchSize < MIN_BATCH_SIZE) {
- throw new IllegalArgumentException(initialBatchSize + " < minimum batch size: " + MIN_BATCH_SIZE);
- }
- this.origin = START_POS;
- this.fence = 0;
- this.currentBatchSize = initialBatchSize;
- this.classes = new Class<?>[currentBatchSize];
- }
-
- int curBatchFrameCount() {
- return currentBatchSize-START_POS;
- }
-
- /*
- * Tests if this frame buffer is empty. All frames are fetched.
- */
- final boolean isEmpty() {
- return origin >= fence || (origin == START_POS && fence == 0);
- }
-
- /*
- * Freezes this frame buffer. The stack stream source is done fetching.
- */
- final void freeze() {
- origin = 0;
- fence = 0;
- }
-
- /*
- * Tests if this frame buffer is active. It is inactive when
- * it is done for traversal. All stack frames have been traversed.
- */
- final boolean isActive() {
- return origin > 0 && (fence == 0 || origin < fence || fence == currentBatchSize);
- }
-
- /**
- * Gets the class at the current frame and move to the next frame.
- */
- final Class<?> next() {
- if (isEmpty()) {
- throw new NoSuchElementException("origin=" + origin + " fence=" + fence);
- }
- Class<?> c = classes[origin++];
- if (isDebug) {
- int index = origin-1;
- System.out.format(" next frame at %d: %s (origin %d fence %d)%n", index,
- Objects.toString(c), index, fence);
- }
- return c;
- }
-
- /**
- * Gets the class at the current frame.
- */
- final Class<?> get() {
- if (isEmpty()) {
- throw new NoSuchElementException("origin=" + origin + " fence=" + fence);
- }
- return classes[origin];
- }
-
- /*
- * Returns the index of the current frame.
- */
- final int getIndex() {
- return origin;
- }
-
- /*
- * Set the start and end index of a new batch of stack frames that have
- * been filled in this frame buffer.
- */
- final void setBatch(int startIndex, int endIndex) {
- if (startIndex <= 0 || endIndex <= 0)
- throw new IllegalArgumentException("startIndex=" + startIndex + " endIndex=" + endIndex);
-
- this.origin = startIndex;
- this.fence = endIndex;
- if (depth == 0 && fence > 0) {
- // filter the frames due to the stack stream implementation
- for (int i = START_POS; i < fence; i++) {
- Class<?> c = classes[i];
- if (isDebug) System.err.format(" frame %d: %s%n", i, c);
- if (filterStackWalkImpl(c)) {
- origin++;
- } else {
- break;
- }
- }
- }
- }
-
- /*
- * Checks if the origin is the expected start index.
- */
- final void check(int skipFrames) {
- int index = skipFrames + START_POS;
- if (origin != index) {
- // stack walk must continue with the previous frame depth
- throw new IllegalStateException("origin " + origin + " != " + index);
- }
- }
-
- // ------ subclass may override the following methods -------
- /**
- * Resizes the buffers for VM to fill in the next batch of stack frames.
- * The next batch will start at the given startIndex with the maximum number
- * of elements.
- *
- * <p> Subclass may override this method to manage the allocated buffers.
- *
- * @param startIndex the start index for the first frame of the next batch to fill in.
- * @param elements the number of elements for the next batch to fill in.
- *
- */
- void resize(int startIndex, int elements) {
- if (!isActive())
- throw new IllegalStateException("inactive frame buffer can't be resized");
-
- int size = startIndex+elements;
- if (classes.length < size) {
- // copy the elements in classes array to the newly allocated one.
- // classes[0] is a Thread object
- Class<?>[] prev = classes;
- classes = new Class<?>[size];
- System.arraycopy(prev, 0, classes, 0, START_POS);
- }
- currentBatchSize = size;
- }
-
- /*
- * Returns the start index for this frame buffer is refilled.
- *
- * This implementation reuses the allocated buffer for the next batch
- * of stack frames. For subclass to retain the fetched stack frames,
- * it should override this method to return the index at which the frame
- * should be filled in for the next batch.
- */
- int startIndex() {
- return START_POS;
- }
-
- /**
- * Returns next StackFrame object in the current batch of stack frames
- */
- StackFrame nextStackFrame() {
- throw new InternalError("should not reach here");
- }
- }
- }
-
- /*
- * This StackFrameTraverser supports {@link Stream} traversal.
- *
- * This class implements Spliterator::forEachRemaining and Spliterator::tryAdvance.
- */
- static class StackFrameTraverser<T> extends AbstractStackWalker<T>
- implements Spliterator<StackFrame>
- {
- static {
- stackWalkImplClasses.add(StackFrameTraverser.class);
- }
- private static final int CHARACTERISTICS = Spliterator.ORDERED | Spliterator.IMMUTABLE;
- class Buffer extends FrameBuffer {
- Buffer(int initialBatchSize) {
- super(initialBatchSize);
-
- this.stackFrames = new StackFrame[initialBatchSize];
- for (int i = START_POS; i < initialBatchSize; i++) {
- stackFrames[i] = new StackFrameInfo(walker);
- }
- }
-
- @Override
- void resize(int startIndex, int elements) {
- super.resize(startIndex, elements);
-
- int size = startIndex+elements;
- if (stackFrames.length < size) {
- stackFrames = new StackFrame[size];
- }
- for (int i = startIndex(); i < size; i++) {
- stackFrames[i] = new StackFrameInfo(walker);
- }
- }
-
- @Override
- StackFrame nextStackFrame() {
- if (isEmpty()) {
- throw new NoSuchElementException("origin=" + origin + " fence=" + fence);
- }
-
- StackFrame frame = stackFrames[origin];
- origin++;
- return frame;
- }
- }
-
- final Function<? super Stream<StackFrame>, ? extends T> function; // callback
-
- StackFrameTraverser(StackWalker walker,
- Function<? super Stream<StackFrame>, ? extends T> function) {
- this(walker, function, DEFAULT_MODE);
- }
- StackFrameTraverser(StackWalker walker,
- Function<? super Stream<StackFrame>, ? extends T> function,
- int mode) {
- super(walker, mode);
- this.function = function;
- }
-
- /**
- * Returns next StackFrame object in the current batch of stack frames;
- * or null if no more stack frame.
- */
- StackFrame nextStackFrame() {
- if (!hasNext()) {
- return null;
- }
-
- StackFrame frame = frameBuffer.nextStackFrame();
- depth++;
- return frame;
- }
-
- @Override
- protected T consumeFrames() {
- checkState(OPEN);
- Stream<StackFrame> stream = StreamSupport.stream(this, false);
- if (function != null) {
- return function.apply(stream);
- } else
- throw new UnsupportedOperationException();
- }
-
- @Override
- protected void initFrameBuffer() {
- this.frameBuffer = new Buffer(getNextBatchSize());
- }
-
- @Override
- protected int batchSize(int lastBatchFrameCount) {
- if (lastBatchFrameCount == 0) {
- // First batch, use estimateDepth if not exceed the large batch size
- // and not too small
- int initialBatchSize = Math.max(walker.estimateDepth(), SMALL_BATCH);
- return Math.min(initialBatchSize, LARGE_BATCH_SIZE);
- } else {
- if (lastBatchFrameCount > BATCH_SIZE) {
- return lastBatchFrameCount;
- } else {
- return Math.min(lastBatchFrameCount*2, BATCH_SIZE);
- }
- }
- }
-
- // ------- Implementation of Spliterator
-
- @Override
- public Spliterator<StackFrame> trySplit() {
- return null; // ordered stream and do not allow to split
- }
-
- @Override
- public long estimateSize() {
- return maxDepth;
- }
-
- @Override
- public int characteristics() {
- return CHARACTERISTICS;
- }
-
- @Override
- public void forEachRemaining(Consumer<? super StackFrame> action) {
- checkState(OPEN);
- for (int n = 0; n < maxDepth; n++) {
- StackFrame frame = nextStackFrame();
- if (frame == null) break;
-
- action.accept(frame);
- }
- }
-
- @Override
- public boolean tryAdvance(Consumer<? super StackFrame> action) {
- checkState(OPEN);
-
- int index = frameBuffer.getIndex();
- if (hasNext()) {
- StackFrame frame = nextStackFrame();
- action.accept(frame);
- if (isDebug) {
- System.err.println("tryAdvance: " + index + " " + frame);
- }
- return true;
- }
- if (isDebug) {
- System.err.println("tryAdvance: " + index + " NO element");
- }
- return false;
- }
- }
-
- /*
- * CallerClassFinder is specialized to return Class<?> for each stack frame.
- * StackFrame is not requested.
- */
- static class CallerClassFinder extends AbstractStackWalker<Integer> {
- static {
- stackWalkImplClasses.add(CallerClassFinder.class);
- }
-
- private Class<?> caller;
-
- CallerClassFinder(StackWalker walker) {
- super(walker, FILL_CLASS_REFS_ONLY);
- }
-
- Class<?> findCaller() {
- walk();
- return caller;
- }
-
- @Override
- protected Integer consumeFrames() {
- checkState(OPEN);
- int n = 0;
- Class<?>[] frames = new Class<?>[2];
- // skip the API calling this getCallerClass method
- // 0: StackWalker::getCallerClass
- // 1: caller-sensitive method
- // 2: caller class
- while (n < 2 && (caller = nextFrame()) != null) {
- if (isMethodHandleFrame(caller)) continue;
- frames[n++] = caller;
- }
-
- if (frames[1] == null)
- throw new IllegalStateException("no caller frame");
- return n;
- }
-
- @Override
- protected void initFrameBuffer() {
- this.frameBuffer = new FrameBuffer(getNextBatchSize());
- }
-
- @Override
- protected int batchSize(int lastBatchFrameCount) {
- return MIN_BATCH_SIZE;
- }
-
- @Override
- protected int getNextBatchSize() {
- return MIN_BATCH_SIZE;
- }
- }
-
- /*
- * StackTrace caches all frames in the buffer. StackTraceElements are
- * created lazily when Throwable::getStackTrace is called.
- */
- static class StackTrace extends AbstractStackWalker<Integer> {
- static {
- stackWalkImplClasses.add(StackTrace.class);
- }
-
- class GrowableBuffer extends FrameBuffer {
- GrowableBuffer(int initialBatchSize) {
- super(initialBatchSize);
-
- this.stackFrames = new StackFrame[initialBatchSize];
- for (int i = START_POS; i < initialBatchSize; i++) {
- stackFrames[i] = new StackFrameInfo(walker);
- }
- }
-
- /*
- * Returns the next index to fill
- */
- @Override
- int startIndex() {
- return origin;
- }
-
- /**
- * Initialize the buffers for VM to fill in the stack frame information.
- * The next batch will start at the given startIndex to
- * the length of the buffer.
- */
- @Override
- void resize(int startIndex, int elements) {
- // Expand the frame buffer.
- // Do not call super.resize that will reuse the filled elements
- // in this frame buffer
- int size = startIndex+elements;
- if (classes.length < size) {
- // resize the frame buffer
- classes = Arrays.copyOf(classes, size);
- stackFrames = Arrays.copyOf(stackFrames, size);
- }
- for (int i = startIndex; i < size; i++) {
- stackFrames[i] = new StackFrameInfo(walker);
- }
- currentBatchSize = size;
- }
-
- StackTraceElement get(int index) {
- return new StackTraceElement(classes[index].getName(), "unknown", null, -1);
- }
-
- /**
- * Returns an array of StackTraceElement for all stack frames cached in
- * this StackTrace object.
- * <p>
- * This method is intended for Throwable::getOurStackTrace use only.
- */
- StackTraceElement[] toStackTraceElements() {
- int startIndex = START_POS;
- for (int i = startIndex; i < classes.length; i++) {
- if (classes[i] != null && filterStackWalkImpl(classes[i])) {
- startIndex++;
- } else {
- break;
- }
- }
-
- // VM fills in the method name, filename, line number info
- StackFrameInfo.fillInStackFrames(0, stackFrames, startIndex, startIndex + depth);
-
- StackTraceElement[] stes = new StackTraceElement[depth];
- for (int i = startIndex, j = 0; i < classes.length && j < depth; i++, j++) {
- if (isDebug) {
- System.err.println("StackFrame: " + i + " " + stackFrames[i]);
- }
- stes[j] = stackFrames[i].toStackTraceElement();
- }
- return stes;
- }
- }
-
- private static final int MAX_STACK_FRAMES = 1024;
- private static final StackWalker STACKTRACE_WALKER =
- StackWalker.newInstanceNoCheck(EnumSet.of(Option.SHOW_REFLECT_FRAMES));
-
- private StackTraceElement[] stes;
- static StackTrace dump() {
- return new StackTrace();
- }
-
- static StackTrace dump(Throwable ex) {
- return new StackTrace(ex);
- }
-
- private StackTrace() {
- this(STACKTRACE_WALKER, DEFAULT_MODE);
- }
-
- /*
- * Throwable::fillInStackTrace and <init> of Throwable and subclasses
- * are filtered in the VM.
- */
- private StackTrace(Throwable ex) {
- this(STACKTRACE_WALKER, FILTER_FILL_IN_STACKTRACE); // skip Throwable::init frames
- if (isDebug) {
- System.err.println("dump stack for " + ex.getClass().getName());
- }
- }
-
- StackTrace(StackWalker walker, int mode) {
- super(walker, mode, MAX_STACK_FRAMES);
-
- // snapshot the stack trace
- walk();
- }
-
- @Override
- protected Integer consumeFrames() {
- // traverse all frames and perform the action on the stack frames, if specified
- int n = 0;
- while (n < maxDepth && nextFrame() != null) {
- n++;
- }
- return n;
- }
-
- @Override
- protected void initFrameBuffer() {
- this.frameBuffer = new GrowableBuffer(getNextBatchSize());
- }
-
- // TODO: implement better heuristic
- @Override
- protected int batchSize(int lastBatchFrameCount) {
- // chunk size of VM backtrace is 32
- return lastBatchFrameCount == 0 ? 32 : 32;
- }
-
- /**
- * Returns an array of StackTraceElement for all stack frames cached in
- * this StackTrace object.
- * <p>
- * This method is intended for Throwable::getOurStackTrace use only.
- */
- synchronized StackTraceElement[] getStackTraceElements() {
- if (stes == null) {
- stes = ((GrowableBuffer) frameBuffer).toStackTraceElements();
- // release the frameBuffer memory
- frameBuffer = null;
- }
- return stes;
- }
-
- /*
- * Prints stack trace to the given PrintStream.
- *
- * Further implementation could skip creating StackTraceElement objects
- * print directly to the PrintStream.
- */
- void printStackTrace(PrintStream s) {
- StackTraceElement[] stes = getStackTraceElements();
- synchronized (s) {
- s.println("Stack trace");
- for (StackTraceElement traceElement : stes)
- s.println("\tat " + traceElement);
- }
- }
- }
-
- static class LiveStackInfoTraverser<T> extends StackFrameTraverser<T> {
- static {
- stackWalkImplClasses.add(LiveStackInfoTraverser.class);
- }
- // VM will fill in all method info and live stack info directly in StackFrameInfo
- class Buffer extends FrameBuffer {
- Buffer(int initialBatchSize) {
- super(initialBatchSize);
- this.stackFrames = new StackFrame[initialBatchSize];
- for (int i = START_POS; i < initialBatchSize; i++) {
- stackFrames[i] = new LiveStackFrameInfo(walker);
- }
- }
-
- @Override
- void resize(int startIndex, int elements) {
- super.resize(startIndex, elements);
- int size = startIndex + elements;
-
- if (stackFrames.length < size) {
- this.stackFrames = new StackFrame[size];
- }
-
- for (int i = startIndex(); i < size; i++) {
- stackFrames[i] = new LiveStackFrameInfo(walker);
- }
- }
-
- @Override
- StackFrame nextStackFrame() {
- if (isEmpty()) {
- throw new NoSuchElementException("origin=" + origin + " fence=" + fence);
- }
-
- StackFrame frame = stackFrames[origin];
- origin++;
- return frame;
- }
- }
-
- LiveStackInfoTraverser(StackWalker walker,
- Function<? super Stream<StackFrame>, ? extends T> function) {
- super(walker, function, DEFAULT_MODE);
- }
-
- @Override
- protected void initFrameBuffer() {
- this.frameBuffer = new Buffer(getNextBatchSize());
- }
- }
-
- private static native boolean checkStackWalkModes();
-
- // avoid loading other subclasses as they may not be used
- private static Set<Class<?>> init() {
- if (!checkStackWalkModes()) {
- throw new InternalError("StackWalker mode values do not match with JVM");
- }
-
- Set<Class<?>> classes = new HashSet<>();
- classes.add(StackWalker.class);
- classes.add(StackStreamFactory.class);
- classes.add(AbstractStackWalker.class);
- return classes;
- }
-
- private static boolean filterStackWalkImpl(Class<?> c) {
- return stackWalkImplClasses.contains(c) ||
- c.getName().startsWith("java.util.stream.");
- }
-
- // MethodHandle frames are not hidden and CallerClassFinder has
- // to filter them out
- private static boolean isMethodHandleFrame(Class<?> c) {
- return c.getName().startsWith("java.lang.invoke.");
- }
-
- private static boolean isReflectionFrame(Class<?> c) {
- if (c.getName().startsWith("sun.reflect") &&
- !sun.reflect.MethodAccessor.class.isAssignableFrom(c)) {
- throw new InternalError("Not sun.reflect.MethodAccessor: " + c.toString());
- }
- // ## should filter all @Hidden frames?
- return c == Method.class ||
- sun.reflect.MethodAccessor.class.isAssignableFrom(c) ||
- c.getName().startsWith("java.lang.invoke.LambdaForm");
- }
-
- private static boolean getProperty(String key, boolean value) {
- String s = AccessController.doPrivileged(new PrivilegedAction<>() {
- @Override
- public String run() {
- return System.getProperty(key);
- }
- });
- if (s != null) {
- return Boolean.valueOf(s);
- }
- return value;
- }
-}
--- a/jdk/src/java.base/share/classes/java/lang/StackWalker.java Tue Nov 24 04:46:04 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,563 +0,0 @@
-/*
- * Copyright (c) 2015, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package java.lang;
-
-import sun.reflect.CallerSensitive;
-
-import java.util.*;
-import java.util.function.Consumer;
-import java.util.function.Function;
-import java.util.stream.Stream;
-
-/**
- * A stack walker.
- *
- * <p> The {@link StackWalker#walk walk} method opens a sequential stream
- * of {@link StackFrame StackFrame}s for the current thread and then applies
- * the given function to walk the {@code StackFrame} stream.
- * The stream reports stack frame elements in order, from the top most frame
- * that represents the execution point at which the stack was generated to
- * the bottom most frame.
- * The {@code StackFrame} stream is closed when the {@code walk} method returns.
- * If an attempt is made to reuse the closed stream,
- * {@code IllegalStateException} will be thrown.
- *
- * <p> The {@linkplain Option <em>stack walking options</em>} of a
- * {@code StackWalker} determines the information of
- * {@link StackFrame StackFrame} objects to be returned.
- * By default, stack frames of the reflection API and implementation
- * classes are {@linkplain Option#SHOW_HIDDEN_FRAMES hidden}
- * and {@code StackFrame}s have the class name and method name
- * available but not the {@link StackFrame#getDeclaringClass() Class reference}.
- *
- * <p> {@code StackWalker} is thread-safe. Multiple threads can share
- * a single {@code StackWalker} object to traverse its own stack.
- * A permission check is performed when a {@code StackWalker} is created,
- * according to the options it requests.
- * No further permission check is done at stack walking time.
- *
- * @apiNote
- * Examples
- *
- * <p>1. To find the first caller filtering a known list of implementation class:
- * <pre>{@code
- * StackWalker walker = StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE);
- * Optional<Class<?>> callerClass = walker.walk(s ->
- * s.map(StackFrame::getDeclaringClass)
- * .filter(interestingClasses::contains)
- * .findFirst());
- * }</pre>
- *
- * <p>2. To snapshot the top 10 stack frames of the current thread,
- * <pre>{@code
- * List<StackFrame> stack = StackWalker.getInstance().walk(s ->
- * s.limit(10).collect(Collectors.toList()));
- * }</pre>
- *
- * Unless otherwise noted, passing a {@code null} argument to a
- * constructor or method in this {@code StackWalker} class
- * will cause a {@link NullPointerException NullPointerException}
- * to be thrown.
- *
- * @since 1.9
- */
-public final class StackWalker {
- /**
- * A {@code StackFrame} object represents a method invocation returned by
- * {@link StackWalker}.
- *
- * <p> The {@link #getDeclaringClass()} method may be unsupported as determined
- * by the {@linkplain Option stack walking options} of a {@linkplain
- * StackWalker stack walker}.
- *
- * @since 1.9
- * @jvms 2.6
- */
- public static interface StackFrame {
- /**
- * Gets the <a href="ClassLoader.html#name">binary name</a>
- * of the declaring class of the method represented by this stack frame.
- *
- * @return the binary name of the declaring class of the method
- * represented by this stack frame
- *
- * @jls 13.1 The Form of a Binary
- */
- public String getClassName();
-
- /**
- * Gets the name of the method represented by this stack frame.
- * @return the name of the method represented by this stack frame
- */
- public String getMethodName();
-
- /**
- * Gets the declaring {@code Class} for the method represented by
- * this stack frame.
- *
- * @return the declaring {@code Class} of the method represented by
- * this stack frame
- *
- * @throws UnsupportedOperationException if this {@code StackWalker}
- * is not configured with {@link Option#RETAIN_CLASS_REFERENCE
- * Option.RETAIN_CLASS_REFERENCE}.
- */
- public Class<?> getDeclaringClass();
-
- /**
- * Returns the name of the source file containing the execution point
- * represented by this stack frame. Generally, this corresponds
- * to the {@code SourceFile} attribute of the relevant {@code class}
- * file as defined by <cite>The Java Virtual Machine Specification</cite>.
- * In some systems, the name may refer to some source code unit
- * other than a file, such as an entry in a source repository.
- *
- * @return the name of the file containing the execution point
- * represented by this stack frame, or empty {@code Optional}
- * is unavailable.
- *
- * @jvms 4.7.10 The {@code SourceFile} Attribute
- */
- public Optional<String> getFileName();
-
- /**
- * Returns the line number of the source line containing the execution
- * point represented by this stack frame. Generally, this is
- * derived from the {@code LineNumberTable} attribute of the relevant
- * {@code class} file as defined by <cite>The Java Virtual Machine
- * Specification</cite>.
- *
- * @return the line number of the source line containing the execution
- * point represented by this stack frame, or empty
- * {@code Optional} if this information is unavailable.
- *
- * @jvms 4.7.12 The {@code LineNumberTable} Attribute
- */
- public OptionalInt getLineNumber();
-
- /**
- * Returns {@code true} if the method containing the execution point
- * represented by this stack frame is a native method.
- *
- * @return {@code true} if the method containing the execution point
- * represented by this stack frame is a native method.
- */
- public boolean isNativeMethod();
-
- /**
- * Gets a {@code StackTraceElement} for this stack frame.
- *
- * @return {@code StackTraceElement} for this stack frame.
- *
- * */
- public default StackTraceElement toStackTraceElement() {
- int lineNumber = isNativeMethod() ? -2
- : getLineNumber().orElse(-1);
- return new StackTraceElement(getClassName(), getMethodName(),
- getFileName().orElse(null),
- lineNumber);
- }
- }
-
- /**
- * Stack walker option to configure the {@linkplain StackFrame stack frame}
- * information obtained by a {@code StackWalker}.
- *
- * @since 1.9
- */
- public enum Option {
- /**
- * Retains {@code Class} object in {@code StackFrame}s
- * walked by this {@code StackWalker}.
- *
- * <p> A {@code StackWalker} configured with this option will support
- * {@link StackWalker#getCallerClass()} and
- * {@link StackFrame#getDeclaringClass() StackFrame.getDeclaringClass()}.
- */
- RETAIN_CLASS_REFERENCE,
- /**
- * Shows all reflection frames.
- *
- * <p>By default, reflection frames are hidden. This includes the
- * {@link java.lang.reflect.Method#invoke} method
- * and the reflection implementation classes. A {@code StackWalker} with
- * this {@code SHOW_REFLECT_FRAMES} option will show all reflection frames.
- * The {@link #SHOW_HIDDEN_FRAMES} option can also be used to show all
- * reflection frames and it will also show other hidden frames that
- * are implementation-specific.
- */
- SHOW_REFLECT_FRAMES,
- /**
- * Shows all hidden frames.
- *
- * <p>A Java Virtual Machine implementation may hide implementation
- * specific frames in addition to {@linkplain #SHOW_REFLECT_FRAMES
- * reflection frames}. A {@code StackWalker} with this {@code SHOW_HIDDEN_FRAMES}
- * option will show all hidden frames (including reflection frames).
- */
- SHOW_HIDDEN_FRAMES;
- }
-
- enum ExtendedOption {
- /**
- * Obtain monitors, locals and operands.
- */
- LOCALS_AND_OPERANDS
- };
-
- static final EnumSet<Option> DEFAULT_EMPTY_OPTION = EnumSet.noneOf(Option.class);
-
- private final static StackWalker DEFAULT_WALKER =
- new StackWalker(DEFAULT_EMPTY_OPTION);
-
- private final Set<Option> options;
- private final ExtendedOption extendedOption;
- private final int estimateDepth;
-
- /**
- * Returns a {@code StackWalker} instance.
- *
- * <p> This {@code StackWalker} is configured to skip all
- * {@linkplain Option#SHOW_HIDDEN_FRAMES hidden frames} and
- * no {@linkplain Option#RETAIN_CLASS_REFERENCE class reference} is retained.
- *
- * @return a {@code StackWalker} configured to skip all
- * {@linkplain Option#SHOW_HIDDEN_FRAMES hidden frames} and
- * no {@linkplain Option#RETAIN_CLASS_REFERENCE class reference} is retained.
- *
- */
- public static StackWalker getInstance() {
- // no permission check needed
- return DEFAULT_WALKER;
- }
-
- /**
- * Returns a {@code StackWalker} instance with the given option specifying
- * the stack frame information it can access.
- *
- * <p>
- * If a security manager is present and the given {@code option} is
- * {@link Option#RETAIN_CLASS_REFERENCE Option.RETAIN_CLASS_REFERENCE},
- * it calls its {@link SecurityManager#checkPermission checkPermission}
- * method for {@code StackFramePermission("retainClassReference")}.
- *
- * @param option {@link Option stack walking option}
- *
- * @return a {@code StackWalker} configured with the given option
- *
- * @throws SecurityException if a security manager exists and its
- * {@code checkPermission} method denies access.
- */
- public static StackWalker getInstance(Option option) {
- return getInstance(EnumSet.of(Objects.requireNonNull(option)));
- }
-
- /**
- * Returns a {@code StackWalker} instance with the given {@code options} specifying
- * the stack frame information it can access. If the given {@code options}
- * is empty, this {@code StackWalker} is configured to skip all
- * {@linkplain Option#SHOW_HIDDEN_FRAMES hidden frames} and no
- * {@linkplain Option#RETAIN_CLASS_REFERENCE class reference} is retained.
- *
- * <p>
- * If a security manager is present and the given {@code options} contains
- * {@link Option#RETAIN_CLASS_REFERENCE Option.RETAIN_CLASS_REFERENCE},
- * it calls its {@link SecurityManager#checkPermission checkPermission}
- * method for {@code StackFramePermission("retainClassReference")}.
- *
- * @param options {@link Option stack walking option}
- *
- * @return a {@code StackWalker} configured with the given options
- *
- * @throws SecurityException if a security manager exists and its
- * {@code checkPermission} method denies access.
- */
- public static StackWalker getInstance(Set<Option> options) {
- if (options.isEmpty()) {
- return DEFAULT_WALKER;
- }
-
- checkPermission(options);
- return new StackWalker(toEnumSet(options));
- }
-
- /**
- * Returns a {@code StackWalker} instance with the given {@ocde options} specifying
- * the stack frame information it can access. If the given {@ocde options}
- * is empty, this {@code StackWalker} is configured to skip all
- * {@linkplain Option#SHOW_HIDDEN_FRAMES hidden frames} and no
- * {@linkplain Option#RETAIN_CLASS_REFERENCE class reference} is retained.
- *
- * <p>
- * If a security manager is present and the given {@code options} contains
- * {@link Option#RETAIN_CLASS_REFERENCE Option.RETAIN_CLASS_REFERENCE},
- * it calls its {@link SecurityManager#checkPermission checkPermission}
- * method for {@code StackFramePermission("retainClassReference")}.
- *
- * <p>
- * The {@code estimateDepth} specifies the estimate number of stack frames
- * this {@code StackWalker} will traverse that the {@code StackWalker} could
- * use as a hint for the buffer size.
- *
- * @param options {@link Option stack walking options}
- * @param estimateDepth Estimate number of stack frames to be traversed.
- *
- * @return a {@code StackWalker} configured with the given options
- *
- * @throws IllegalArgumentException if {@code estimateDepth <= 0}
- * @throws SecurityException if a security manager exists and its
- * {@code checkPermission} method denies access.
- */
- public static StackWalker getInstance(Set<Option> options, int estimateDepth) {
- if (estimateDepth <= 0) {
- throw new IllegalArgumentException("estimateDepth must be > 0");
- }
- checkPermission(options);
- return new StackWalker(toEnumSet(options), estimateDepth);
- }
-
- // ----- private constructors ------
- private StackWalker(EnumSet<Option> options) {
- this(options, 0, null);
- }
- private StackWalker(EnumSet<Option> options, int estimateDepth) {
- this(options, estimateDepth, null);
- }
- private StackWalker(EnumSet<Option> options, int estimateDepth, ExtendedOption extendedOption) {
- this.options = options;
- this.estimateDepth = estimateDepth;
- this.extendedOption = extendedOption;
- }
-
- private static void checkPermission(Set<Option> options) {
- Objects.requireNonNull(options);
- SecurityManager sm = System.getSecurityManager();
- if (sm != null) {
- if (options.contains(Option.RETAIN_CLASS_REFERENCE)) {
- sm.checkPermission(new StackFramePermission("retainClassReference"));
- }
- }
- }
-
- /*
- * Returns a defensive copy
- */
- private static EnumSet<Option> toEnumSet(Set<Option> options) {
- Objects.requireNonNull(options);
- if (options.isEmpty()) {
- return DEFAULT_EMPTY_OPTION;
- } else {
- return EnumSet.copyOf(options);
- }
- }
-
- /**
- * Applies the given function to the stream of {@code StackFrame}s
- * for the current thread, traversing from the top frame of the stack,
- * which is the method calling this {@code walk} method.
- *
- * <p>The {@code StackFrame} stream will be closed when
- * this method returns. When a closed {@code Stream<StackFrame>} object
- * is reused, {@code IllegalStateException} will be thrown.
- *
- * @apiNote
- * For example, to find the first 10 calling frames, first skipping those frames
- * whose declaring class is in package {@code com.foo}:
- * <blockquote>
- * <pre>{@code
- * List<StackFrame> frames = StackWalker.getInstance().walk(s ->
- * s.dropWhile(f -> f.getClassName().startsWith("com.foo."))
- * .limit(10)
- * .collect(Collectors.toList()));
- * }</pre></blockquote>
- *
- * <p>This method takes a {@code Function} accepting a {@code Stream<StackFrame>},
- * rather than returning a {@code Stream<StackFrame>} and allowing the
- * caller to directly manipulate the stream. The Java virtual machine is
- * free to reorganize a thread's control stack, for example, via
- * deoptimization. By taking a {@code Function} parameter, this method
- * allows access to stack frames through a stable view of a thread's control
- * stack.
- *
- * <p>Parallel execution is effectively disabled and stream pipeline
- * execution will only occur on the current thread.
- *
- * @implNote The implementation stabilizes the stack by anchoring a frame
- * specific to the stack walking and ensures that the stack walking is
- * performed above the anchored frame. When the stream object is closed or
- * being reused, {@code IllegalStateException} will be thrown.
- *
- * @param function a function that takes a stream of
- * {@linkplain StackFrame stack frames} and returns a result.
- * @param <T> The type of the result of applying the function to the
- * stream of {@linkplain StackFrame stack frame}.
- *
- * @return the result of applying the function to the stream of
- * {@linkplain StackFrame stack frame}.
- */
- @CallerSensitive
- public <T> T walk(Function<? super Stream<StackFrame>, ? extends T> function) {
- // Returning a Stream<StackFrame> would be unsafe, as the stream could
- // be used to access the stack frames in an uncontrolled manner. For
- // example, a caller might pass a Spliterator of stack frames after one
- // or more frames had been traversed. There is no robust way to detect
- // whether the execution point when
- // Spliterator.tryAdvance(java.util.function.Consumer<? super T>) is
- // invoked is the exact same execution point where the stack frame
- // traversal is expected to resume.
-
- Objects.requireNonNull(function);
- return StackStreamFactory.makeStackTraverser(this, function)
- .walk();
- }
-
- /**
- * Performs the given action on each element of {@code StackFrame} stream
- * of the current thread, traversing from the top frame of the stack,
- * which is the method calling this {@code forEach} method.
- *
- * <p> This method is equivalent to calling
- * <blockquote>
- * {@code walk(s -> { s.forEach(action); return null; });}
- * </blockquote>
- *
- * @param action an action to be performed on each {@code StackFrame}
- * of the stack of the current thread
- */
- @CallerSensitive
- public void forEach(Consumer<? super StackFrame> action) {
- Objects.requireNonNull(action);
- StackStreamFactory.makeStackTraverser(this, s -> {
- s.forEach(action);
- return null;
- }).walk();
- }
-
- /**
- * 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
- * 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.
- *
- * <p> This method throws {@code UnsupportedOperationException}
- * if this {@code StackWalker} is not configured with
- * {@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;
- * {@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
- * class loader to load the resource bundle. The caller class in this example
- * is the {@code MyTool} class.
- *
- * <pre>{@code
- * class Util {
- * private final StackWalker walker = StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE);
- * public ResourceBundle getResourceBundle(String bundleName) {
- * Class<?> caller = walker.getCallerClass();
- * return ResourceBundle.getBundle(bundleName, Locale.getDefault(), caller.getClassLoader());
- * }
- * }
- *
- * class MyTool {
- * private final Util util = new Util();
- * private void init() {
- * ResourceBundle rb = util.getResourceBundle("mybundle");
- * }
- * }
- * }</pre>
- *
- * An equivalent way to find the caller class using the
- * {@link StackWalker#walk walk} method is as follows
- * (filtering the reflection frames, {@code MethodHandle} and hidden frames
- * not shown below):
- * <pre>{@code
- * Optional<Class<?>> caller = walker.walk(s ->
- * s.map(StackFrame::getDeclaringClass)
- * .skip(2)
- * .findFirst());
- * }</pre>
- *
- * 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 IllegalStateException} is thrown.
- *
- * @return {@code Class} object of the caller's caller invoking this method.
- *
- * @throws UnsupportedOperationException if this {@code StackWalker}
- * is not configured with {@link Option#RETAIN_CLASS_REFERENCE
- * Option.RETAIN_CLASS_REFERENCE}.
- * @throws IllegalStateException if there is no caller frame, i.e.
- * when this {@code getCallerClass} method is called from a method
- * which is the last frame on the stack.
- */
- @CallerSensitive
- public Class<?> getCallerClass() {
- if (!options.contains(Option.RETAIN_CLASS_REFERENCE)) {
- throw new UnsupportedOperationException("This stack walker " +
- "does not have RETAIN_CLASS_REFERENCE access");
- }
-
- return StackStreamFactory.makeCallerFinder(this).findCaller();
- }
-
- // ---- package access ----
- static StackWalker newInstanceNoCheck(EnumSet<Option> options) {
- return new StackWalker(options, 0, null);
- }
-
- static StackWalker newInstance(Set<Option> options, ExtendedOption extendedOption) {
- checkPermission(options);
- return new StackWalker(toEnumSet(options), 0, extendedOption);
- }
-
- int estimateDepth() {
- return estimateDepth;
- }
-
- boolean hasOption(Option option) {
- return options.contains(option);
- }
-
- boolean hasLocalsOperandsOption() {
- return extendedOption == ExtendedOption.LOCALS_AND_OPERANDS;
- }
-
- void ensureAccessEnabled(Option access) {
- if (!hasOption(access)) {
- throw new UnsupportedOperationException("No access to " + access +
- ": " + options.toString());
- }
- }
-}
--- a/jdk/src/java.base/share/classes/java/lang/System.java Tue Nov 24 04:46:04 2015 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/System.java Tue Nov 24 10:12:32 2015 -0800
@@ -28,11 +28,11 @@
import java.lang.reflect.Executable;
import java.lang.annotation.Annotation;
import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
import java.util.Properties;
import java.util.PropertyPermission;
import java.util.Map;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.nio.channels.Channel;
import java.nio.channels.spi.SelectorProvider;
import java.util.Objects;
@@ -1896,6 +1896,12 @@
public void registerShutdownHook(int slot, boolean registerShutdownInProgress, Runnable hook) {
Shutdown.add(slot, registerShutdownInProgress, hook);
}
+ public int getStackTraceDepth(Throwable t) {
+ return t.getStackTraceDepth();
+ }
+ public StackTraceElement getStackTraceElement(Throwable t, int i) {
+ return t.getStackTraceElement(i);
+ }
public String newStringUnsafe(char[] chars) {
return new String(chars, true);
}
--- a/jdk/src/java.base/share/classes/java/lang/Thread.java Tue Nov 24 04:46:04 2015 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/Thread.java Tue Nov 24 10:12:32 2015 -0800
@@ -1329,9 +1329,11 @@
/**
* Prints a stack trace of the current thread to the standard error stream.
* This method is used only for debugging.
+ *
+ * @see Throwable#printStackTrace()
*/
public static void dumpStack() {
- StackStreamFactory.makeStackTrace().printStackTrace(System.err);
+ new Exception("Stack trace").printStackTrace();
}
/**
@@ -1554,7 +1556,7 @@
return stackTrace;
} else {
// Don't need JVM help for current thread
- return StackStreamFactory.makeStackTrace().getStackTraceElements();
+ return (new Exception()).getStackTrace();
}
}
--- a/jdk/src/java.base/share/classes/java/lang/Throwable.java Tue Nov 24 04:46:04 2015 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/Throwable.java Tue Nov 24 10:12:32 2015 -0800
@@ -24,8 +24,6 @@
*/
package java.lang;
-import sun.misc.VM;
-
import java.io.*;
import java.util.*;
@@ -780,11 +778,7 @@
public synchronized Throwable fillInStackTrace() {
if (stackTrace != null ||
backtrace != null /* Out of protocol state */ ) {
- if (backtrace == null && StackStreamFactory.useStackTrace(this)) {
- backtrace = StackStreamFactory.makeStackTrace(this);
- } else {
- fillInStackTrace(0);
- }
+ fillInStackTrace(0);
stackTrace = UNASSIGNED_STACK;
}
return this;
@@ -825,14 +819,10 @@
// backtrace if this is the first call to this method
if (stackTrace == UNASSIGNED_STACK ||
(stackTrace == null && backtrace != null) /* Out of protocol state */) {
- if (backtrace instanceof StackStreamFactory.StackTrace) {
- stackTrace = ((StackStreamFactory.StackTrace)backtrace).getStackTraceElements();
- } else {
- int depth = getStackTraceDepth();
- stackTrace = new StackTraceElement[depth];
- for (int i = 0; i < depth; i++)
- stackTrace[i] = getStackTraceElement(i);
- }
+ int depth = getStackTraceDepth();
+ stackTrace = new StackTraceElement[depth];
+ for (int i=0; i < depth; i++)
+ stackTrace[i] = getStackTraceElement(i);
} else if (stackTrace == null) {
return UNASSIGNED_STACK;
}
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java Tue Nov 24 04:46:04 2015 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java Tue Nov 24 10:12:32 2015 -0800
@@ -1077,13 +1077,4 @@
// System.out.println("Hello world! My methods are:");
// System.out.println(Factory.INSTANCE.getMethods(MemberName.class, true, null));
// }
-
- static {
- // Allow privileged classes outside of java.lang
- jdk.internal.misc.SharedSecrets.setJavaLangInvokeAccess(new jdk.internal.misc.JavaLangInvokeAccess() {
- public Object newMemberName() {
- return new MemberName();
- }
- });
- }
}
--- a/jdk/src/java.base/share/classes/jdk/internal/logger/SimpleConsoleLogger.java Tue Nov 24 04:46:04 2015 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/logger/SimpleConsoleLogger.java Tue Nov 24 10:12:32 2015 -0800
@@ -31,12 +31,13 @@
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.time.ZonedDateTime;
-import java.util.Optional;
import java.util.ResourceBundle;
import java.util.function.Function;
import java.lang.System.Logger;
-import java.util.function.Predicate;
+import java.lang.System.Logger.Level;
import java.util.function.Supplier;
+import jdk.internal.misc.JavaLangAccess;
+import jdk.internal.misc.SharedSecrets;
import sun.util.logging.PlatformLogger;
import sun.util.logging.PlatformLogger.ConfigurableBridge.LoggerConfiguration;
@@ -168,55 +169,42 @@
// Returns the caller's class and method's name; best effort
// if cannot infer, return the logger's name.
private String getCallerInfo() {
- Optional<StackWalker.StackFrame> frame = new CallerFinder().get();
- if (frame.isPresent()) {
- return frame.get().getClassName() + " " + frame.get().getMethodName();
- } else {
- return name;
- }
- }
+ String sourceClassName = null;
+ String sourceMethodName = null;
+
+ JavaLangAccess access = SharedSecrets.getJavaLangAccess();
+ Throwable throwable = new Throwable();
+ int depth = access.getStackTraceDepth(throwable);
- /*
- * CallerFinder is a stateful predicate.
- */
- static final class CallerFinder implements Predicate<StackWalker.StackFrame> {
- static final StackWalker WALKER = StackWalker.getInstance();
-
- /**
- * Returns StackFrame of the caller's frame.
- * @return StackFrame of the caller's frame.
- */
- Optional<StackWalker.StackFrame> get() {
- return WALKER.walk((s) -> s.filter(this).findFirst());
+ String logClassName = "sun.util.logging.PlatformLogger";
+ String simpleLoggerClassName = "jdk.internal.logger.SimpleConsoleLogger";
+ boolean lookingForLogger = true;
+ for (int ix = 0; ix < depth; ix++) {
+ // Calling getStackTraceElement directly prevents the VM
+ // from paying the cost of building the entire stack frame.
+ final StackTraceElement frame =
+ access.getStackTraceElement(throwable, ix);
+ final String cname = frame.getClassName();
+ if (lookingForLogger) {
+ // Skip all frames until we have found the first logger frame.
+ if (cname.equals(logClassName) || cname.equals(simpleLoggerClassName)) {
+ lookingForLogger = false;
+ }
+ } else {
+ if (skipLoggingFrame(cname)) continue;
+ if (!cname.equals(logClassName) && !cname.equals(simpleLoggerClassName)) {
+ // We've found the relevant frame.
+ sourceClassName = cname;
+ sourceMethodName = frame.getMethodName();
+ break;
+ }
+ }
}
- private boolean lookingForLogger = true;
- /**
- * Returns true if we have found the caller's frame, false if the frame
- * must be skipped.
- *
- * @param t The frame info.
- * @return true if we have found the caller's frame, false if the frame
- * must be skipped.
- */
- @Override
- public boolean test(StackWalker.StackFrame t) {
- final String cname = t.getClassName();
- // We should skip all frames until we have found the logger,
- // because these frames could be frames introduced by e.g. custom
- // sub classes of Handler.
- if (lookingForLogger) {
- // Skip all frames until we have found the first logger frame.
- lookingForLogger = !isLoggerImplFrame(cname);
- return false;
- }
- // We've found the relevant frame.
- return !skipLoggingFrame(cname) && !isLoggerImplFrame(cname);
- }
-
- private boolean isLoggerImplFrame(String cname) {
- return (cname.equals("sun.util.logging.PlatformLogger") ||
- cname.equals("jdk.internal.logger.SimpleConsoleLogger"));
+ if (sourceClassName != null) {
+ return sourceClassName + " " + sourceMethodName;
+ } else {
+ return name;
}
}
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangAccess.java Tue Nov 24 04:46:04 2015 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangAccess.java Tue Nov 24 10:12:32 2015 -0800
@@ -103,6 +103,16 @@
void registerShutdownHook(int slot, boolean registerShutdownInProgress, Runnable hook);
/**
+ * Returns the number of stack frames represented by the given throwable.
+ */
+ int getStackTraceDepth(Throwable t);
+
+ /**
+ * Returns the ith StackTraceElement for the given throwable.
+ */
+ StackTraceElement getStackTraceElement(Throwable t, int i);
+
+ /**
* Returns a new string backed by the provided character array. The
* character array is not copied and must never be modified after the
* String is created, in order to fulfill String's contract.
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangInvokeAccess.java Tue Nov 24 04:46:04 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2015, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.internal.misc;
-
-public interface JavaLangInvokeAccess {
- /**
- * Create a new MemberName instance
- */
- Object newMemberName();
-}
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java Tue Nov 24 04:46:04 2015 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java Tue Nov 24 10:12:32 2015 -0800
@@ -45,7 +45,6 @@
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static JavaUtilJarAccess javaUtilJarAccess;
private static JavaLangAccess javaLangAccess;
- private static JavaLangInvokeAccess javaLangInvokeAccess;
private static JavaLangRefAccess javaLangRefAccess;
private static JavaIOAccess javaIOAccess;
private static JavaNetAccess javaNetAccess;
@@ -81,20 +80,6 @@
return javaLangAccess;
}
- public static void setJavaLangInvokeAccess(JavaLangInvokeAccess jlia) {
- javaLangInvokeAccess = jlia;
- }
-
- public static JavaLangInvokeAccess getJavaLangInvokeAccess() {
- if (javaLangInvokeAccess == null) {
- try {
- Class<?> c = Class.forName("java.lang.invoke.MemberName");
- unsafe.ensureClassInitialized(c);
- } catch (ClassNotFoundException e) {};
- }
- return javaLangInvokeAccess;
- }
-
public static void setJavaLangRefAccess(JavaLangRefAccess jlra) {
javaLangRefAccess = jlra;
}
--- a/jdk/src/java.base/share/native/include/jvm.h Tue Nov 24 04:46:04 2015 +0000
+++ b/jdk/src/java.base/share/native/include/jvm.h Tue Nov 24 10:12:32 2015 -0800
@@ -178,37 +178,6 @@
JVM_GetStackTraceElement(JNIEnv *env, jobject throwable, jint index);
/*
- * java.lang.StackWalker
- */
-enum {
- JVM_STACKWALK_FILL_CLASS_REFS_ONLY = 0x2,
- JVM_STACKWALK_FILTER_FILL_IN_STACK_TRACE = 0x10,
- JVM_STACKWALK_SHOW_HIDDEN_FRAMES = 0x20,
- JVM_STACKWALK_FILL_LIVE_STACK_FRAMES = 0x100
-};
-
-JNIEXPORT jobject JNICALL
-JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mode,
- jint skip_frames, jint frame_count, jint start_index,
- jobjectArray classes,
- jobjectArray frames);
-
-JNIEXPORT jint JNICALL
-JVM_MoreStackWalk(JNIEnv *env, jobject stackStream, jlong mode, jlong anchor,
- jint frame_count, jint start_index,
- jobjectArray classes,
- jobjectArray frames);
-
-JNIEXPORT void JNICALL
-JVM_FillStackFrames(JNIEnv* env, jclass cls,
- jint start_index,
- jobjectArray stackFrames,
- jint from_index, jint toIndex);
-
-JNIEXPORT void JNICALL
-JVM_SetMethodInfo(JNIEnv* env, jobject frame);
-
-/*
* java.lang.Thread
*/
JNIEXPORT void JNICALL
--- a/jdk/src/java.base/share/native/libjava/StackFrameInfo.c Tue Nov 24 04:46:04 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2015, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * Implementation of class StackFrameInfo
- */
-
-#include <stdio.h>
-#include <signal.h>
-
-#include "jni.h"
-#include "jvm.h"
-
-#include "java_lang_StackFrameInfo.h"
-
-
-/*
- * Class: java_lang_StackFrameInfo
- * Method: fillInStackFrames
- * Signature: (I[Ljava/lang/Object;[Ljava/lang/Object;II)V
- */
-JNIEXPORT void JNICALL Java_java_lang_StackFrameInfo_fillInStackFrames
- (JNIEnv *env, jclass dummy, jint startIndex,
- jobjectArray stackFrames, jint fromIndex, jint toIndex) {
- JVM_FillStackFrames(env, dummy, startIndex,
- stackFrames, fromIndex, toIndex);
-}
-
-/*
- * Class: java_lang_StackFrameInfo
- * Method: setMethodInfo
- * Signature: (Ljava/lang/Class;)V
- */
-JNIEXPORT void JNICALL Java_java_lang_StackFrameInfo_setMethodInfo
- (JNIEnv *env, jobject stackframeinfo) {
- JVM_SetMethodInfo(env, stackframeinfo);
-}
--- a/jdk/src/java.base/share/native/libjava/StackStreamFactory.c Tue Nov 24 04:46:04 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2015, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * Implementation of class StackStreamfactory and AbstractStackWalker
- */
-
-#include <stdio.h>
-#include <signal.h>
-
-#include "jni.h"
-#include "jvm.h"
-
-#include "java_lang_StackStreamFactory.h"
-#include "java_lang_StackStreamFactory_AbstractStackWalker.h"
-
-/*
- * Class: java_lang_StackStreamFactory
- * Method: checkStackWalkModes
- * Signature: ()
- */
-JNIEXPORT jboolean JNICALL Java_java_lang_StackStreamFactory_checkStackWalkModes
- (JNIEnv *env, jclass dummy)
-{
- return JVM_STACKWALK_FILL_CLASS_REFS_ONLY == java_lang_StackStreamFactory_FILL_CLASS_REFS_ONLY &&
- JVM_STACKWALK_FILTER_FILL_IN_STACK_TRACE == java_lang_StackStreamFactory_FILTER_FILL_IN_STACKTRACE &&
- JVM_STACKWALK_SHOW_HIDDEN_FRAMES == java_lang_StackStreamFactory_SHOW_HIDDEN_FRAMES &&
- JVM_STACKWALK_FILL_LIVE_STACK_FRAMES == java_lang_StackStreamFactory_FILL_LIVE_STACK_FRAMES;
-}
-
-/*
- * Class: java_lang_StackStreamFactory_AbstractStackWalker
- * Method: callStackWalk
- * Signature: (JIII[Ljava/lang/Class;[Ljava/lang/StackWalker/StackFrame;)Ljava/lang/Object;
- */
-JNIEXPORT jobject JNICALL Java_java_lang_StackStreamFactory_00024AbstractStackWalker_callStackWalk
- (JNIEnv *env, jobject stackstream, jlong mode, jint skipFrames, jint batchSize, jint startIndex,
- jobjectArray classes, jobjectArray frames)
-{
- return JVM_CallStackWalk(env, stackstream, mode, skipFrames, batchSize,
- startIndex, classes, frames);
-}
-
-/*
- * Class: java_lang_StackStreamFactory_AbstractStackWalker
- * Method: fetchStackFrames
- * Signature: (JJII[Ljava/lang/Class;[Ljava/lang/StackWalker/StackFrame;)I
- */
-JNIEXPORT jint JNICALL Java_java_lang_StackStreamFactory_00024AbstractStackWalker_fetchStackFrames
- (JNIEnv *env, jobject stackstream, jlong mode, jlong anchor,
- jint batchSize, jint startIndex,
- jobjectArray classes, jobjectArray frames)
-{
- return JVM_MoreStackWalk(env, stackstream, mode, anchor, batchSize,
- startIndex, classes, frames);
-}
--- a/jdk/src/java.logging/share/classes/java/util/logging/LogRecord.java Tue Nov 24 04:46:04 2015 +0000
+++ b/jdk/src/java.logging/share/classes/java/util/logging/LogRecord.java Tue Nov 24 10:12:32 2015 -0800
@@ -30,8 +30,9 @@
import java.util.concurrent.atomic.AtomicLong;
import java.io.*;
import java.time.Clock;
-import java.util.function.Predicate;
+import jdk.internal.misc.JavaLangAccess;
+import jdk.internal.misc.SharedSecrets;
import static jdk.internal.logger.SimpleConsoleLogger.skipLoggingFrame;
/**
@@ -660,58 +661,42 @@
//
private void inferCaller() {
needToInferCaller = false;
- // Skip all frames until we have found the first logger frame.
- Optional<StackWalker.StackFrame> frame = new CallerFinder().get();
- frame.ifPresent(f -> {
- setSourceClassName(f.getClassName());
- setSourceMethodName(f.getMethodName());
- });
+ JavaLangAccess access = SharedSecrets.getJavaLangAccess();
+ Throwable throwable = new Throwable();
+ int depth = access.getStackTraceDepth(throwable);
+ boolean lookingForLogger = true;
+ for (int ix = 0; ix < depth; ix++) {
+ // Calling getStackTraceElement directly prevents the VM
+ // from paying the cost of building the entire stack frame.
+ StackTraceElement frame =
+ access.getStackTraceElement(throwable, ix);
+ String cname = frame.getClassName();
+ boolean isLoggerImpl = isLoggerImplFrame(cname);
+ if (lookingForLogger) {
+ // Skip all frames until we have found the first logger frame.
+ if (isLoggerImpl) {
+ lookingForLogger = false;
+ }
+ } else {
+ if (!isLoggerImpl) {
+ // skip logging/logger infrastructure and reflection calls
+ if (!skipLoggingFrame(cname)) {
+ // We've found the relevant frame.
+ setSourceClassName(cname);
+ setSourceMethodName(frame.getMethodName());
+ return;
+ }
+ }
+ }
+ }
// We haven't found a suitable frame, so just punt. This is
// OK as we are only committed to making a "best effort" here.
}
- /*
- * CallerFinder is a stateful predicate.
- */
- static final class CallerFinder implements Predicate<StackWalker.StackFrame> {
- static final StackWalker WALKER = StackWalker.getInstance();
-
- /**
- * Returns StackFrame of the caller's frame.
- * @return StackFrame of the caller's frame.
- */
- Optional<StackWalker.StackFrame> get() {
- return WALKER.walk((s) -> s.filter(this).findFirst());
- }
-
- private boolean lookingForLogger = true;
- /**
- * Returns true if we have found the caller's frame, false if the frame
- * must be skipped.
- *
- * @param t The frame info.
- * @return true if we have found the caller's frame, false if the frame
- * must be skipped.
- */
- @Override
- public boolean test(StackWalker.StackFrame t) {
- final String cname = t.getClassName();
- // We should skip all frames until we have found the logger,
- // because these frames could be frames introduced by e.g. custom
- // sub classes of Handler.
- if (lookingForLogger) {
- // the log record could be created for a platform logger
- lookingForLogger = !isLoggerImplFrame(cname);
- return false;
- }
- // skip logging/logger infrastructure and reflection calls
- return !skipLoggingFrame(cname);
- }
-
- private boolean isLoggerImplFrame(String cname) {
- return (cname.equals("java.util.logging.Logger") ||
- cname.startsWith("sun.util.logging.PlatformLogger"));
- }
+ private boolean isLoggerImplFrame(String cname) {
+ // the log record could be created for a platform logger
+ return (cname.equals("java.util.logging.Logger") ||
+ cname.startsWith("sun.util.logging.PlatformLogger"));
}
}
--- a/jdk/test/java/lang/StackWalker/AcrossThreads.java Tue Nov 24 04:46:04 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,227 +0,0 @@
-/*
- * Copyright (c) 2015, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8140450
- * @summary Verify that StackWalker works well when one instance of StackWalker
- * is used by several threads sequentially or concurrently.
- * @run testng AcrossThreads
- */
-
-import java.util.ArrayList;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import java.lang.StackWalker.StackFrame;
-import static java.lang.StackWalker.Option.*;
-
-import org.testng.annotations.*;
-import static org.testng.Assert.*;
-
-public class AcrossThreads {
- static final StackWalker WALKERS[] = new StackWalker[] {
- StackWalker.getInstance(RETAIN_CLASS_REFERENCE),
- StackWalker.getInstance(EnumSet.of(SHOW_REFLECT_FRAMES, RETAIN_CLASS_REFERENCE)),
- StackWalker.getInstance(EnumSet.of(SHOW_HIDDEN_FRAMES, RETAIN_CLASS_REFERENCE))
- };
-
- @DataProvider
- public StackWalker[][] walkerProvider() {
- return new StackWalker[][] {
- new StackWalker[] { WALKERS[0] },
- new StackWalker[] { WALKERS[1] },
- new StackWalker[] { WALKERS[2] }
- };
- }
-
- @Test(dataProvider = "walkerProvider")
- public void test(StackWalker walker) {
- Thread t1 = new T1(walker);
- // call methods of one instance of StackWalker sequentially in T1, T2, T3.
- t1.start();
- try {
- t1.join();
- } catch (InterruptedException e) { }
-
- List<Thread> threads = new ArrayList<Thread>();
- for (int i = 0; i < 100; i++) {
- threads.add(new T1(walker));
- threads.add(new T2(walker));
- threads.add(new T3(walker));
- }
- // call methods of one instance of StackWalker concurrently in several threads.
- threads.parallelStream().forEach(t -> {
- t.setDaemon(true);
- t.start();
- });
- threads.parallelStream().forEach(t -> {
- try {
- t.join();
- } catch (InterruptedException e) { }
- });
- }
-
- interface Consumer {
- final int LOOPS = 5;
-
- public void consume();
-
- default public void assertWalker(StackWalker walker, int n) {
- if (--n == 0) {
- Map<String, Integer> methods = new HashMap<String, Integer>();
- walker.forEach(f -> {
- Integer i = methods.putIfAbsent(f.getMethodName(), 1);
- if (i != null) {
- methods.put(f.getMethodName(), i + 1);
- }
- });
-
- // verify that walker.forEach(...) reaches the specified methods.
- assertTrue(methods.get("consume") == 1);
- assertTrue(methods.get("run") == 1);
- assertTrue(methods.get("assertWalker") == LOOPS);
-
- // verify that walker.walk(...) reaches the specified methods.
- assertTrue(walker.walk(s -> s.map(StackFrame::getMethodName)
- .filter(mn -> mn.equals("consume"))
- .count()) == 1);
- assertTrue(walker.walk(s -> s.map(StackFrame::getMethodName)
- .filter(mn -> mn.equals("run"))
- .count()) == 1);
- assertTrue(walker.walk(s -> s.map(StackFrame::getMethodName)
- .filter(mn -> mn.equals("assertWalker"))
- .count()) == LOOPS);
- } else {
- assertWalker(walker, n);
- }
- }
- }
-
- class T1 extends Thread implements Consumer {
- final StackWalker walker;
-
- public T1(StackWalker walker) {
- this.walker = walker;
- }
-
- public void run() {
- consume();
-
- Thread t2 = new T2(walker);
- t2.start();
- try {
- t2.join();
- } catch (InterruptedException e) { }
-
- consume();
- }
-
- public void consume() {
- assertWalker(walker, LOOPS);
-
- // verify walker.walk() reaches T1 class through methods run() and consume().
- assertTrue(walker.walk(s -> s.filter(f -> T1.class == f.getDeclaringClass())
- .count()) == 2);
-
- assertCallerClass(walker);
- assertEquals(T1.class, walker.getCallerClass());
- }
- }
-
- class T2 extends Thread implements Consumer {
- final StackWalker walker;
-
- public T2(StackWalker walker) {
- this.walker = walker;
- }
-
- public void run() {
- consume();
-
- Thread t3 = new T3(walker);
- t3.start();
- try {
- t3.join();
- } catch (InterruptedException e) { }
-
- consume();
- }
-
- public void consume() {
- assertWalker(walker, LOOPS);
-
- // verify walker.walk() reaches T2 class through methods run() and consume().
- assertTrue(walker.walk(s -> s.filter(f -> T2.class == f.getDeclaringClass())
- .count()) == 2);
- // verify T1 is not reached, even if call is invoked
- // from test()->T1.start()->T1.run()->T2
- assertTrue(walker.walk(s -> s.filter(f -> T1.class == f.getDeclaringClass())
- .count()) == 0);
-
- assertCallerClass(walker);
- assertEquals(T2.class, walker.getCallerClass());
- }
- }
-
- class T3 extends Thread implements Consumer {
- final StackWalker walker;
-
- public T3(StackWalker walker) {
- this.walker = walker;
- }
-
- public void run() {
- consume();
- }
-
- public void consume() {
- assertWalker(walker, LOOPS);
-
- // verify walker.walk() reaches T1 class through methods run() and consume().
- assertTrue(walker.walk(s -> s.filter(f -> T3.class == f.getDeclaringClass())
- .count()) == 2);
- // verify T1, T2 is not reached, even if call is invoked
- // from test() -> T1.start() -> T1.run() -> T2.start() -> T2.run() -> T3
- assertTrue(walker.walk(s -> s.filter(f -> T2.class == f.getDeclaringClass())
- .count()) == 0);
- assertTrue(walker.walk(s -> s.filter(f -> T1.class == f.getDeclaringClass())
- .count()) == 0);
-
- assertCallerClass(walker);
- assertEquals(T3.class, walker.getCallerClass());
- }
- }
-
- static void assertCallerClass(StackWalker walker) {
- // verify walker.getCallerClass() get the expected class.
- call(walker);
- }
-
- static void call(StackWalker walker) {
- Class<?> c = walker.getCallerClass();
- assertEquals(c, AcrossThreads.class);
- }
-}
--- a/jdk/test/java/lang/StackWalker/Basic.java Tue Nov 24 04:46:04 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-/*
- * Copyright (c) 2015, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8140450
- * @summary Basic test for the StackWalker::walk method
- * @run testng Basic
- */
-
-import java.lang.StackWalker.StackFrame;
-import java.util.List;
-import java.util.stream.Collectors;
-import static java.lang.StackWalker.Option.*;
-
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-
-public class Basic {
- private static boolean verbose = false;
-
- @DataProvider(name = "stackDepths")
- public static Object[][] stackDepths() {
- return new Object[][] {
- { new int[] { 12 }, new int[] { 4, 8, 12} },
- { new int[] { 18 }, new int[] { 8, 16, 20} },
- { new int[] { 32 }, new int[] { 16, 32, 64} },
- };
- }
-
- /**
- * For a stack of a given depth, it creates a StackWalker with an estimate.
- * Test walking different number of frames
- */
- @Test(dataProvider = "stackDepths")
- public static void test(int[] depth, int[] estimates) {
- Basic test = new Basic(depth[0]);
- for (int estimate : estimates) {
- test.walk(estimate);
- }
- }
-
- private final int depth;
- Basic(int depth) {
- this.depth = depth;
- }
-
- /*
- * Setup a stack builder with the expected stack depth
- * Walk the stack and count the frames.
- */
- void walk(int estimate) {
- int limit = Math.min(depth, 16);
- List<StackFrame> frames = new StackBuilder(depth, limit).build();
- System.out.format("depth=%d estimate=%d expected=%d walked=%d%n",
- depth, estimate, limit, frames.size());
- assertEquals(limit, frames.size());
- }
-
- class StackBuilder {
- private final int stackDepth;
- private final int limit;
- private int depth = 0;
- private List<StackFrame> result;
- StackBuilder(int stackDepth, int limit) {
- this.stackDepth = stackDepth; // build method;
- this.limit = limit;
- }
- List<StackFrame> build() {
- trace("build");
- m1();
- return result;
- }
- void m1() {
- trace("m1");
- m2();
- }
- void m2() {
- trace("m2");
- m3();
- }
- void m3() {
- trace("m3");
- m4();
- }
- void m4() {
- trace("m4");
- int remaining = stackDepth-depth-1;
- if (remaining >= 4) {
- m1();
- } else {
- filler(remaining);
- }
- }
- void filler(int i) {
- trace("filler");
- if (i == 0)
- walk();
- else
- filler(--i);
- }
-
- void walk() {
- StackWalker walker = StackWalker.getInstance(RETAIN_CLASS_REFERENCE);
- result = walker.walk(s -> s.limit(limit).collect(Collectors.toList()));
- }
- void trace(String methodname) {
- ++depth;
- if (verbose)
- System.out.format("%2d: %s%n", depth, methodname);
- }
- }
-
- static void assertEquals(int x, int y) {
- if (x != y) {
- throw new RuntimeException(x + " != " + y);
- }
- }
-}
--- a/jdk/test/java/lang/StackWalker/CallerFromMain.java Tue Nov 24 04:46:04 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,137 +0,0 @@
-/*
- * Copyright (c) 2015, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8140450
- * @library /lib/testlibrary
- * @build jdk.testlibrary.*
- * @summary Test if the getCallerClass method returns empty optional
- * @run main CallerFromMain exec
- */
-
-import jdk.testlibrary.ProcessTools;
-import jdk.testlibrary.OutputAnalyzer;
-
-public class CallerFromMain {
-
- private static final StackWalker sw = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
- public static void main(String[] args) throws Exception {
- if (args.length > 0) {
- ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, "CallerFromMain");
- OutputAnalyzer output = ProcessTools.executeProcess(pb);
- System.out.println(output.getOutput());
- output.shouldHaveExitValue(0);
- return;
- }
-
- // StackWalker::getCallerClass
- // CallerFromMain::main
- // no caller
- try {
- Class<?> c = sw.getCallerClass();
- throw new RuntimeException("UOE not thrown. Caller: " + c);
- } catch (IllegalStateException e) {}
-
- // StackWalker::getCallerClass
- // Runnable::run
- // Thread::run
- Thread t1 = new Thread(new Runnable() {
- @Override
- public void run() {
- Class<?> c = sw.getCallerClass();
- System.out.println("Call from Thread.run: " + c);
- assertThreadClassAsCaller(c);
- }
- });
- t1.setDaemon(true);
- t1.start();
-
- // StackWalker::getCallerClass
- // CallerFromMain::doit
- // Thread::run
- Thread t2 = new Thread(CallerFromMain::doit);
- t2.setDaemon(true);
- t2.start();
-
- // StackWalker::getCallerClass
- // MyRunnable::run
- // Thread::run
- Thread t3 = new Thread(new MyRunnable());
- t3.setDaemon(true);
- t3.start();
-
- // StackWalker::getCallerClass
- // Runnable::run
- // MyThread::run
- Thread t4 = new MyThread(new Runnable() {
- @Override
- public void run() {
- Class<?> c = sw.getCallerClass();
- System.out.println("Call from MyThread.run: " + c);
- if (c != MyThread.class) {
- throw new RuntimeException("Expected MyThread.class but got " + c);
- }
- }
- });
- t4.setDaemon(true);
- t4.start();
-
- t1.join();
- t2.join();
- t3.join();
- t4.join();
- }
-
- static class MyThread extends Thread {
- final Runnable runnable;
- MyThread(Runnable runnable) {
- super("MyThread");
- this.runnable = runnable;
- }
- public void run() {
- runnable.run();
- }
- }
-
- static class MyRunnable implements Runnable {
- @Override
- public void run() {
- Class<?> c = sw.getCallerClass();
- System.out.println("Call from Thread::run: " + c);
- assertThreadClassAsCaller(c);
- }
- }
-
- static void doit() {
- Class<?> c = sw.getCallerClass();
- System.out.println("Call from CallerFromMain.doit: " + c);
- assertThreadClassAsCaller(c);
- }
-
- static void assertThreadClassAsCaller(Class<?> caller) {
- if (caller != Thread.class) {
- throw new RuntimeException("Expected Thread.class but got " + caller);
- }
- }
-}
--- a/jdk/test/java/lang/StackWalker/DumpStackTest.java Tue Nov 24 04:46:04 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,234 +0,0 @@
-/*
- * Copyright (c) 2015, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8140450
- * @summary Verify outputs of Thread.dumpStack() and Throwable.printStackTrace().
- * This test should also been run against jdk9 successfully except of
- * VM option MemberNameInStackFrame.
- * @run main/othervm DumpStackTest
- * @run main/othervm -Dstackwalk.newThrowable=false DumpStackTest
- * @run main/othervm -Dstackwalk.newThrowable=true -XX:-MemberNameInStackFrame DumpStackTest
- * @run main/othervm -Dstackwalk.newThrowable=true -XX:+MemberNameInStackFrame DumpStackTest
- */
-
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-import java.lang.reflect.Method;
-import java.util.Arrays;
-import java.util.function.Consumer;
-
-public class DumpStackTest {
-
- public static void main(String args[]) {
- test();
- testThread();
- testLambda();
- testMethodInvoke();
- testMethodHandle();
- }
-
- static class CallFrame {
- final String classname;
- final String methodname;
- CallFrame(Class<?> c, String methodname) {
- this(c.getName(), methodname);
- }
- CallFrame(String classname, String methodname) {
- this.classname = classname;
- this.methodname = methodname;
- }
-
- String getClassName() {
- return classname;
- }
- String getMethodName() {
- return methodname;
- }
- String getFileName() {
- int i = classname.lastIndexOf('.');
- int j = classname.lastIndexOf('$');
- String name = classname.substring(i+1, j >= 0 ? j : classname.length());
- return name + ".java";
- }
- @Override
- public String toString() {
- return classname + "." + methodname + "(" + getFileName() + ")";
- }
- }
-
- static void test() {
- CallFrame[] callStack = new CallFrame[] {
- new CallFrame(Thread.class, "getStackTrace"),
- new CallFrame(DumpStackTest.class, "test"),
- new CallFrame(DumpStackTest.class, "main"),
- // if invoked from jtreg
- new CallFrame("sun.reflect.NativeMethodAccessorImpl", "invoke0"), // non-public class
- new CallFrame("sun.reflect.NativeMethodAccessorImpl", "invoke"),
- new CallFrame("sun.reflect.DelegatingMethodAccessorImpl", "invoke"),
- new CallFrame(Method.class, "invoke"),
- new CallFrame(Thread.class, "run"),
- };
-
- assertStackTrace(Thread.currentThread().getStackTrace(), callStack);
- getStackTrace(callStack);
- }
-
- static void getStackTrace(CallFrame[] callStack) {
- // this method is the top of the stack
- callStack[0] = new CallFrame(DumpStackTest.class, "getStackTrace");
-
- try {
- throw new RuntimeException();
- } catch(RuntimeException ex) {
- assertStackTrace(ex.getStackTrace(), callStack);
- }
- }
- static void testThread() {
- Thread t1 = new Thread() {
- public void run() {
- c();
- }
-
- void c() {
- CallFrame[] callStack = new CallFrame[] {
- new CallFrame(Thread.class, "getStackTrace"),
- new CallFrame(this.getClass(), "c"),
- new CallFrame(this.getClass(), "run")
- };
- assertStackTrace(Thread.currentThread().getStackTrace(), callStack);
- DumpStackTest.getStackTrace(callStack);
- }
- };
- t1.start();
- try {
- t1.join();
- } catch(InterruptedException e) {}
- }
-
- static void testLambda() {
- Consumer<Void> c = (x) -> consumeLambda();
- c.accept(null);
- }
-
- static void consumeLambda() {
- CallFrame[] callStack = new CallFrame[]{
- new CallFrame(Thread.class, "getStackTrace"),
- new CallFrame(DumpStackTest.class, "consumeLambda"),
- new CallFrame(DumpStackTest.class, "lambda$testLambda$0"),
- new CallFrame(DumpStackTest.class, "testLambda"),
- new CallFrame(DumpStackTest.class, "main"),
- // if invoked from jtreg
- new CallFrame("sun.reflect.NativeMethodAccessorImpl", "invoke0"),
- new CallFrame("sun.reflect.NativeMethodAccessorImpl", "invoke"),
- new CallFrame("sun.reflect.DelegatingMethodAccessorImpl", "invoke"),
- new CallFrame(Method.class, "invoke"),
- new CallFrame(Thread.class, "run")
- };
- assertStackTrace(Thread.currentThread().getStackTrace(), callStack);
- DumpStackTest.getStackTrace(callStack);
- }
-
- static void testMethodInvoke() {
- try {
- Method m = DumpStackTest.class.getDeclaredMethod("methodInvoke");
- m.invoke(null);
- } catch(Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- static void methodInvoke() {
- CallFrame[] callStack = new CallFrame[] {
- new CallFrame(Thread.class, "getStackTrace"),
- new CallFrame(DumpStackTest.class, "methodInvoke"),
- new CallFrame("sun.reflect.NativeMethodAccessorImpl", "invoke0"),
- new CallFrame("sun.reflect.NativeMethodAccessorImpl", "invoke"),
- new CallFrame("sun.reflect.DelegatingMethodAccessorImpl", "invoke"),
- new CallFrame(Method.class, "invoke"),
- new CallFrame(DumpStackTest.class, "testMethodInvoke"),
- new CallFrame(DumpStackTest.class, "main"),
- // if invoked from jtreg
- new CallFrame("sun.reflect.NativeMethodAccessorImpl", "invoke0"),
- new CallFrame("sun.reflect.NativeMethodAccessorImpl", "invoke"),
- new CallFrame("sun.reflect.DelegatingMethodAccessorImpl", "invoke"),
- new CallFrame(Method.class, "invoke"),
- new CallFrame(Thread.class, "run")
- };
- assertStackTrace(Thread.currentThread().getStackTrace(), callStack);
- DumpStackTest.getStackTrace(callStack);
- }
-
- static void testMethodHandle() {
- MethodHandles.Lookup lookup = MethodHandles.lookup();
- try {
- MethodHandle handle = lookup.findStatic(DumpStackTest.class, "methodHandle",
- MethodType.methodType(void.class));
- handle.invoke();
- } catch(Throwable t) {
- throw new RuntimeException(t);
- }
- }
-
- static void methodHandle() {
- CallFrame[] callStack = new CallFrame[]{
- new CallFrame(Thread.class, "getStackTrace"),
- new CallFrame(DumpStackTest.class, "methodHandle"),
- new CallFrame(DumpStackTest.class, "testMethodHandle"),
- new CallFrame(DumpStackTest.class, "main"),
- // if invoked from jtreg
- new CallFrame("sun.reflect.NativeMethodAccessorImpl", "invoke0"),
- new CallFrame("sun.reflect.NativeMethodAccessorImpl", "invoke"),
- new CallFrame("sun.reflect.DelegatingMethodAccessorImpl", "invoke"),
- new CallFrame(Method.class, "invoke"),
- new CallFrame(Thread.class, "run")
- };
- assertStackTrace(Thread.currentThread().getStackTrace(), callStack);
- DumpStackTest.getStackTrace(callStack);
- }
-
- static void assertStackTrace(StackTraceElement[] actual, CallFrame[] expected) {
- System.out.println("--- Actual ---");
- Arrays.stream(actual).forEach(e -> System.out.println(e));
- System.out.println("--- Expected ---");
- Arrays.stream(expected).forEach(e -> System.out.println(e));
-
- for (int i = 0, j = 0; i < actual.length; i++) {
- // filter test framework classes
- if (actual[i].getClassName().startsWith("com.sun.javatest.regtest"))
- continue;
- assertEquals(actual[i], expected[j++], i);
- }
-
- }
- static void assertEquals(StackTraceElement actual, CallFrame expected, int idx) {
- if (!actual.getClassName().equals(expected.getClassName()) ||
- !actual.getFileName().equals(expected.getFileName()) ||
- !actual.getMethodName().equals(expected.getMethodName())) {
- throw new RuntimeException("StackTraceElements mismatch at index " + idx +
- ". Expected [" + expected + "], but get [" + actual + "]");
- }
- }
-}
--- a/jdk/test/java/lang/StackWalker/EmbeddedStackWalkTest.java Tue Nov 24 04:46:04 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,158 +0,0 @@
-/*
- * Copyright (c) 2015, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/**
- * @test
- * @bug 8140450
- * @summary Verify StackWalker works well when embedded in another
- * StackWalker's functions.
- * @run testng/othervm EmbeddedStackWalkTest
- */
-
-import java.lang.StackWalker.StackFrame;
-import static java.lang.StackWalker.Option.*;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-import java.util.Arrays;
-import java.util.EnumSet;
-
-import org.testng.annotations.*;
-import static org.testng.Assert.*;
-
-public class EmbeddedStackWalkTest {
- static final StackWalker WALKERS[] = new StackWalker[] {
- StackWalker.getInstance(RETAIN_CLASS_REFERENCE),
- StackWalker.getInstance(EnumSet.of(SHOW_REFLECT_FRAMES, RETAIN_CLASS_REFERENCE)),
- StackWalker.getInstance(EnumSet.of(SHOW_HIDDEN_FRAMES, RETAIN_CLASS_REFERENCE))
- };
-
- static final int BIG_LOOP = 30;
- static final int SMALL_LOOP = 5;
-
- @DataProvider
- public StackWalker[][] walkerProvider() {
- return new StackWalker[][] {
- new StackWalker[] { WALKERS[0] },
- new StackWalker[] { WALKERS[1] },
- new StackWalker[] { WALKERS[2] }
- };
- }
-
- @Test(dataProvider = "walkerProvider")
- public void test(StackWalker walker) {
- C1.call(walker, BIG_LOOP);
- }
-
- // line numbers are hardcoded for now.
- // Should annotate the line numbers and auto-generated these constants
- // for test verification instead
- static final int BEGIN_LINE = 71; // the begin line number of approximate range.
- static final int END_LINE = 136; // the end line number of approximate range.
- static class C1 { // here is the begin line number of approximate range, L71.
- public static void call(StackWalker walker, int loops) {
- if (loops == 0) {
- String caller = walker.walk(s ->
- s.map(StackFrame::getClassName)
- .filter(cn -> !cn.startsWith("sun.reflect.") && !cn.startsWith("java.lang.invoke"))
- .skip(2).findFirst()
- ).get();
- assertEquals(caller, C1.class.getName());
-
- walker.forEach(f -> C2.testEmbeddedWalker());
- } else {
- call(walker, --loops);
- }
- }
- }
-
- static class C2 {
- static final StackWalker embeddedWalkers[] = new StackWalker[] {
- StackWalker.getInstance(),
- StackWalker.getInstance(SHOW_REFLECT_FRAMES),
- StackWalker.getInstance(SHOW_HIDDEN_FRAMES)
- };
-
- public static void testEmbeddedWalker() {
- walk(SMALL_LOOP);
- }
-
- static void walk(int loops) {
- if (loops == 0) {
- Arrays.stream(embeddedWalkers)
- .forEach(walker -> run(walker));
- } else {
- walk(--loops);
- }
- }
-
- static void run(StackWalker walker) {
- MethodHandles.Lookup lookup = MethodHandles.lookup();
- MethodHandle handle = null;
- try {
- handle = lookup.findStatic(C2.class, "call",
- MethodType.methodType(void.class, StackWalker.class));
- handle.invoke(walker);
- } catch(Throwable t) {
- throw new RuntimeException(t);
- }
- }
-
- static void call(StackWalker walker) {
- String caller = walker.walk(s ->
- s.map(StackFrame::getClassName)
- .filter(cn -> !cn.startsWith("sun.reflect.") && !cn.startsWith("java.lang.invoke"))
- .skip(2).findFirst()
- ).get();
- assertEquals(caller, C2.class.getName());
-
- verify(walker, C1.class, "call");
- verify(walker, C2.class, "call");
- verify(walker, C2.class, "run");
- verify(walker, C2.class, "walk");
- verify(walker, C2.class, "testEmbeddedWalker");
- } // here is the end line number of approximate range, L136.
-
- static void verify(StackWalker walker, Class<?> c, String mn) {
- final String fileName = "EmbeddedStackWalkTest.java";
- walker.walk(s -> {
- s.limit(BIG_LOOP)
- .filter(f -> c.getName().equals(f.getClassName()) && mn.equals(f.getMethodName()))
- .forEach(f -> {
- assertEquals(f.getFileName().get(), fileName);
- int line = f.getLineNumber().getAsInt();
- assertTrue(line >= BEGIN_LINE && line <= END_LINE);
-
- StackTraceElement st = f.toStackTraceElement();
- assertEquals(c.getName(), st.getClassName());
- assertEquals(mn, st.getMethodName());
- assertEquals(st.getFileName(), fileName);
- line = st.getLineNumber();
- assertTrue(line >= BEGIN_LINE && line <= END_LINE);
- });
- return null;
- });
- }
- }
-}
--- a/jdk/test/java/lang/StackWalker/GetCallerClassTest.java Tue Nov 24 04:46:04 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,253 +0,0 @@
-/*
- * Copyright (c) 2015, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8140450
- * @summary Basic test for StackWalker.getCallerClass()
- * @run main/othervm -XX:-MemberNameInStackFrame GetCallerClassTest
- * @run main/othervm -XX:+MemberNameInStackFrame GetCallerClassTest
- * @run main/othervm GetCallerClassTest sm
- */
-
-import static java.lang.StackWalker.Option.*;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.security.Permission;
-import java.security.PermissionCollection;
-import java.security.Permissions;
-import java.security.Policy;
-import java.security.ProtectionDomain;
-import java.util.Arrays;
-import java.util.List;
-
-public class GetCallerClassTest {
- private final StackWalker walker;
- private final boolean expectUOE;
-
- public GetCallerClassTest(StackWalker sw, boolean expect) {
- this.walker = sw;
- this.expectUOE = expect;
- }
- public static void main(String... args) throws Exception {
- if (args.length > 0 && args[0].equals("sm")) {
- PermissionCollection perms = new Permissions();
- perms.add(new StackFramePermission("retainClassReference"));
- Policy.setPolicy(new Policy() {
- @Override
- public boolean implies(ProtectionDomain domain, Permission p) {
- return perms.implies(p);
- }
- });
- System.setSecurityManager(new SecurityManager());
- }
- new GetCallerClassTest(StackWalker.getInstance(), true).test();
- new GetCallerClassTest(StackWalker.getInstance(RETAIN_CLASS_REFERENCE), false).test();
- }
-
- public void test() {
- new TopLevelCaller().run();
- new Nested().createNestedCaller().run();
- new InnerClassCaller().run();
- new ReflectionTest().run();
-
- List<Thread> threads = Arrays.asList(
- new Thread(new TopLevelCaller()),
- new Thread(new Nested().createNestedCaller()),
- new Thread(new InnerClassCaller()),
- new Thread(new ReflectionTest())
- );
- threads.stream().forEach(Thread::start);
- threads.stream().forEach(t -> {
- try {
- t.join();
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- });
- }
-
- public static void staticGetCallerClass(StackWalker stackWalker,
- Class<?> expected,
- boolean expectUOE) {
- try {
- Class<?> c = stackWalker.getCallerClass();
- assertEquals(c, expected);
- if (expectUOE) { // Should have thrown
- throw new RuntimeException("Didn't get expected exception");
- }
- } catch (RuntimeException e) { // also catches UOE
- if (expectUOE && causeIsUOE(e)) {
- return; /* expected */
- }
- System.err.println("Unexpected exception:");
- throw e;
- }
- }
-
- public static void reflectiveGetCallerClass(StackWalker stackWalker,
- Class<?> expected,
- boolean expectUOE) {
- try {
- Method m = StackWalker.class.getMethod("getCallerClass");
- Class<?> c = (Class<?>) m.invoke(stackWalker);
- assertEquals(c, expected);
- 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);
- }
- }
-
- public static void methodHandleGetCallerClass(StackWalker stackWalker,
- Class<?> expected,
- boolean expectUOE) {
- MethodHandles.Lookup lookup = MethodHandles.lookup();
- try {
- MethodHandle mh = lookup.findVirtual(StackWalker.class, "getCallerClass",
- MethodType.methodType(Class.class));
- Class<?> c = (Class<?>) mh.invokeExact(stackWalker);
- assertEquals(c, expected);
- 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);
- }
- }
-
- public static void assertEquals(Class<?> c, Class<?> expected) {
- if (expected != c) {
- throw new RuntimeException(c + " != " + expected);
- }
- }
-
- /** Is there an UnsupportedOperationException in there? */
- public static boolean causeIsUOE(Throwable t) {
- while (t != null) {
- if (t instanceof UnsupportedOperationException) {
- return true;
- }
- t = t.getCause();
- }
- return false;
- }
-
- class TopLevelCaller implements Runnable {
- public void run() {
- GetCallerClassTest.staticGetCallerClass(walker, this.getClass(), expectUOE);
- GetCallerClassTest.reflectiveGetCallerClass(walker, this.getClass(), expectUOE);
- GetCallerClassTest.methodHandleGetCallerClass(walker, this.getClass(), expectUOE);
- }
- }
-
- class Nested {
- NestedClassCaller createNestedCaller() { return new NestedClassCaller(); }
- class NestedClassCaller implements Runnable {
- public void run() {
- GetCallerClassTest.staticGetCallerClass(walker, this.getClass(), expectUOE);
- GetCallerClassTest.reflectiveGetCallerClass(walker, this.getClass(), expectUOE);
- GetCallerClassTest.methodHandleGetCallerClass(walker, this.getClass(), expectUOE);
- }
- }
- }
-
- class InnerClassCaller implements Runnable {
- public void run() {
- new Inner().test();
- }
- class Inner {
- void test() {
- GetCallerClassTest.staticGetCallerClass(walker, this.getClass(), expectUOE);
- GetCallerClassTest.reflectiveGetCallerClass(walker, this.getClass(), expectUOE);
- GetCallerClassTest.methodHandleGetCallerClass(walker, this.getClass(), expectUOE);
- }
- }
- }
-
- class ReflectionTest implements Runnable {
- final MethodType methodType =
- MethodType.methodType(void.class, StackWalker.class, Class.class, boolean.class);
-
- public void run() {
- callMethodHandle();
- callMethodHandleRefl();
- callMethodInvoke();
- callMethodInvokeRefl();
- }
- void callMethodHandle() {
- MethodHandles.Lookup lookup = MethodHandles.publicLookup();
- try {
- MethodHandle mh = lookup.findStatic(GetCallerClassTest.class,
- "staticGetCallerClass",
- methodType);
- mh.invokeExact(walker, ReflectionTest.class, expectUOE);
- } catch (Throwable e) {
- throw new RuntimeException(e);
- }
- }
- void callMethodHandleRefl() {
- MethodHandles.Lookup lookup = MethodHandles.publicLookup();
- try {
- MethodHandle mh = lookup.findStatic(GetCallerClassTest.class,
- "reflectiveGetCallerClass",
- methodType);
- mh.invokeExact(walker, ReflectionTest.class, expectUOE);
- } catch (Throwable e) {
- throw new RuntimeException(e);
- }
- }
- void callMethodInvoke() {
- try {
- Method m = GetCallerClassTest.class.getMethod("staticGetCallerClass",
- StackWalker.class, Class.class, boolean.class);
- m.invoke(null, walker, ReflectionTest.class, expectUOE);
- } catch (NoSuchMethodException|IllegalAccessException|InvocationTargetException e) {
- throw new RuntimeException(e);
- }
- }
- void callMethodInvokeRefl() {
- try {
- Method m = GetCallerClassTest.class.getMethod("reflectiveGetCallerClass",
- StackWalker.class, Class.class, boolean.class);
- m.invoke(null, walker, ReflectionTest.class, expectUOE);
- } catch (UnsupportedOperationException e) {
- throw e;
- } catch (NoSuchMethodException|IllegalAccessException|InvocationTargetException e) {
- throw new RuntimeException(e);
- }
- }
- }
-}
--- a/jdk/test/java/lang/StackWalker/HiddenFrames.java Tue Nov 24 04:46:04 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,108 +0,0 @@
-/*
- * Copyright (c) 2015, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8140450
- * @summary Basic test for hidden frames
- * @run main HiddenFrames
- */
-
-import java.lang.StackWalker.Option;
-import java.lang.StackWalker.StackFrame;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Stream;
-
-public class HiddenFrames {
- public static void main(String... args) throws Exception {
- new HiddenFrames().test();
- new HiddenFrames(Option.SHOW_REFLECT_FRAMES).test();
- new HiddenFrames(Option.SHOW_HIDDEN_FRAMES).test();
- }
-
- private final Option option;
- private final StackWalker walker;
- private final List<StackFrame> lambdas = new ArrayList<>();
- private final List<StackFrame> reflects = new ArrayList<>();
-
- HiddenFrames() {
- this.option = null;
- this.walker = StackWalker.getInstance();
- }
- HiddenFrames(Option option) {
- this.option = option;
- this.walker = StackWalker.getInstance(option);
- }
-
- void test() throws Exception {
- walk();
- walkFromReflection();
- }
-
- void walk() {
- Stream.of(0).forEach(i -> walker.walk(s ->
- {
- s.forEach(this::checkFrame);
- return null;
- }));
-
- // only check hidden frames but not reflection frames
- // walk is not invoked via reflection
- if (option == null && !lambdas.isEmpty()) {
- throw new RuntimeException("Hidden frames are shown");
- }
-
- if (option == Option.SHOW_HIDDEN_FRAMES && lambdas.isEmpty()) {
- throw new RuntimeException("No hidden Lambda frame");
- }
- }
-
- void walkFromReflection() throws Exception {
- Method m = HiddenFrames.class.getDeclaredMethod("walk");
- m.invoke(this);
-
- if (option == null && !lambdas.isEmpty()) {
- throw new RuntimeException("Hidden frames are shown");
- }
-
- if (option == Option.SHOW_HIDDEN_FRAMES && lambdas.isEmpty()) {
- throw new RuntimeException("No hidden Lambda frame");
- }
-
- if (option != null && reflects.isEmpty()) {
- throw new RuntimeException("No reflection frame");
- }
- }
-
- void checkFrame(StackFrame frame) {
- String cn = frame.getClassName();
- if (cn.startsWith("java.lang.reflect.") || cn.startsWith("sun.reflect.")) {
- reflects.add(frame);
- }
- if (cn.contains("$$Lambda$")) {
- lambdas.add(frame);
- }
- }
-}
--- a/jdk/test/java/lang/StackWalker/LocalsAndOperands.java Tue Nov 24 04:46:04 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +0,0 @@
-/*
- * Copyright (c) 2015, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8140450
- * @summary Sanity test for locals and operands
- * @run main LocalsAndOperands
- */
-
-import java.lang.StackWalker.StackFrame;
-import java.lang.reflect.*;
-import java.util.List;
-import java.util.stream.Collectors;
-
-public class LocalsAndOperands {
- static Class<?> liveStackFrameClass;
- static Class<?> primitiveValueClass;
- static StackWalker extendedWalker;
- static Method getLocals;
- static Method getOperands;
- static Method getMonitors;
- static Method primitiveType;
- public static void main(String... args) throws Exception {
- liveStackFrameClass = Class.forName("java.lang.LiveStackFrame");
- primitiveValueClass = Class.forName("java.lang.LiveStackFrame$PrimitiveValue");
-
- getLocals = liveStackFrameClass.getDeclaredMethod("getLocals");
- getLocals.setAccessible(true);
-
- getOperands = liveStackFrameClass.getDeclaredMethod("getStack");
- getOperands.setAccessible(true);
-
- getMonitors = liveStackFrameClass.getDeclaredMethod("getMonitors");
- getMonitors.setAccessible(true);
-
- primitiveType = primitiveValueClass.getDeclaredMethod("type");
- primitiveType.setAccessible(true);
-
- Method method = liveStackFrameClass.getMethod("getStackWalker");
- method.setAccessible(true);
- extendedWalker = (StackWalker) method.invoke(null);
- new LocalsAndOperands(extendedWalker, true).test();
-
- // no access to local and operands.
- new LocalsAndOperands(StackWalker.getInstance(), false).test();
- }
-
- private final StackWalker walker;
- private final boolean extended;
- LocalsAndOperands(StackWalker walker, boolean extended) {
- this.walker = walker;
- this.extended = extended;
- }
-
- synchronized void test() throws Exception {
- int x = 10;
- char c = 'z';
- String hi = "himom";
- long l = 1000000L;
- double d = 3.1415926;
-
- List<StackWalker.StackFrame> frames = walker.walk(s -> s.collect(Collectors.toList()));
- if (extended) {
- for (StackWalker.StackFrame f : frames) {
- 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]));
- }
-
- 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]));
- }
-
- Object[] monitors = (Object[]) getMonitors.invoke(f);
- for (int i = 0; i < monitors.length; i++) {
- System.out.format("monitor %d: %s%n", i, monitors[i]);
- }
- }
- } else {
- for (StackFrame f : frames) {
- if (liveStackFrameClass.isInstance(f))
- throw new RuntimeException("should not be LiveStackFrame");
- }
- }
- }
-
- String type(Object o) throws Exception {
- if (primitiveValueClass.isInstance(o)) {
- char c = (char)primitiveType.invoke(o);
- return String.valueOf(c);
- } else {
- return o.getClass().getName();
- }
- }
-}
--- a/jdk/test/java/lang/StackWalker/MultiThreadStackWalk.java Tue Nov 24 04:46:04 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,362 +0,0 @@
-/*
- * Copyright (c) 2015, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicLong;
-import java.lang.StackWalker.StackFrame;
-import static java.lang.StackWalker.Option.*;
-
-
-/**
- * @test
- * @bug 8140450
- * @summary This test will walk the stack using different methods, called
- * from several threads running concurrently.
- * Except in the case of MTSTACKSTREAM - which takes a snapshot
- * of the stack before walking, all the methods only allow to
- * walk the current thread stack.
- * @run main/othervm MultiThreadStackWalk
- * @author danielfuchs
- */
-public class MultiThreadStackWalk {
-
- static Set<String> infrastructureClasses = new TreeSet<>(Arrays.asList(
- "sun.reflect.NativeMethodAccessorImpl",
- "sun.reflect.DelegatingMethodAccessorImpl",
- "java.lang.reflect.Method",
- "com.sun.javatest.regtest.MainWrapper$MainThread",
- "java.lang.Thread"
- ));
-
-
- static final List<Class<?>> streamPipelines = Arrays.asList(
- classForName("java.util.stream.AbstractPipeline"),
- classForName("java.util.stream.TerminalOp")
- );
-
- static Class<?> classForName(String name) {
- try {
- return Class.forName(name);
- } catch (ClassNotFoundException e){
- throw new RuntimeException(e);
- }
- }
-
- private static boolean isStreamPipeline(Class<?> clazz) {
- for (Class<?> c : streamPipelines) {
- if (c.isAssignableFrom(clazz)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * An object that contains variables pertaining to the execution
- * of the test within one thread.
- * A small amount of those variable are shared with sub threads when
- * the stack walk is executed in parallel - that is when spliterators
- * obtained from trySplit are handed over to an instance of SplitThread
- * in order to parallelize thread walking.
- * @see WalkThread#handOff(MultiThreadStackWalk.Env, java.util.Spliterator, boolean, boolean)
- * @see Env#split(MultiThreadStackWalk.Env)
- */
- public static class Env {
- final AtomicLong frameCounter; // private: the counter for the current thread.
- final long checkMarkAt; // constant: the point at which we expect to
- // find the marker in consume()
- final long max; // constant: the maximum number of recursive
- // calls to Call.
- final AtomicBoolean debug ; // shared: whether debug is active for the
- // instance of Test from which this instance
- // of Env was spawned
- final AtomicLong markerCalled; // shared: whether the marker was reached
- final AtomicLong maxReached; // shared: whether max was reached
- final Set<String> unexpected; // shared: list of unexpected infrastructure
- // classes encountered after max is reached
-
- public Env(long total, long markAt, AtomicBoolean debug) {
- this.debug = debug;
- frameCounter = new AtomicLong();
- maxReached = new AtomicLong();
- unexpected = Collections.synchronizedSet(new TreeSet<>());
- this.max = total+2;
- this.checkMarkAt = total - markAt + 1;
- this.markerCalled = new AtomicLong();
- }
-
- // Used when delegating part of the stack walking to a sub thread
- // see WalkThread.handOff.
- private Env(Env orig, long start) {
- debug = orig.debug;
- frameCounter = new AtomicLong(start);
- maxReached = orig.maxReached;
- unexpected = orig.unexpected;
- max = orig.max;
- checkMarkAt = orig.checkMarkAt;
- markerCalled = orig.markerCalled;
- }
-
- // The stack walk consumer method, where all the checks are
- // performed.
- public void consume(StackFrame sfi) {
- if (frameCounter.get() == 0 && isStreamPipeline(sfi.getDeclaringClass())) {
- return;
- }
-
- final long count = frameCounter.getAndIncrement();
- final StringBuilder builder = new StringBuilder();
- builder.append("Declaring class[")
- .append(count)
- .append("]: ")
- .append(sfi.getDeclaringClass());
- builder.append('\n');
- builder.append("\t")
- .append(sfi.getClassName())
- .append(".")
- .append(sfi.toStackTraceElement().getMethodName())
- .append(sfi.toStackTraceElement().isNativeMethod()
- ? "(native)"
- : "(" + sfi.toStackTraceElement().getFileName()
- +":"+sfi.toStackTraceElement().getLineNumber()+")");
- builder.append('\n');
- if (debug.get()) {
- System.out.print("[debug] " + builder.toString());
- builder.setLength(0);
- }
- if (count == max) {
- maxReached.incrementAndGet();
- }
- if (count == checkMarkAt) {
- if (sfi.getDeclaringClass() != MultiThreadStackWalk.Marker.class) {
- throw new RuntimeException("Expected Marker at " + count
- + ", found " + sfi.getDeclaringClass());
- }
- } else {
- if (count <= 0 && sfi.getDeclaringClass() != MultiThreadStackWalk.Call.class) {
- throw new RuntimeException("Expected Call at " + count
- + ", found " + sfi.getDeclaringClass());
- } else if (count > 0 && count < max && sfi.getDeclaringClass() != MultiThreadStackWalk.Test.class) {
- throw new RuntimeException("Expected Test at " + count
- + ", found " + sfi.getDeclaringClass());
- } else if (count == max && sfi.getDeclaringClass() != MultiThreadStackWalk.class) {
- throw new RuntimeException("Expected MultiThreadStackWalk at "
- + count + ", found " + sfi.getDeclaringClass());
- } else if (count == max && !sfi.toStackTraceElement().getMethodName().equals("runTest")) {
- throw new RuntimeException("Expected runTest method at "
- + count + ", found " + sfi.toStackTraceElement().getMethodName());
- } else if (count == max+1) {
- if (sfi.getDeclaringClass() != MultiThreadStackWalk.WalkThread.class) {
- throw new RuntimeException("Expected MultiThreadStackWalk at "
- + count + ", found " + sfi.getDeclaringClass());
- }
- if (count == max && !sfi.toStackTraceElement().getMethodName().equals("run")) {
- throw new RuntimeException("Expected main method at "
- + count + ", found " + sfi.toStackTraceElement().getMethodName());
- }
- } else if (count > max+1) {
- // expect JTreg infrastructure...
- if (!infrastructureClasses.contains(sfi.getDeclaringClass().getName())) {
- System.err.println("**** WARNING: encountered unexpected infrastructure class at "
- + count +": " + sfi.getDeclaringClass().getName());
- unexpected.add(sfi.getDeclaringClass().getName());
- }
- }
- }
- if (count == 100) {
- // Maybe we should had some kind of checking inside that lambda
- // too. For the moment we should be satisfied if it doesn't throw
- // any exception and doesn't make the outer walk fail...
- StackWalker.getInstance(RETAIN_CLASS_REFERENCE).forEach(x -> {
- StackTraceElement st = x.toStackTraceElement();
- StringBuilder b = new StringBuilder();
- b.append("*** inner walk: ")
- .append(x.getClassName())
- .append(st == null ? "- no stack trace element -" :
- ("." + st.getMethodName()
- + (st.isNativeMethod() ? "(native)" :
- "(" + st.getFileName()
- + ":" + st.getLineNumber() + ")")))
- .append('\n');
- if (debug.get()) {
- System.out.print(b.toString());
- b.setLength(0);
- }
- });
- }
- }
- }
-
- public interface Call {
- enum WalkType {
- WALKSTACK, // use Thread.walkStack
- }
- default WalkType getWalkType() { return WalkType.WALKSTACK;}
- default void walk(Env env) {
- WalkType walktype = getWalkType();
- System.out.println("Thread "+ Thread.currentThread().getName()
- +" starting walk with " + walktype);
- switch(walktype) {
- case WALKSTACK:
- StackWalker.getInstance(RETAIN_CLASS_REFERENCE)
- .forEach(env::consume);
- break;
- default:
- throw new InternalError("Unknown walk type: " + walktype);
- }
- }
- default void call(Env env, Call next, int total, int current, int markAt) {
- if (current < total) {
- next.call(env, next, total, current+1, markAt);
- }
- }
- }
-
- public static class Marker implements Call {
- final WalkType walkType;
- Marker(WalkType walkType) {
- this.walkType = walkType;
- }
- @Override
- public WalkType getWalkType() {
- return walkType;
- }
-
- @Override
- public void call(Env env, Call next, int total, int current, int markAt) {
- env.markerCalled.incrementAndGet();
- if (current < total) {
- next.call(env, next, total, current+1, markAt);
- } else {
- next.walk(env);
- }
- }
- }
-
- public static class Test implements Call {
- final Marker marker;
- final WalkType walkType;
- final AtomicBoolean debug;
- Test(WalkType walkType) {
- this.walkType = walkType;
- this.marker = new Marker(walkType);
- this.debug = new AtomicBoolean();
- }
- @Override
- public WalkType getWalkType() {
- return walkType;
- }
- @Override
- public void call(Env env, Call next, int total, int current, int markAt) {
- if (current < total) {
- int nexti = current + 1;
- Call nextObj = nexti==markAt ? marker : next;
- nextObj.call(env, next, total, nexti, markAt);
- } else {
- walk(env);
- }
- }
- }
-
- public static Env runTest(Test test, int total, int markAt) {
- Env env = new Env(total, markAt, test.debug);
- test.call(env, test, total, 0, markAt);
- return env;
- }
-
- public static void checkTest(Env env, Test test) {
- String threadName = Thread.currentThread().getName();
- System.out.println(threadName + ": Marker called: " + env.markerCalled.get());
- System.out.println(threadName + ": Max reached: " + env.maxReached.get());
- System.out.println(threadName + ": Frames consumed: " + env.frameCounter.get());
- if (env.markerCalled.get() == 0) {
- throw new RuntimeException(Thread.currentThread().getName() + ": Marker was not called.");
- }
- if (env.markerCalled.get() > 1) {
- throw new RuntimeException(Thread.currentThread().getName()
- + ": Marker was called more than once: " + env.maxReached.get());
- }
- if (!env.unexpected.isEmpty()) {
- System.out.flush();
- System.err.println("Encountered some unexpected infrastructure classes below 'main': "
- + env.unexpected);
- }
- if (env.maxReached.get() == 0) {
- throw new RuntimeException(Thread.currentThread().getName()
- + ": max not reached");
- }
- if (env.maxReached.get() > 1) {
- throw new RuntimeException(Thread.currentThread().getName()
- + ": max was reached more than once: " + env.maxReached.get());
- }
- }
-
- static class WalkThread extends Thread {
- final static AtomicLong walkersCount = new AtomicLong();
- Throwable failed = null;
- final Test test;
- public WalkThread(Test test) {
- super("WalkThread[" + walkersCount.incrementAndGet() + ", type="
- + test.getWalkType() + "]");
- this.test = test;
- }
-
- public void run() {
- try {
- Env env = runTest(test, 2000, 10);
- //waitWalkers(env);
- checkTest(env, test);
- } catch(Throwable t) {
- failed = t;
- }
- }
- }
-
- public static void main(String[] args) throws Throwable {
- WalkThread[] threads = new WalkThread[Call.WalkType.values().length*3];
- Throwable failed = null;
- for (int i=0; i<threads.length; i++) {
- Test test = new Test(Call.WalkType.values()[i%Call.WalkType.values().length]);
- threads[i] = new WalkThread(test);
- }
- for (int i=0; i<threads.length; i++) {
- threads[i].start();
- }
- for (int i=0; i<threads.length; i++) {
- threads[i].join();
- if (failed == null) failed = threads[i].failed;
- else if (threads[i].failed == null) {
- failed.addSuppressed(threads[i].failed);
- }
- }
- if (failed != null) {
- throw failed;
- }
- }
-
-}
--- a/jdk/test/java/lang/StackWalker/SanityTest.java Tue Nov 24 04:46:04 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2015, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- * @test
- * @bug 8140450
- * @summary Sanity test for exception cases
- * @run testng SanityTest
- */
-
-
-import java.util.Collections;
-import java.util.Set;
-
-import org.testng.annotations.Test;
-
-public class SanityTest {
- @Test
- public static void testNPE() {
- try {
- StackWalker sw = StackWalker.getInstance((Set<StackWalker.Option>) null);
- throw new RuntimeException("NPE expected");
- } catch (NullPointerException e) {}
-
- try {
- StackWalker sw = StackWalker.getInstance((StackWalker.Option) null);
- throw new RuntimeException("NPE expected");
- } catch (NullPointerException e) {}
- }
-
- @Test
- public static void testUOE() {
- try {
- StackWalker.getInstance().getCallerClass();
- throw new RuntimeException("UOE expected");
- } catch (UnsupportedOperationException expected) {}
- }
-
- @Test
- public static void testInvalidEstimateDepth() {
- try {
- StackWalker sw = StackWalker.getInstance(Collections.emptySet(), 0);
- throw new RuntimeException("Illegal estimateDepth should throw IAE");
- } catch (IllegalArgumentException e) {}
- }
-
- @Test
- public static void testNullFuncation() {
- try {
- StackWalker.getInstance().walk(null);
- throw new RuntimeException("NPE expected");
- } catch (NullPointerException e) {}
- }
-
- @Test
- public static void testNullConsumer() {
- try {
- StackWalker.getInstance().forEach(null);
- throw new RuntimeException("NPE expected");
- } catch (NullPointerException e) {}
- }
-}
--- a/jdk/test/java/lang/StackWalker/SecurityExceptions.java Tue Nov 24 04:46:04 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2015, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test 8140450
- * @summary Test security permission check
- * @run main/othervm/java.security.policy=noperms.policy SecurityExceptions true
- * @run main/othervm/java.security.policy=stackwalk.policy SecurityExceptions false
- */
-public class SecurityExceptions {
- public static void main(String[] args) {
- boolean expectException = Boolean.parseBoolean(args[0]);
-
- StackWalker sw = StackWalker.getInstance();
-
- try {
- sw = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
- if (expectException) {
- throw new RuntimeException("Expected SecurityException, but none thrown");
- }
- } catch (SecurityException e) {
- if (!expectException) {
- System.err.println("Unexpected security exception:");
- throw e;
- }
- }
- }
-}
--- a/jdk/test/java/lang/StackWalker/StackRecorderUtil.java Tue Nov 24 04:46:04 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,137 +0,0 @@
-/*
- * Copyright (c) 2015, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.lang.StackWalker.Option;
-import java.lang.StackWalker.StackFrame;
-import java.util.*;
-
-/**
- * Utility class for recording a stack trace for later comparison to
- * StackWalker results.
- *
- * StackTraceElement comparison does not include line number, isNativeMethod
- */
-public class StackRecorderUtil implements Iterable<StackRecorderUtil.TestFrame> {
- private List<TestFrame> testFrames = new LinkedList();
-
- private boolean compareClasses;
- private boolean compareClassNames = true;
- private boolean compareMethodNames = true;
- private boolean compareSTEs;
-
- public StackRecorderUtil(Set<StackWalker.Option> swOptions) {
- compareClasses = swOptions.contains(Option.RETAIN_CLASS_REFERENCE);
- compareSTEs = true;
- }
-
- /**
- * Add a method call to this recorded stack.
- */
- public void add(Class declaringClass, String methodName, String fileName) {
- testFrames.add(0, new TestFrame(declaringClass, methodName, fileName));
- }
-
- public int frameCount() { return testFrames.size(); }
-
- /**
- * Compare the given StackFrame returned from the StackWalker to the
- * recorded frame at the given index.
- *
- * Tests for equality, as well as functional correctness with respect to
- * the StackWalker's options (e.g. throws or doesn't throw exceptions)
- */
- public void compareFrame(int index, StackFrame sf) {
- TestFrame tf = testFrames.get(index);
- if (compareClasses) {
- if (!tf.declaringClass.equals(sf.getDeclaringClass())) {
- throw new RuntimeException("Expected class: " +
- tf.declaringClass.toString() + ", but got: " +
- sf.getDeclaringClass().toString());
- }
- } else {
- boolean caught = false;
- try {
- sf.getDeclaringClass();
- } catch (UnsupportedOperationException e) {
- caught = true;
- }
- if (!caught) {
- throw new RuntimeException("StackWalker did not have " +
- "RETAIN_CLASS_REFERENCE Option, but did not throw " +
- "UnsupportedOperationException");
- }
- }
-
- if (compareClassNames && !tf.className().equals(sf.getClassName())) {
- throw new RuntimeException("Expected class name: " + tf.className() +
- ", but got: " + sf.getClassName());
- }
- if (compareMethodNames && !tf.methodName.equals(sf.getMethodName())) {
- throw new RuntimeException("Expected method name: " + tf.methodName +
- ", but got: " + sf.getMethodName());
- }
- if (compareSTEs) {
- StackTraceElement ste = sf.toStackTraceElement();
- if (!(ste.getClassName().equals(tf.className()) &&
- ste.getMethodName().equals(tf.methodName)) &&
- ste.getFileName().equals(tf.fileName)) {
- throw new RuntimeException("Expected StackTraceElement info: " +
- tf + ", but got: " + ste);
- }
- if (!Objects.equals(ste.getClassName(), sf.getClassName())
- || !Objects.equals(ste.getMethodName(), sf.getMethodName())
- || !Objects.equals(ste.getFileName(), sf.getFileName().orElse(null))
- || !Objects.equals(ste.getLineNumber(), sf.getLineNumber().orElse(-1))
- || !Objects.equals(ste.isNativeMethod(), sf.isNativeMethod())) {
- throw new RuntimeException("StackFrame and StackTraceElement differ: " +
- "sf=" + sf + ", ste=" + ste);
- }
- }
- }
-
- public Iterator<TestFrame> iterator() {
- return testFrames.iterator();
- }
-
- /**
- * Class used to record stack frame information.
- */
- public static class TestFrame {
- public Class declaringClass;
- public String methodName;
- public String fileName = null;
-
- public TestFrame (Class declaringClass, String methodName, String fileName) {
- this.declaringClass = declaringClass;
- this.methodName = methodName;
- this.fileName = fileName;
- }
- public String className() {
- return declaringClass.getName();
- }
- public String toString() {
- return "TestFrame: " + className() + "." + methodName +
- (fileName == null ? "" : "(" + fileName + ")");
- }
- }
-}
--- a/jdk/test/java/lang/StackWalker/StackStreamState.java Tue Nov 24 04:46:04 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2015, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8140450
- * @summary Basic test for Stream<StackFrame> state
- * @run main StackStreamState
- */
-
-import java.lang.StackWalker.StackFrame;
-import java.util.stream.Stream;
-
-public class StackStreamState {
- public static void main(String... args) {
- StackStreamState test = new StackStreamState();
- test.testStatic();
- test.testInstance();
- test.testLocal();
- }
-
- private static Stream<StackFrame> staticStream;
- private Stream<StackFrame> instanceStream;
- private final StackWalker walker = StackWalker.getInstance();
- void testStatic() {
- walker.walk(s -> {
- staticStream = s;
- return null;
- });
- checkStreamState(staticStream);
- }
- void testInstance() {
- walker.walk(s -> {
- instanceStream = s;
- return null;
- });
- checkStreamState(instanceStream);
- }
- void testLocal() {
- Stream<StackFrame> stream = walker.walk(s -> {
- return s;
- });
- checkStreamState(stream);
- }
- void checkStreamState(Stream<StackFrame> stream) {
- try {
- stream.count();
- throw new RuntimeException("IllegalStateException not thrown");
- } catch (IllegalStateException e) {
- System.out.println("Got expected IllegalStateException: " + e.getMessage());
- e.printStackTrace(System.out);
- }
- }
-}
--- a/jdk/test/java/lang/StackWalker/StackStreamTest.java Tue Nov 24 04:46:04 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,290 +0,0 @@
-/*
- * Copyright (c) 2015, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import static java.lang.StackWalker.Option.*;
-import java.lang.StackWalker.StackFrame;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Optional;
-import java.util.logging.Logger;
-import java.util.stream.Collectors;
-
-/**
- * @test
- * @bug 8140450
- * @summary Stack Stream Test
- * @run main/othervm StackStreamTest
- */
-public class StackStreamTest {
- public static void main(String[] argv) throws Exception {
- new StackStreamTest().test();
- }
-
- private static Logger logger = Logger.getLogger("stackstream");
- public StackStreamTest() {
- }
-
- public void test() {
- A.a();
- }
- static class A {
- public static void a() {
- B.b();
- }
- }
- static class B {
- public static void b() {
- C.c();
- }
- }
- static class C {
- public static void c() {
- D.d();
- }
- }
- static class D {
- public static void d() {
- E.e();
- }
- }
- static class E {
- public static void e() {
- F.f();
- }
- }
- static class F {
- public static void f() {
- logger.severe("log message");
- G.g();
- new K().k();
- }
- }
-
- private static boolean isTestClass(StackFrame f) {
- // Filter jtreg frames from the end of the stack
- return f.getClassName().startsWith("StackStreamTest");
- }
-
- static class G {
- static StackWalker STE_WALKER = StackWalker.getInstance();
- static StackWalker DEFAULT_WALKER = StackWalker.getInstance();
-
- private static final List<String> GOLDEN_CLASS_NAMES =
- Arrays.asList("StackStreamTest$G",
- "StackStreamTest$F",
- "StackStreamTest$E",
- "StackStreamTest$D",
- "StackStreamTest$C",
- "StackStreamTest$B",
- "StackStreamTest$A",
- "StackStreamTest",
- "StackStreamTest");
- private static final List<String> GOLDEN_METHOD_NAMES =
- Arrays.asList("g", "f", "e", "d", "c", "b", "a", "test", "main");
-
-
- public static void g() {
-
- System.out.println("Thread dump");
- Thread.dumpStack();
-
- caller();
- firstFrame();
-
- // Check class names
- System.out.println("check class names");
- List<String> sfs = DEFAULT_WALKER.walk(s -> {
- return s.filter(StackStreamTest::isTestClass)
- .map(StackFrame::getClassName)
- .collect(Collectors.toList());
- });
- equalsOrThrow("class names", sfs, GOLDEN_CLASS_NAMES);
-
- // Check method names
- System.out.println("methodNames()");
- sfs = DEFAULT_WALKER.walk(s -> {
- return s.filter(StackStreamTest::isTestClass)
- .map(StackFrame::getMethodName)
- .collect(Collectors.toList());}
- );
- equalsOrThrow("method names", sfs, GOLDEN_METHOD_NAMES);
-
- Exception exc = new Exception("G.g stack");
- exc.printStackTrace();
-
- System.out.println("Stream of StackTraceElement");
- StackWalker.getInstance()
- .walk(s ->
- {
- s.map(StackFrame::toStackTraceElement)
- .forEach(ste -> System.out.println("STE: " + ste));
- return null;
- });
-
- // Do we need this?
- System.out.println("Collect StackTraceElement");
- List<StackTraceElement> stacktrace = STE_WALKER.walk(s ->
- {
- // Filter out jtreg frames
- return s.filter(StackStreamTest::isTestClass)
- .collect(Collectors.mapping(StackFrame::toStackTraceElement, Collectors.toList()));
- });
- int i=0;
- for (StackTraceElement s : stacktrace) {
- System.out.format(" %d: %s%n", i++, s);
- }
-
- // Check STEs for correctness
- checkStackTraceElements(GOLDEN_CLASS_NAMES, GOLDEN_METHOD_NAMES, stacktrace);
- }
-
- static void checkStackTraceElements(List<String> classNames,
- List<String> methodNames,
- List<StackTraceElement> stes) {
- if (classNames.size() != methodNames.size() ) {
- throw new RuntimeException("Test error: classNames and methodNames should be same size");
- }
- if (classNames.size() != stes.size()) {
- dumpSTEInfo(classNames, methodNames, stes);
- throw new RuntimeException("wrong number of elements in stes");
- }
- for (int i = 0; i < classNames.size() ; i++) {
- if (!classNames.get(i).equals(stes.get(i).getClassName()) ||
- !methodNames.get(i).equals(stes.get(i).getMethodName())) {
- dumpSTEInfo(classNames, methodNames, stes);
- throw new RuntimeException("class & method names don't match");
- }
- }
- }
-
- static void dumpSTEInfo(List<String> classNames, List<String> methodNames,
- List<StackTraceElement> stes) {
- System.out.println("Observed class, method names:");
- for (StackTraceElement ste : stes) {
- System.out.println(" " + ste.getClassName() + ", " + ste.getMethodName());
- }
- System.out.println("Expected class, method names:");
- for (int i = 0; i < classNames.size(); i++) {
- System.out.println(" " + classNames.get(i) + ", " + methodNames.get(i));
- }
- }
-
- static void firstFrame() {
- System.out.println("first frame()");
- StackWalker sw = StackWalker.getInstance(RETAIN_CLASS_REFERENCE);
- sw.forEach(e -> {
- System.out.println(e.getClassName() + "," + e.getMethodName());
- });
- System.out.println("\n");
- Optional<StackFrame> frame = sw.walk(s ->
- {
- return s.filter(e -> {
- System.err.println(e.getClassName() + " == " +
- e.getClassName().equals("StackStreamTest"));
- return e.getClassName().equals("StackStreamTest");
- }).findFirst();
- });
- Class<?> c = frame.get().getDeclaringClass();
- System.out.println("\nfirst frame: " + c);
- if (c != StackStreamTest.class) {
- throw new RuntimeException("Unexpected first caller class " + c);
- }
- }
- }
-
- private static <T> void equalsOrThrow(String label, List<T> list, List<T> expected) {
- System.out.println("List: " + list);
- System.out.println("Expectd: " + list);
- if (!list.equals(expected)) {
- System.err.println("Observed " + label);
- for (T s1 : list) {
- System.out.println(" " + s1);
- }
- System.err.println("Expected " + label);
- for (T s2 : expected) {
- System.out.println(" " + s2);
- }
- throw new RuntimeException("Error with " + label);
- }
- }
-
-
- static class K {
- void k() {
- k1();
- }
- void k1() {
- k2();
- }
- void k2() {
- k3();
- }
- void k3() {
- k4();
- }
- void k4() {
- k5();
- }
- void k5() {
- k6();
- }
- void k6() {
- k7();
- }
- void k7() {
- k8();
- }
- void k8() {
- k9();
- }
- void k9() {
- k10();
- }
- void k10() {
- k20();
- }
- void k20() {
- new Caller().test();
- }
-
- class Caller {
- void test() {
- Class<?> c = StackWalker.getInstance(RETAIN_CLASS_REFERENCE).getCallerClass();
- System.out.println("\nTesting K class : " + c);
- Thread.dumpStack();
- if (c != K.class) {
- throw new RuntimeException("Unexpected caller class "+ c);
- }
- }
- }
- }
-
- static void caller() {
- Class<?> c = StackWalker.getInstance(RETAIN_CLASS_REFERENCE).getCallerClass();
- System.out.println("\ncaller class : " + c);
- if (c != G.class) {
- throw new RuntimeException("Unexpected caller class "+ c);
- }
- }
-
-}
--- a/jdk/test/java/lang/StackWalker/StackWalkTest.java Tue Nov 24 04:46:04 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,355 +0,0 @@
-/*
- * Copyright (c) 2015, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import static java.lang.StackWalker.Option.*;
-import java.lang.StackWalker.StackFrame;
-import java.util.Arrays;
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Random;
-import java.util.Set;
-import java.util.TreeSet;
-
-import jdk.testlibrary.RandomFactory;
-
-/**
- * @test
- * @bug 8140450
- * @summary Stack Walk Test (use -Dseed=X to set PRNG seed)
- * @library /lib/testlibrary
- * @build jdk.testlibrary.*
- * @compile StackRecorderUtil.java
- * @run main/othervm StackWalkTest
- * @run main/othervm/java.security.policy=stackwalktest.policy StackWalkTest
- * @run main/othervm StackWalkTest -random:50
- * @run main/othervm/java.security.policy=stackwalktest.policy StackWalkTest -random:50
- * @run main/othervm -XX:-MemberNameInStackFrame -Dstackwalk.newThrowable=false StackWalkTest -random:50
- * @run main/othervm -XX:-MemberNameInStackFrame -Dstackwalk.newThrowable=true StackWalkTest -random:50
- * @run main/othervm -XX:+MemberNameInStackFrame -Dstackwalk.newThrowable=false StackWalkTest -random:50
- * @run main/othervm -XX:+MemberNameInStackFrame -Dstackwalk.newThrowable=true StackWalkTest -random:50
- * @author danielfuchs, bchristi
- * @key randomness
- */
-public class StackWalkTest {
- private static boolean random = false;
- private static boolean verbose = false;
- private static int randomRuns = 50;
-
- private static final int MAX_RANDOM_DEPTH = 1000;
-
- static final Set<String> infrastructureClasses = new TreeSet<>(Arrays.asList(
- "sun.reflect.NativeMethodAccessorImpl",
- "sun.reflect.DelegatingMethodAccessorImpl",
- "java.lang.reflect.Method",
- "com.sun.javatest.regtest.MainWrapper$MainThread",
- "com.sun.javatest.regtest.agent.MainWrapper$MainThread",
- "java.lang.Thread"
- ));
- static final List<Class<?>> streamPipelines = Arrays.asList(
- classForName("java.util.stream.AbstractPipeline"),
- classForName("java.util.stream.TerminalOp")
- );
- static Class<?> classForName(String name) {
- try {
- return Class.forName(name);
- } catch (ClassNotFoundException e){
- throw new RuntimeException(e);
- }
- }
-
- private static boolean isStreamPipeline(Class<?> clazz) {
- for (Class<?> c : streamPipelines) {
- if (c.isAssignableFrom(clazz)) {
- return true;
- }
- }
- return false;
- }
-
- StackRecorderUtil recorder;
- int count = 0;
- boolean didWalk = false;
-
- final int estDepth;
- final Set<StackWalker.Option> swOptions;
-
- public StackWalkTest() {
- this(EnumSet.noneOf(StackWalker.Option.class), -1);
- }
-
- public StackWalkTest(Set<StackWalker.Option> swOptions) {
- this(swOptions, -1);
- }
-
- public StackWalkTest(int estimatedDepth) {
- this(EnumSet.noneOf(StackWalker.Option.class), -1);
- }
-
- public StackWalkTest(Set<StackWalker.Option> swOptions, int estimatedDepth) {
- this.swOptions = swOptions;
- this.estDepth = estimatedDepth;
- }
-
- private StackWalker createStackWalker() {
- // test all StackWalker factory methods
- if (this.estDepth < 0) {
- if (swOptions.isEmpty()) {
- return StackWalker.getInstance();
- } else {
- return StackWalker.getInstance(swOptions);
- }
- }
- return StackWalker.getInstance(swOptions, estDepth);
- }
- public void consume(StackFrame sf) {
- if (count == 0 && swOptions.contains(StackWalker.Option.RETAIN_CLASS_REFERENCE)
- && isStreamPipeline(sf.getDeclaringClass())) {
- return;
- }
- if (verbose) {
- System.out.println("\t" + sf.getClassName() + "." + sf.getMethodName());
- }
- if (count >= recorder.frameCount()) {
- // We've gone past main()...
- if (infrastructureClasses.contains(sf.getClassName())) {
- // safe to ignore
- return;
- }
- }
- try {
- recorder.compareFrame(count, sf);
- } catch (IndexOutOfBoundsException e) {
- // Extra non-infra frame in stream
- throw new RuntimeException("extra non-infra stack frame at count "
- + count + ": <" + sf + ">", e);
- }
- count++;
- }
-
- public class Call {
- public void walk(int total, int markAt) {
- recorder.add(Call.class, "walk", "StackWalkTest.java");
- long swFrameCount = createStackWalker().walk(s -> s.count());
-
- if (verbose) {
- System.out.println("Call.walk() total=" + total + ", markAt=" + markAt);
- System.out.println("recorder frames:");
- for (StackRecorderUtil.TestFrame f : recorder) {
- System.out.println("\t" + f.declaringClass + "." + f.methodName);
- }
- System.out.println("\nStackWalker recorded " + swFrameCount + " frames");
- System.out.flush();
- }
- long recFrameCount = (long)recorder.frameCount();
- if (swFrameCount < recFrameCount) {
- throw new RuntimeException("StackWalker recorded fewer frames ("+
- swFrameCount + ") than recorded ("+ recorder.frameCount() +
- ") - " + "estimatedDepth set to " + estDepth);
- }
- if (verbose) {
- System.out.println("StackWalker frames:");
- }
- createStackWalker().forEach(StackWalkTest.this::consume);
- didWalk = true;
- }
- public void call(int total, int current, int markAt) {
- recorder.add(Call.class, "call", "StackWalkTest.java");
- if (current < total) {
- testCall.call(total, current+1, markAt);
- } else {
- walk(total, markAt);
- }
- }
- }
-
- public class Marker extends Call {
- @Override
- public void call(int total, int current, int markAt) {
- recorder.add(Marker.class, "call", "StackWalkTest.java");
- if (current < total) {
- testCall.call(total, current+1, markAt);
- } else {
- walk(total, markAt);
- }
- }
- }
- private Call markerCall = new Marker();
-
- public class Test extends Call {
- @Override
- public void call(int total, int current, int markAt) {
- recorder.add(Test.class, "call", "StackWalkTest.java");
- if (current < total) {
- int nexti = current + 1;
- if (nexti==markAt) {
- markerCall.call(total, nexti, markAt);
- } else {
- testCall.call2(total, nexti, markAt);
- }
- } else {
- walk(total, markAt);
- }
- }
- public void call2(int total, int current, int markAt) {
- recorder.add(Test.class, "call2", "StackWalkTest.java");
- if (current < total) {
- int nexti = current + 1;
- if (nexti==markAt) {
- markerCall.call(total, nexti, markAt);
- } else {
- test2Call.call(total, nexti, markAt);
- }
- } else {
- walk(total, markAt);
- }
- }
- }
- private Test testCall = new Test();
-
- /** Inherits call() from Call */
- public class Test2 extends Call {}
- private Test2 test2Call = new Test2();
-
- public void runTest(Class callerClass, String callerMethod, int stackDepth,
- int markAt) {
- if (didWalk) {
- throw new IllegalStateException("StackWalkTest already used");
- }
- assert markAt <= stackDepth : "markAt(" + markAt + ") > stackDepth("
- + stackDepth + ")";
- System.out.print("runTest(" + swOptions
- + "), estimatedDepth=" + estDepth);
-
- recorder = new StackRecorderUtil(swOptions);
- recorder.add(callerClass, callerMethod, "StackWalkTest.java");
- recorder.add(StackWalkTest.class, "runTest", "StackWalkTest.java");
-
- Test test1 = new Test();
- test1.call(stackDepth, 0, markAt);
-
- System.out.println(" finished");
- if (!didWalk) {
- throw new IllegalStateException("Test wasn't actually performed");
- }
- }
-
- public static void main(String[] args) {
- String rand = "-random";
- String randItems = "-random:";
- for(String arg : args) {
- if (arg.startsWith(rand)) {
- random = true;
- try {
- if(arg.startsWith(randItems)) {
- randomRuns = Integer.valueOf(arg.substring(randItems.length()));
- }
- } catch(NumberFormatException e) {}
- } else if("-verbose".equals(arg)) {
- verbose = true;
- }
- }
- if (random) {
- Random rng = RandomFactory.getRandom();
- for (int iters = 0; iters < randomRuns; iters++) {
- Set<StackWalker.Option> opts = new HashSet<>();
- if (rng.nextBoolean()) {
- opts.add(RETAIN_CLASS_REFERENCE);
- }
-
- int depth = 1 + rng.nextInt(MAX_RANDOM_DEPTH);
-
- StackWalkTest swt;
- if (rng.nextBoolean() && depth > 1) {
- // Test that specifying an estimatedDepth doesn't prevent
- // full stack traversal
- swt = new StackWalkTest(opts, 1+rng.nextInt(depth-1));
- } else {
- swt = new StackWalkTest(opts);
- }
-
- int markAt = rng.nextInt(depth+1);
- System.out.print(depth + "@" + markAt + " ");
- System.out.flush();
- swt.runTest(StackWalkTest.class, "main", depth, markAt);
- }
- } else {
- // Long stack, default maxDepth
- StackWalkTest swt;
- swt = new StackWalkTest();
- swt.runTest(StackWalkTest.class, "main", 2000, 10);
-
- // Long stack, matching maxDepth
- swt = new StackWalkTest(2000);
- swt.runTest(StackWalkTest.class, "main", 2000, 10);
-
- // Long stack, maximum maxDepth
- swt = new StackWalkTest(Integer.MAX_VALUE);
- swt.runTest(StackWalkTest.class, "main", 2000, 10);
-
- //
- // Single batch
- //
- swt = new StackWalkTest(); // default maxDepth
- swt.runTest(StackWalkTest.class, "main", 6, 3);
-
- swt = new StackWalkTest(4); // maxDepth < stack
- swt.runTest(StackWalkTest.class, "main", 6, 3);
-
- swt = new StackWalkTest(2); // maxDepth < marker
- swt.runTest(StackWalkTest.class, "main", 6, 4);
-
- //
- // 2 batches
- //
- swt = new StackWalkTest(); // default maxDepth
- swt.runTest(StackWalkTest.class, "main", 24, 10);
- swt = new StackWalkTest(18); // maxDepth < stack
- swt.runTest(StackWalkTest.class, "main", 24, 10);
- swt = new StackWalkTest(8); // maxDepth < marker
- swt.runTest(StackWalkTest.class, "main", 24, 10);
-
- //
- // 3 batch
- //
- swt = new StackWalkTest(); // default maxDepth
- swt.runTest(StackWalkTest.class, "main", 60, 20);
- swt = new StackWalkTest(35); // maxDepth < stack
- swt.runTest(StackWalkTest.class, "main", 60, 20);
- swt = new StackWalkTest(8); // maxDepth < marker
- swt.runTest(StackWalkTest.class, "main", 60, 20);
-
- //
- // StackWalker.Options
- //
- swt = new StackWalkTest();
- swt.runTest(StackWalkTest.class, "main", 50, 10);
-
- swt = new StackWalkTest(EnumSet.of(RETAIN_CLASS_REFERENCE));
- swt.runTest(StackWalkTest.class, "main", 80, 40);
-
- swt = new StackWalkTest(EnumSet.of(RETAIN_CLASS_REFERENCE), 50);
- swt.runTest(StackWalkTest.class, "main", 2000, 1048);
- }
- }
-}
--- a/jdk/test/java/lang/StackWalker/VerifyStackTrace.java Tue Nov 24 04:46:04 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,284 +0,0 @@
-/*
- * Copyright (c) 2015, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.lang.reflect.InvocationTargetException;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.EnumSet;
-import java.util.concurrent.atomic.AtomicLong;
-import java.lang.StackWalker.StackFrame;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-import java.util.Objects;
-
-import static java.lang.StackWalker.Option.*;
-
-/**
- * @test
- * @bug 8140450
- * @summary Verify stack trace information obtained with respect to StackWalker
- * options, when the stack contains lambdas, method handle invoke
- * virtual calls, and reflection.
- * @run main/othervm -XX:-MemberNameInStackFrame VerifyStackTrace
- * @run main/othervm -XX:+MemberNameInStackFrame VerifyStackTrace
- * @run main/othervm/java.security.policy=stackwalk.policy VerifyStackTrace
- * @author danielfuchs
- */
-public class VerifyStackTrace {
-
- static interface TestCase {
- StackWalker walker();
- String description();
- String expected();
- }
- static final class TestCase1 implements TestCase {
- private final StackWalker walker = StackWalker.getInstance(RETAIN_CLASS_REFERENCE);
-
- private final String description = "StackWalker.getInstance(" +
- "StackWalker.Option.RETAIN_CLASS_REFERENCE)";
-
- // Note: line numbers and lambda hashes will be erased when
- // comparing stack traces. However, the stack may change
- // if some methods are being renamed in the code base.
- // If the JDKcode base changes and the test fails because of that,
- // then after validating that the actual stack trace obtained
- // is indeed correct (no frames are skipped that shouldn't)
- // then you can cut & paste the <-- actual --> stack printed in the
- // test output in here:
- private final String expected =
- "1: VerifyStackTrace.lambda$test$1(VerifyStackTrace.java:209)\n" +
- "2: VerifyStackTrace$Handle.execute(VerifyStackTrace.java:145)\n" +
- "3: VerifyStackTrace$Handle.run(VerifyStackTrace.java:158)\n" +
- "4: VerifyStackTrace.invoke(VerifyStackTrace.java:188)\n" +
- "5: VerifyStackTrace$1.run(VerifyStackTrace.java:218)\n" +
- "6: java.security.AccessController.doPrivileged(Native Method)\n" +
- "7: VerifyStackTrace.test(VerifyStackTrace.java:227)\n" +
- "8: VerifyStackTrace.main(VerifyStackTrace.java:182)\n";
-
- @Override public StackWalker walker() { return walker;}
- @Override public String description() { return description;}
- @Override public String expected() { return expected;}
- }
- static final class TestCase2 implements TestCase {
- private final StackWalker walker = StackWalker.getInstance(
- EnumSet.of(RETAIN_CLASS_REFERENCE, SHOW_REFLECT_FRAMES));
-
- private final String description = "nStackWalker.getInstance(" +
- "StackWalker.Option.RETAIN_CLASS_REFERENCE, " +
- "StackWalker.Option.SHOW_REFLECT_FRAMES)";
-
- // Note: line numbers and lambda hashes will be erased when
- // comparing stack traces. However, the stack may change
- // if some methods are being renamed in the code base.
- // If the JDK code base changes and the test fails because of that,
- // then after validating that the actual stack trace obtained
- // is indeed correct (no frames are skipped that shouldn't)
- // then you can cut & paste the <-- actual --> stack printed in the
- // test output in here (don't forget the final \n):
- private final String expected =
- "1: VerifyStackTrace.lambda$test$1(VerifyStackTrace.java:211)\n" +
- "2: VerifyStackTrace$Handle.execute(VerifyStackTrace.java:147)\n" +
- "3: VerifyStackTrace$Handle.run(VerifyStackTrace.java:160)\n" +
- "4: VerifyStackTrace.invoke(VerifyStackTrace.java:190)\n" +
- "5: sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n" +
- "6: sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n" +
- "7: sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n" +
- "8: java.lang.reflect.Method.invoke(Method.java:520)\n" +
- "9: VerifyStackTrace$1.run(VerifyStackTrace.java:220)\n" +
- "10: java.security.AccessController.doPrivileged(Native Method)\n" +
- "11: VerifyStackTrace.test(VerifyStackTrace.java:229)\n" +
- "12: VerifyStackTrace.main(VerifyStackTrace.java:185)\n";
-
- @Override public StackWalker walker() { return walker;}
- @Override public String description() { return description;}
- @Override public String expected() { return expected;}
- }
- static class TestCase3 implements TestCase {
- private final StackWalker walker = StackWalker.getInstance(
- EnumSet.of(RETAIN_CLASS_REFERENCE, SHOW_HIDDEN_FRAMES));
-
- private final String description = "StackWalker.getInstance(" +
- "StackWalker.Option.RETAIN_CLASS_REFERENCE, " +
- "StackWalker.Option.SHOW_HIDDEN_FRAMES)";
-
- // Note: line numbers and lambda hashes will be erased when
- // comparing stack traces. However, the stack may change
- // if some methods are being renamed in the code base.
- // If the JDK code base changes and the test fails because of that,
- // then after validating that the actual stack trace obtained
- // is indeed correct (no frames are skipped that shouldn't)
- // then you can cut & paste the <-- actual --> stack printed in the
- // test output in here (don't forget the final \n):
- private final String expected =
- "1: VerifyStackTrace.lambda$test$1(VerifyStackTrace.java:213)\n" +
- "2: VerifyStackTrace$$Lambda$1/662441761.run(Unknown Source)\n" +
- "3: VerifyStackTrace$Handle.execute(VerifyStackTrace.java:149)\n" +
- "4: java.lang.invoke.LambdaForm$DMH/2008017533.invokeVirtual_LL_V(LambdaForm$DMH)\n" +
- "5: java.lang.invoke.LambdaForm$MH/1395089624.invoke_MT(LambdaForm$MH)\n" +
- "6: VerifyStackTrace$Handle.run(VerifyStackTrace.java:162)\n" +
- "7: VerifyStackTrace.invoke(VerifyStackTrace.java:192)\n" +
- "8: sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n" +
- "9: sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n" +
- "10: sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n" +
- "11: java.lang.reflect.Method.invoke(Method.java:520)\n" +
- "12: VerifyStackTrace$1.run(VerifyStackTrace.java:222)\n" +
- "13: java.security.AccessController.doPrivileged(Native Method)\n" +
- "14: VerifyStackTrace.test(VerifyStackTrace.java:231)\n" +
- "15: VerifyStackTrace.main(VerifyStackTrace.java:188)\n";
-
- @Override public StackWalker walker() { return walker;}
- @Override public String description() { return description;}
- @Override public String expected() { return expected;}
- }
-
- static final class TestCase4 extends TestCase3 {
- private final StackWalker walker = StackWalker.getInstance(
- EnumSet.allOf(StackWalker.Option.class));
-
- private final String description = "StackWalker.getInstance(" +
- "StackWalker.Option.RETAIN_CLASS_REFERENCE, " +
- "StackWalker.Option.SHOW_HIDDEN_FRAMES, " +
- "StackWalker.Option.SHOW_REFLECT_FRAMES)";
-
- @Override public StackWalker walker() {return walker;}
- @Override public String description() {return description;}
- }
-
- public static class Handle implements Runnable {
-
- Runnable impl;
- public Handle(Runnable run) {
- this.impl = run;
- }
-
- public void execute(Runnable run) {
- run.run();
- }
-
- public void run() {
- MethodHandles.Lookup lookup = MethodHandles.lookup();
- MethodHandle handle = null;
- try {
- handle = lookup.findVirtual(Handle.class, "execute",
- MethodType.methodType(void.class, Runnable.class));
- } catch(NoSuchMethodException | IllegalAccessException x) {
- throw new RuntimeException(x);
- }
- try {
- handle.invoke(this, impl);
- } catch(Error | RuntimeException x) {
- throw x;
- } catch(Throwable t) {
- throw new RuntimeException(t);
- }
- }
- }
-
- static String prepare(String produced, boolean eraseSensitiveInfo) {
- if (eraseSensitiveInfo) {
- // Erase sensitive information before comparing:
- // comparing line numbers is too fragile, so we just erase them
- // out before comparing. We also erase the hash-like names of
- // synthetic frames introduced by lambdas & method handles
- return produced.replaceAll(":[1-9][0-9]*\\)", ":00)")
- .replaceAll("/[0-9]+\\.run", "/xxxxxxxx.run")
- .replaceAll("/[0-9]+\\.invoke", "/xxxxxxxx.invoke")
- .replaceAll("\\$[0-9]+", "\\$??");
- } else {
- return produced;
- }
- }
-
-
- public static void main(String[] args) {
- test(new TestCase1());
- test(new TestCase2());
- test(new TestCase3());
- test(new TestCase4());
- }
-
- public static void invoke(Runnable run) {
- run.run();
- }
-
- static final class Recorder {
- boolean found; // stop recording after main
- public void recordSTE(long counter, StringBuilder s, StackFrame f) {
- if (found) return;
- found = VerifyStackTrace.class.equals(f.getDeclaringClass()) &&
- "main".equals(f.getMethodName());
- String line = String.format("%d: %s", counter, f.toStackTraceElement());
- s.append(line).append('\n');
- System.out.println(line);
- }
- }
-
-
- static void test(TestCase test) {
- System.out.println("\nTesting: " + test.description());
- final AtomicLong counter = new AtomicLong();
- final StringBuilder builder = new StringBuilder();
- final Recorder recorder = new Recorder();
- final Runnable run = () -> test.walker().forEach(
- f -> recorder.recordSTE(counter.incrementAndGet(), builder, f));
- final Handle handle = new Handle(run);
-
- // We're not using lambda on purpose here. We want the anonymous
- // class on the stack.
- PrivilegedAction<Object> pa = new PrivilegedAction<Object>() {
- @Override
- public Object run() {
- try {
- return VerifyStackTrace.class
- .getMethod("invoke", Runnable.class)
- .invoke(null, handle);
- } catch (NoSuchMethodException
- | IllegalAccessException
- | InvocationTargetException ex) {
- System.out.flush();
- throw new RuntimeException(ex);
- }
- }
- };
- AccessController.doPrivileged(pa);
- System.out.println("Main found: " + recorder.found);
- if (!Objects.equals(prepare(test.expected(), true), prepare(builder.toString(), true))) {
- System.out.flush();
- try {
- // sleep to make it less likely that System.out & System.err will
- // interleave.
- Thread.sleep(1000);
- } catch (InterruptedException ex) {
- }
- System.err.println("\nUnexpected stack trace: "
- + "\n<!-- expected -->\n"
- + prepare(test.expected(), true)
- + "\n<-- actual -->\n"
- + prepare(builder.toString(), false));
- throw new RuntimeException("Unexpected stack trace for: " + test.description());
- }
- }
-
-
-}
--- a/jdk/test/java/lang/StackWalker/WalkFunction.java Tue Nov 24 04:46:04 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2015, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8140450
- * @summary Sanity test for Function wildcard signature
- * @run main WalkFunction
- */
-
-import java.lang.StackWalker.StackFrame;
-import java.util.Optional;
-import java.util.function.Function;
-import java.util.stream.Stream;
-
-public class WalkFunction {
- private static final StackWalker walker = StackWalker.getInstance();
-
- public static void main(String... args) throws Exception {
- testFunctions();
- testWildcards();
- walker.walk(counter());
- walker.walk(wildCounter());
- }
-
- private static void testFunctions() {
- walker.walk(Stream::count);
-
- try {
- walker.walk(null);
- throw new RuntimeException("NPE expected");
- } catch (NullPointerException e) {}
-
- Optional<StackFrame> result = walker.walk(WalkFunction::reduce);
- if (!result.get().getClassName().equals(WalkFunction.class.getName())) {
- throw new RuntimeException(result.get() + " expected: " + WalkFunction.class.getName());
- }
- }
-
- static Optional<StackFrame> reduce(Stream<StackFrame> stream) {
- return stream.reduce((r,f) -> r.getClassName().compareTo(f.getClassName()) > 0 ? f : r);
- }
-
- private static void testWildcards() {
- Function<? super Stream<? extends StackFrame>, Void> f1 = WalkFunction::function;
- Function<? super Stream<? super StackFrame>, Void> f2 = WalkFunction::function;
- Function<? super Stream<StackFrame>, Void> f3 = WalkFunction::function;
- Function<Stream<? extends StackFrame>, Void> f4 = WalkFunction::function;
- Function<Stream<? super StackFrame>, Void> f5 = WalkFunction::function;
- Function<Stream<StackFrame>, Void> f6 = WalkFunction::function;
- walker.walk(f1);
- walker.walk(f2);
- walker.walk(f3);
- walker.walk(f4);
- walker.walk(f5);
- walker.walk(f6);
- }
-
- private static Void function(Stream<?> s) {
- return null;
- }
-
- private static Function<Stream<?>, Long> wildCounter() {
- return Stream::count;
- }
- private static <T> Function<Stream<T>, Long> counter() {
- return Stream::count;
- }
-}
--- a/jdk/test/java/lang/StackWalker/noperms.policy Tue Nov 24 04:46:04 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-/*
- * grant nothing
- */
-grant {};
-
--- a/jdk/test/java/lang/StackWalker/stackwalk.policy Tue Nov 24 04:46:04 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-grant {
- permission java.lang.StackFramePermission "retainClassReference";
-};
-
--- a/jdk/test/java/lang/StackWalker/stackwalktest.policy Tue Nov 24 04:46:04 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-grant {
- permission java.lang.StackFramePermission "retainClassReference";
- permission java.util.PropertyPermission "seed", "read";
-};
-