1/* 2 * Copyright (c) 2016, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24import java.lang.reflect.Field; 25import java.lang.reflect.Method; 26import java.util.List; 27import java.util.Set; 28import java.util.stream.Collectors; 29import java.lang.StackWalker.StackFrame; 30 31public class LocalLongHelper { 32 static StackWalker sw; 33 static Method longValue; 34 static Method getLocals; 35 static Class<?> primitiveValueClass; 36 static Method primitiveSize; 37 static Method getMethodType; 38 static Field memberName; 39 static Field offset; 40 41 public static void main(String[] args) throws Throwable { 42 setupReflectionStatics(); 43 new LocalLongHelper().longArg(0xC0FFEE, 0x1234567890ABCDEFL); 44 } 45 46 // locals[2] contains the unused slot of the long argument. 47 public long longArg(int i, long l) throws Throwable { 48 List<StackFrame> frames = sw.walk(s -> s.collect(Collectors.toList())); 49 Object[] locals = (Object[]) getLocals.invoke(frames.get(0)); 50 51 if (8 == (int) primitiveSize.invoke(locals[2])) { // Only test 64-bit 52 long locals_2 = (long) longValue.invoke(locals[2]); 53 if (locals_2 != 0){ 54 throw new RuntimeException("Expected locals_2 == 0"); 55 } 56 } 57 return l; // Don't want l to become a dead var 58 } 59 60 private static void setupReflectionStatics() throws Throwable { 61 Class<?> liveStackFrameClass = Class.forName("java.lang.LiveStackFrame"); 62 primitiveValueClass = Class.forName("java.lang.LiveStackFrame$PrimitiveSlot"); 63 64 getLocals = liveStackFrameClass.getDeclaredMethod("getLocals"); 65 getLocals.setAccessible(true); 66 67 longValue = primitiveValueClass.getDeclaredMethod("longValue"); 68 longValue.setAccessible(true); 69 70 Class<?> stackFrameInfoClass = Class.forName("java.lang.StackFrameInfo"); 71 memberName = stackFrameInfoClass.getDeclaredField("memberName"); 72 memberName.setAccessible(true); 73 offset = stackFrameInfoClass.getDeclaredField("bci"); 74 offset.setAccessible(true); 75 getMethodType = Class.forName("java.lang.invoke.MemberName").getDeclaredMethod("getMethodType"); 76 getMethodType.setAccessible(true); 77 78 Class<?> extendedOptionClass = Class.forName("java.lang.StackWalker$ExtendedOption"); 79 Method ewsNI = StackWalker.class.getDeclaredMethod("newInstance", Set.class, extendedOptionClass); 80 ewsNI.setAccessible(true); 81 Field f = extendedOptionClass.getDeclaredField("LOCALS_AND_OPERANDS"); 82 f.setAccessible(true); 83 Object localsAndOperandsOption = f.get(null); 84 85 primitiveSize = primitiveValueClass.getDeclaredMethod("size"); 86 primitiveSize.setAccessible(true); 87 sw = (StackWalker) ewsNI.invoke(null, java.util.Collections.emptySet(), localsAndOperandsOption); 88 } 89} 90