1 import java.lang.reflect.Field; 2 import java.lang.reflect.Method; 3 import java.util.List; 4 import java.util.Set; 5 import java.util.stream.Collectors; 6 import java.lang.StackWalker.StackFrame; 7 8 public class LocalLongHelper { 9 static StackWalker sw; 10 static Method intValue; 11 static Method getLocals; 12 static Class<?> primitiveValueClass; 13 static Method primitiveType; 14 static Method getMethodType; 15 static Field memberName; 16 static Field offset; 17 18 public static void main(String[] args) throws Throwable { 19 setupReflectionStatics(); 20 new LocalLongHelper().longArg(0xC0FFEE, 0x1234567890ABCDEFL); 21 } 22 23 /* 24 * The first 4 local slots should be: 25 * 0: this 26 * 1: int "i" 27 * 2: long "l", first slot 28 * 3: long "l", second slot 29 */ 30 public long longArg(int i, long l) throws Throwable { 31 List<StackFrame> frames = sw.walk(s -> s.collect(Collectors.toList())); 32 Object[] locals = (Object[]) getLocals.invoke(frames.get(0)); 33 34 int locals_1 = (int) intValue.invoke(locals[1]); // java.lang.LiveStackFrame$PrimitiveValue.intValue() 35 int locals_2 = (int) intValue.invoke(locals[2]); 36 int locals_3 = (int) intValue.invoke(locals[3]); 37 if (locals_2 != 0){ 38 throw new RuntimeException("Expected locals_2 == 0"); 39 } 40 return l; // Don't want l to become a dead var 41 } 42 43 private static void setupReflectionStatics() throws Throwable { 44 Class<?> liveStackFrameClass = Class.forName("java.lang.LiveStackFrame"); 45 primitiveValueClass = Class.forName("java.lang.LiveStackFrame$PrimitiveValue"); 46 47 getLocals = liveStackFrameClass.getDeclaredMethod("getLocals"); 48 getLocals.setAccessible(true); 49 50 intValue = primitiveValueClass.getDeclaredMethod("intValue"); 51 intValue.setAccessible(true); 52 53 Class<?> stackFrameInfoClass = Class.forName("java.lang.StackFrameInfo"); 54 memberName = stackFrameInfoClass.getDeclaredField("memberName"); 55 memberName.setAccessible(true); 56 offset = stackFrameInfoClass.getDeclaredField("bci"); 57 offset.setAccessible(true); 58 getMethodType = Class.forName("java.lang.invoke.MemberName").getDeclaredMethod("getMethodType"); 59 getMethodType.setAccessible(true); 60 61 Class<?> extendedOptionClass = Class.forName("java.lang.StackWalker$ExtendedOption"); 62 Method ewsNI = StackWalker.class.getDeclaredMethod("newInstance", Set.class, extendedOptionClass); 63 ewsNI.setAccessible(true); 64 Field f = extendedOptionClass.getDeclaredField("LOCALS_AND_OPERANDS"); 65 f.setAccessible(true); 66 Object localsAndOperandsOption = f.get(null); 67 68 primitiveType = primitiveValueClass.getDeclaredMethod("type"); 69 primitiveType.setAccessible(true); 70 71 sw = (StackWalker) ewsNI.invoke(null, java.util.Collections.emptySet(), localsAndOperandsOption); 72 } 73 74 private static String type(Object o) throws Throwable { 75 if (primitiveValueClass.isInstance(o)) { 76 final char c = (char) primitiveType.invoke(o); 77 return String.valueOf(c); 78 } else if (o != null) { 79 return o.getClass().getName(); 80 } else { 81 return "null"; 82 } 83 } 84 }