1 /* 2 * Copyright (c) 2018, 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.constant; 26 27 import java.lang.invoke.MethodHandle; 28 import java.lang.invoke.MethodHandleInfo; 29 import java.lang.invoke.MethodHandles; 30 31 import jdk.internal.vm.annotation.Stable; 32 33 import static java.lang.invoke.MethodHandleInfo.REF_getField; 34 import static java.lang.invoke.MethodHandleInfo.REF_getStatic; 35 import static java.lang.invoke.MethodHandleInfo.REF_invokeInterface; 36 import static java.lang.invoke.MethodHandleInfo.REF_invokeSpecial; 37 import static java.lang.invoke.MethodHandleInfo.REF_invokeStatic; 38 import static java.lang.invoke.MethodHandleInfo.REF_invokeVirtual; 39 import static java.lang.invoke.MethodHandleInfo.REF_newInvokeSpecial; 40 import static java.lang.invoke.MethodHandleInfo.REF_putField; 41 import static java.lang.invoke.MethodHandleInfo.REF_putStatic; 42 43 /** 44 * A <a href="package-summary.html#nominal">nominal descriptor</a> for a direct 45 * {@link MethodHandle}. A {@linkplain DirectMethodHandleDescImpl} corresponds to 46 * a {@code Constant_MethodHandle_info} entry in the constant pool of a classfile. 47 * 48 * @apiNote In the future, if the Java language permits, {@linkplain DirectMethodHandleDesc} 49 * may become a {@code sealed} interface, which would prohibit subclassing except 50 * by explicitly permitted types. Non-platform classes should not implement 51 * {@linkplain DirectMethodHandleDesc} directly. 52 */ 53 public interface DirectMethodHandleDesc extends MethodHandleDesc { 54 /** 55 * Kinds of method handles that can be described with {@linkplain DirectMethodHandleDesc}. 56 */ 57 enum Kind { 58 /** A method handle for a method invoked as with {@code invokestatic} */ 59 STATIC(REF_invokeStatic), 60 /** A method handle for a method invoked as with {@code invokestatic} */ 61 INTERFACE_STATIC(REF_invokeStatic, true), 62 /** A method handle for a method invoked as with {@code invokevirtual} */ 63 VIRTUAL(REF_invokeVirtual), 64 /** A method handle for a method invoked as with {@code invokeinterface} */ 65 INTERFACE_VIRTUAL(REF_invokeInterface, true), 66 /** A method handle for a method invoked as with {@code invokespecial} */ 67 SPECIAL(REF_invokeSpecial), 68 /** A method handle for an interface method invoked as with {@code invokespecial} */ 69 INTERFACE_SPECIAL(REF_invokeSpecial, true), 70 /** A method handle for a constructor */ 71 CONSTRUCTOR(REF_newInvokeSpecial), 72 /** A method handle for a read accessor for an instance field */ 73 GETTER(REF_getField), 74 /** A method handle for a write accessor for an instance field */ 75 SETTER(REF_putField), 76 /** A method handle for a read accessor for a static field */ 77 STATIC_GETTER(REF_getStatic), 78 /** A method handle for a write accessor for a static field */ 79 STATIC_SETTER(REF_putStatic); 80 81 /** The corresponding {@code refKind} value for this kind of method handle, 82 * as defined by {@link MethodHandleInfo} 83 */ 84 public final int refKind; 85 86 /** Is this an interface 87 */ 88 public final boolean isInterface; 89 Kind(int refKind) { 90 this(refKind, false); 91 } 92 93 Kind(int refKind, boolean isInterface) { this.refKind = refKind; this.isInterface = isInterface; } 94 95 /** 96 * Find the enumeration member with the given {@code refKind} field. 97 * More precisely, invoke {@code valueOf(refKind, false)}. 98 * @param refKind refKind of desired member 99 * @return the matching enumeration member 100 * @throws IllegalArgumentException if there is no such member 101 */ 102 public static Kind valueOf(int refKind) { 103 return valueOf(refKind, false); 104 } 105 106 /** 107 * Find the enumeration member with the given {@code refKind} and 108 * {@code isInterface} fields. 109 * If {@code isInterface} is true and there is no such enumeration member, 110 * return the member, if any, with the same {@code refKind} and a false 111 * {@code isInterface} field. 112 * If {@code isInterface} is false and {@code refKind} is {@code REF_invokeInterface} 113 * return {@code INTERFACE_VIRTUAL}. 114 * @param refKind refKind of desired member 115 * @param isInterface whether desired member is for interface methods 116 * @return the matching enumeration member 117 * @throws IllegalArgumentException if there is no such member 118 */ 119 public static Kind valueOf(int refKind, boolean isInterface) { 120 int i = tableIndex(refKind, isInterface); 121 if (i >= 0 && i < TABLE.length) { 122 Kind kind = TABLE[i]; 123 if (kind.refKind == refKind && kind.isInterface == isInterface) { 124 return kind; 125 } 126 } 127 if (isInterface) return valueOf(refKind); 128 if (refKind == REF_invokeInterface) return INTERFACE_VIRTUAL; 129 throw new IllegalArgumentException("refKind="+refKind+(isInterface?"&isInterface":"")); 130 } 131 private static int tableIndex(int refKind, boolean isInterface) { 132 if (refKind < 0) return refKind; 133 return (refKind * 2) + (isInterface ? 1 : 0); 134 } 135 private static final @Stable Kind[] TABLE = new Kind[20]; 136 static { 137 // Pack the static table. 138 for (Kind kind : values()) { 139 int i = tableIndex(kind.refKind, kind.isInterface); 140 if (i >= TABLE.length || TABLE[i] != null) 141 throw new AssertionError("TABLE entry for "+kind); 142 TABLE[i] = kind; 143 } 144 } 145 } 146 /** 147 * Return the {@code kind} of the method handle described by this nominal 148 * descriptor. 149 * 150 * @return the {@link Kind} 151 */ 152 Kind kind(); 153 154 /** 155 * Return the {@code refKind} of the method handle described by this nominal 156 * reference, as defined by {@link MethodHandleInfo}. 157 * 158 * @return the reference kind 159 */ 160 int refKind(); 161 162 /** 163 * Indicates if the method is declared by an interface 164 * 165 * @return true if the method is declared by an interface 166 */ 167 boolean isOwnerInterface(); 168 169 /** 170 * Return a {@link ClassDesc} describing the class declaring the 171 * method or field described by this nominal descriptor. 172 * 173 * @return the class declaring the method or field 174 */ 175 ClassDesc owner(); 176 177 /** 178 * Return the name of the method or field described by this nominal descriptor. 179 * 180 * @return the name of the method or field 181 */ 182 String methodName(); 183 184 /** 185 * Return a {@link MethodTypeDesc} describing the invocation type of the 186 * method handle described by this nominal descriptor 187 * 188 * @return the method type 189 */ 190 MethodTypeDesc methodType(); 191 }