1 /* 2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package java.lang; 26 27 import java.lang.StackWalker.Option; 28 import java.util.EnumSet; 29 import java.util.Set; 30 31 import static java.lang.StackWalker.ExtendedOption.*; 32 33 final class LiveStackFrameInfo extends StackFrameInfo implements LiveStackFrame { 34 private static Object[] EMPTY_ARRAY = new Object[0]; 35 36 /** 37 * Gets {@code StackWalker} that can get locals and operands. 38 * 39 * @throws SecurityException if the security manager is present and 40 * denies access to {@code RuntimePermission(""liveStackFrames")} 41 */ 42 public static StackWalker getStackWalker() { 43 return getStackWalker(EnumSet.noneOf(Option.class)); 44 } 45 46 47 /** 48 * Gets a {@code StackWalker} instance with the given options specifying 49 * the stack frame information it can access, and which will traverse at most 50 * the given {@code maxDepth} number of stack frames. If no option is 51 * specified, this {@code StackWalker} obtains the method name and 52 * the class name with all 53 * {@linkplain StackWalker.Option#SHOW_HIDDEN_FRAMES hidden frames} skipped. 54 * The returned {@code StackWalker} can get locals and operands. 55 * 56 * <p> 57 * If a security manager is present and the given 58 * {@code options} contains {@link Option#RETAIN_CLASS_REFERENCE}, it will call its 59 * {@link SecurityManager#checkPermission checkPermission} method for 60 * {@code StackFramePermission("classReference")}. 61 * 62 * @param options stack walk {@link Option options} 63 * 64 * @throws IllegalArgumentException if {@code maxDepth <= 0} 65 * @throws SecurityException if a security manager exists and its 66 * {@code checkPermission} method denies access. 67 * @throws SecurityException if the security manager is present and 68 * denies access to {@code RuntimePermission(""liveStackFrames")} 69 */ 70 public static StackWalker getStackWalker(Set<Option> options) { 71 SecurityManager sm = System.getSecurityManager(); 72 if (sm != null) { 73 sm.checkPermission(new RuntimePermission("liveStackFrames")); 74 } 75 return StackWalker.newInstance(options, LOCALS_AND_OPERANDS); 76 } 77 78 LiveStackFrameInfo(StackWalker walker) { 79 super(walker); 80 } 81 82 // These fields are initialized by the VM if ExtendedOption.LOCALS_AND_OPERANDS is set 83 private Object[] monitors = EMPTY_ARRAY; 84 private Object[] locals = EMPTY_ARRAY; 85 private Object[] operands = EMPTY_ARRAY; 86 87 @Override 88 public Object[] getMonitors() { 89 return monitors; 90 } 91 92 @Override 93 public Object[] getLocals() { 94 return locals; 95 } 96 97 @Override 98 public Object[] getStack() { 99 return operands; 100 } 101 102 /* 103 * Convert primitive value to {@code Primitive} object to represent 104 * a local variable or an element on the operand stack of primitive type. 105 */ 106 static PrimitiveValue asPrimitive(boolean value) { 107 return new BooleanPrimitive(value); 108 } 109 110 static PrimitiveValue asPrimitive(int value) { 111 return new IntPrimitive(value); 112 } 113 114 static PrimitiveValue asPrimitive(short value) { 115 return new ShortPrimitive(value); 116 } 117 118 static PrimitiveValue asPrimitive(char value) { 119 System.out.println("CharPrimitive " + value); 120 return new CharPrimitive(value); 121 } 122 123 static PrimitiveValue asPrimitive(byte value) { 124 return new BytePrimitive(value); 125 } 126 127 static PrimitiveValue asPrimitive(long value) { 128 return new LongPrimitive(value); 129 } 130 131 static PrimitiveValue asPrimitive(float value) { 132 return new FloatPrimitive(value); 133 } 134 135 static PrimitiveValue asPrimitive(double value) { 136 return new DoublePrimitive(value); 137 } 138 139 private static class IntPrimitive implements PrimitiveValue { 140 final int value; 141 IntPrimitive(int value) { 142 this.value = value; 143 } 144 145 @Override 146 public char type() { 147 return 'I'; 148 } 149 150 @Override 151 public int intValue() { 152 return value; 153 } 154 155 @Override 156 public String toString() { 157 return String.valueOf(value); 158 } 159 } 160 161 private static class ShortPrimitive implements PrimitiveValue { 162 final short value; 163 ShortPrimitive(short value) { 164 this.value = value; 165 } 166 167 @Override 168 public char type() { 169 return 'S'; 170 } 171 172 @Override 173 public short shortValue() { 174 return value; 175 } 176 177 @Override 178 public String toString() { 179 return String.valueOf(value); 180 } 181 } 182 183 private static class BooleanPrimitive implements PrimitiveValue { 184 final boolean value; 185 BooleanPrimitive(boolean value) { 186 this.value = value; 187 } 188 189 @Override 190 public char type() { 191 return 'Z'; 192 } 193 194 @Override 195 public boolean booleanValue() { 196 return value; 197 } 198 199 @Override 200 public String toString() { 201 return String.valueOf(value); 202 } 203 } 204 205 private static class CharPrimitive implements PrimitiveValue { 206 final char value; 207 CharPrimitive(char value) { 208 this.value = value; 209 } 210 211 @Override 212 public char type() { 213 return 'C'; 214 } 215 216 @Override 217 public char charValue() { 218 return value; 219 } 220 221 @Override 222 public String toString() { 223 return String.valueOf(value); 224 } 225 } 226 227 private static class BytePrimitive implements PrimitiveValue { 228 final byte value; 229 BytePrimitive(byte value) { 230 this.value = value; 231 } 232 233 @Override 234 public char type() { 235 return 'B'; 236 } 237 238 @Override 239 public byte byteValue() { 240 return value; 241 } 242 243 @Override 244 public String toString() { 245 return String.valueOf(value); 246 } 247 } 248 249 private static class LongPrimitive implements PrimitiveValue { 250 final long value; 251 LongPrimitive(long value) { 252 this.value = value; 253 } 254 255 @Override 256 public char type() { 257 return 'J'; 258 } 259 260 @Override 261 public long longValue() { 262 return value; 263 } 264 265 @Override 266 public String toString() { 267 return String.valueOf(value); 268 } 269 } 270 271 private static class FloatPrimitive implements PrimitiveValue { 272 final float value; 273 FloatPrimitive(float value) { 274 this.value = value; 275 } 276 277 @Override 278 public char type() { 279 return 'F'; 280 } 281 282 @Override 283 public float floatValue() { 284 return value; 285 } 286 287 @Override 288 public String toString() { 289 return String.valueOf(value); 290 } 291 } 292 293 private static class DoublePrimitive implements PrimitiveValue { 294 final double value; 295 DoublePrimitive(double value) { 296 this.value = value; 297 } 298 299 @Override 300 public char type() { 301 return 'D'; 302 } 303 304 @Override 305 public double doubleValue() { 306 return value; 307 } 308 309 @Override 310 public String toString() { 311 return String.valueOf(value); 312 } 313 } 314 }