import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.List; import java.util.Set; import java.util.stream.Collectors; import java.lang.StackWalker.StackFrame; public class LocalLongHelper { static StackWalker sw; static Method intValue; static Method getLocals; static Class primitiveValueClass; static Method primitiveType; static Method getMethodType; static Field memberName; static Field offset; public static void main(String[] args) throws Throwable { setupReflectionStatics(); new LocalLongHelper().longArg(0xC0FFEE, 0x1234567890ABCDEFL); } /* * The first 4 local slots should be: * 0: this * 1: int "i" * 2: long "l", first slot * 3: long "l", second slot */ public long longArg(int i, long l) throws Throwable { List frames = sw.walk(s -> s.collect(Collectors.toList())); Object[] locals = (Object[]) getLocals.invoke(frames.get(0)); int locals_1 = (int) intValue.invoke(locals[1]); // java.lang.LiveStackFrame$PrimitiveValue.intValue() int locals_2 = (int) intValue.invoke(locals[2]); int locals_3 = (int) intValue.invoke(locals[3]); if (locals_2 != 0){ throw new RuntimeException("Expected locals_2 == 0"); } return l; // Don't want l to become a dead var } private static void setupReflectionStatics() throws Throwable { Class liveStackFrameClass = Class.forName("java.lang.LiveStackFrame"); primitiveValueClass = Class.forName("java.lang.LiveStackFrame$PrimitiveValue"); getLocals = liveStackFrameClass.getDeclaredMethod("getLocals"); getLocals.setAccessible(true); intValue = primitiveValueClass.getDeclaredMethod("intValue"); intValue.setAccessible(true); Class stackFrameInfoClass = Class.forName("java.lang.StackFrameInfo"); memberName = stackFrameInfoClass.getDeclaredField("memberName"); memberName.setAccessible(true); offset = stackFrameInfoClass.getDeclaredField("bci"); offset.setAccessible(true); getMethodType = Class.forName("java.lang.invoke.MemberName").getDeclaredMethod("getMethodType"); getMethodType.setAccessible(true); Class extendedOptionClass = Class.forName("java.lang.StackWalker$ExtendedOption"); Method ewsNI = StackWalker.class.getDeclaredMethod("newInstance", Set.class, extendedOptionClass); ewsNI.setAccessible(true); Field f = extendedOptionClass.getDeclaredField("LOCALS_AND_OPERANDS"); f.setAccessible(true); Object localsAndOperandsOption = f.get(null); primitiveType = primitiveValueClass.getDeclaredMethod("type"); primitiveType.setAccessible(true); sw = (StackWalker) ewsNI.invoke(null, java.util.Collections.emptySet(), localsAndOperandsOption); } private static String type(Object o) throws Throwable { if (primitiveValueClass.isInstance(o)) { final char c = (char) primitiveType.invoke(o); return String.valueOf(c); } else if (o != null) { return o.getClass().getName(); } else { return "null"; } } }