1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. The Android Open Source 7 * Project designates this particular file as subject to the "Classpath" 8 * exception as provided by The Android Open Source Project in the LICENSE 9 * 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 22 package java.lang.invoke; 23 24 import java.lang.reflect.Constructor; 25 import java.lang.reflect.Member; 26 import java.lang.reflect.Method; 27 import java.lang.reflect.Modifier; 28 29 // Android-changed: Android specific implementation. 30 // The whole class was implemented from scratch for the Android runtime based 31 // on the specification of the MethodHandle class. 32 // The code does not originate from upstream OpenJDK. 33 /** 34 * A method handle that's directly associated with an ArtField or an ArtMethod and 35 * specifies no additional transformations. 36 * 37 * @hide 38 */ 39 public class MethodHandleImpl extends MethodHandle implements Cloneable { 40 private HandleInfo info; 41 MethodHandleImpl(long artFieldOrMethod, int handleKind, MethodType type)42 MethodHandleImpl(long artFieldOrMethod, int handleKind, MethodType type) { 43 super(artFieldOrMethod, handleKind, type); 44 } 45 46 @Override clone()47 public Object clone() throws CloneNotSupportedException { 48 return super.clone(); 49 } 50 reveal()51 MethodHandleInfo reveal() { 52 if (info == null) { 53 final Member member = getMemberInternal(); 54 info = new HandleInfo(member, this); 55 } 56 57 return info; 58 } 59 60 /** 61 * Materialize a member from this method handle's ArtField or ArtMethod pointer. 62 */ getMemberInternal()63 public native Member getMemberInternal(); 64 65 /** 66 * Implementation of {@code MethodHandleInfo} in terms of the handle being cracked 67 * and its corresponding {@code java.lang.reflect.Member}. 68 */ 69 static class HandleInfo implements MethodHandleInfo { 70 private final Member member; 71 private final MethodHandle handle; 72 HandleInfo(Member member, MethodHandle handle)73 HandleInfo(Member member, MethodHandle handle) { 74 this.member = member; 75 this.handle = handle; 76 } 77 78 @Override getReferenceKind()79 public int getReferenceKind() { 80 switch (handle.getHandleKind()) { 81 case INVOKE_VIRTUAL: { 82 if (member.getDeclaringClass().isInterface()) { 83 return REF_invokeInterface; 84 } else { 85 return REF_invokeVirtual; 86 } 87 } 88 89 case INVOKE_DIRECT: { 90 if (member instanceof Constructor) { 91 return REF_newInvokeSpecial; 92 } else { 93 return REF_invokeSpecial; 94 } 95 } 96 97 case INVOKE_SUPER: 98 return MethodHandleInfo.REF_invokeSpecial; 99 case INVOKE_STATIC: 100 return MethodHandleInfo.REF_invokeStatic; 101 case IGET: 102 return MethodHandleInfo.REF_getField; 103 case IPUT: 104 return MethodHandleInfo.REF_putField; 105 case SGET: 106 return MethodHandleInfo.REF_getStatic; 107 case SPUT: 108 return MethodHandleInfo.REF_putStatic; 109 default: 110 throw new AssertionError("Unexpected handle kind: " + handle.getHandleKind()); 111 } 112 } 113 114 @Override getDeclaringClass()115 public Class<?> getDeclaringClass() { 116 return member.getDeclaringClass(); 117 } 118 119 @Override getName()120 public String getName() { 121 if (member instanceof Constructor) { 122 return "<init>"; 123 } 124 125 return member.getName(); 126 } 127 128 @Override getMethodType()129 public MethodType getMethodType() { 130 // The "nominal" type of a cracked method handle is the same as the type 131 // of the handle itself, except in the cases enumerated below. 132 MethodType handleType = handle.type(); 133 134 boolean omitLeadingParam = false; 135 136 // For constructs, the return type is always void.class, and not the type of 137 // the object returned. We also need to omit the leading reference, which is 138 // nominally the type of the object being constructed. 139 if (member instanceof Constructor) { 140 handleType = handleType.changeReturnType(void.class); 141 omitLeadingParam = true; 142 } 143 144 // For instance field gets/puts and instance method gets/puts, we omit the 145 // leading reference parameter to |this|. 146 switch (handle.getHandleKind()) { 147 case IGET: 148 case IPUT: 149 case INVOKE_INTERFACE: 150 case INVOKE_DIRECT: 151 case INVOKE_VIRTUAL: 152 case INVOKE_SUPER: 153 omitLeadingParam = true; 154 } 155 156 return omitLeadingParam ? handleType.dropParameterTypes(0, 1) : handleType; 157 } 158 159 @Override reflectAs(Class<T> expected, MethodHandles.Lookup lookup)160 public <T extends Member> T reflectAs(Class<T> expected, MethodHandles.Lookup lookup) { 161 try { 162 final Class declaringClass = member.getDeclaringClass(); 163 if (Modifier.isNative(getModifiers()) && 164 (MethodHandle.class.isAssignableFrom(declaringClass) 165 || VarHandle.class.isAssignableFrom(declaringClass))) { 166 if (member instanceof Method) { 167 Method m = (Method) member; 168 if (m.isVarArgs()) { 169 // Signature-polymorphic methods should not be reflected as there 170 // is no support for invoking them via reflection. 171 // 172 // We've identified this method as signature-polymorphic due to 173 // its flags (var-args and native) and its class. 174 throw new IllegalArgumentException( 175 "Reflecting signature polymorphic method"); 176 } 177 } 178 } 179 lookup.checkAccess( 180 declaringClass, declaringClass, member.getModifiers(), member.getName()); 181 } catch (IllegalAccessException exception) { 182 throw new IllegalArgumentException("Unable to access member.", exception); 183 } 184 185 return (T) member; 186 } 187 188 @Override getModifiers()189 public int getModifiers() { 190 return member.getModifiers(); 191 } 192 193 @Override toString()194 public String toString() { 195 return MethodHandleInfo.toString( 196 getReferenceKind(), getDeclaringClass(), getName(), getMethodType()); 197 } 198 } 199 } 200