• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2018, 2019, 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.MethodHandles;
29 import java.lang.invoke.MethodType;
30 
31 import static java.lang.constant.ConstantDescs.CD_void;
32 import static java.lang.constant.DirectMethodHandleDesc.Kind.CONSTRUCTOR;
33 
34 /**
35  * A <a href="package-summary.html#nominal">nominal descriptor</a> for a
36  * {@link MethodHandle} constant.
37  *
38  * @since 12
39  */
40 public sealed interface MethodHandleDesc
41         extends ConstantDesc
42         permits AsTypeMethodHandleDesc,
43                 DirectMethodHandleDesc {
44 
45     /**
46      * Creates a {@linkplain MethodHandleDesc} corresponding to an invocation of a
47      * declared method, invocation of a constructor, or access to a field.
48      *
49      * <p>The lookup descriptor string has the same format as for the various
50      * variants of {@code CONSTANT_MethodHandle_info} and for the lookup
51      * methods on {@link MethodHandles.Lookup}.  For a method or constructor
52      * invocation, it is interpreted as a method type descriptor; for field
53      * access, it is interpreted as a field descriptor.  If {@code kind} is
54      * {@code CONSTRUCTOR}, the {@code name} parameter is ignored and the return
55      * type of the lookup descriptor must be {@code void}.  If {@code kind}
56      * corresponds to a virtual method invocation, the lookup type includes the
57      * method parameters but not the receiver type.
58      *
59      * @param kind The kind of method handle to be described
60      * @param owner a {@link ClassDesc} describing the class containing the
61      *              method, constructor, or field
62      * @param name the unqualified name of the method or field (ignored if
63      *             {@code kind} is {@code CONSTRUCTOR})
64      * @param lookupDescriptor a method descriptor string the lookup type,
65      *                         if the request is for a method invocation, or
66      *                         describing the invocation type, if the request is
67      *                         for a field or constructor
68      * @return the {@linkplain MethodHandleDesc}
69      * @throws NullPointerException if any of the non-ignored arguments are null
70      * @throws IllegalArgumentException if the descriptor string is not a valid
71      * method or field descriptor
72      * @jvms 4.4.8 The CONSTANT_MethodHandle_info Structure
73      * @jvms 4.2.2 Unqualified Names
74      * @jvms 4.3.2 Field Descriptors
75      * @jvms 4.3.3 Method Descriptors
76      */
of(DirectMethodHandleDesc.Kind kind, ClassDesc owner, String name, String lookupDescriptor)77     static DirectMethodHandleDesc of(DirectMethodHandleDesc.Kind kind,
78                                      ClassDesc owner,
79                                      String name,
80                                      String lookupDescriptor) {
81         switch (kind) {
82             case GETTER:
83             case SETTER:
84             case STATIC_GETTER:
85             case STATIC_SETTER:
86                 return ofField(kind, owner, name, ClassDesc.ofDescriptor(lookupDescriptor));
87             default:
88                 return new DirectMethodHandleDescImpl(kind, owner, name, MethodTypeDesc.ofDescriptor(lookupDescriptor));
89         }
90     }
91 
92     /**
93      * Creates a {@linkplain MethodHandleDesc} corresponding to an invocation of a
94      * declared method or constructor.
95      *
96      * <p>The lookup descriptor string has the same format as for the lookup
97      * methods on {@link MethodHandles.Lookup}.  If {@code kind} is
98      * {@code CONSTRUCTOR}, the name is ignored and the return type of the lookup
99      * type must be {@code void}.  If {@code kind} corresponds to a virtual method
100      * invocation, the lookup type includes the method parameters but not the
101      * receiver type.
102      *
103      * @param kind The kind of method handle to be described; must be one of
104      *             {@code SPECIAL, VIRTUAL, STATIC, INTERFACE_SPECIAL,
105      *             INTERFACE_VIRTUAL, INTERFACE_STATIC, CONSTRUCTOR}
106      * @param owner a {@link ClassDesc} describing the class containing the
107      *              method or constructor
108      * @param name the unqualified name of the method (ignored if {@code kind}
109      *             is {@code CONSTRUCTOR})
110      * @param lookupMethodType a {@link MethodTypeDesc} describing the lookup type
111      * @return the {@linkplain MethodHandleDesc}
112      * @throws NullPointerException if any non-ignored arguments are null
113      * @throws IllegalArgumentException if the {@code name} has the incorrect
114      * format, or the kind is invalid
115      * @jvms 4.2.2 Unqualified Names
116      */
ofMethod(DirectMethodHandleDesc.Kind kind, ClassDesc owner, String name, MethodTypeDesc lookupMethodType)117     static DirectMethodHandleDesc ofMethod(DirectMethodHandleDesc.Kind kind,
118                                            ClassDesc owner,
119                                            String name,
120                                            MethodTypeDesc lookupMethodType) {
121         switch (kind) {
122             case GETTER:
123             case SETTER:
124             case STATIC_GETTER:
125             case STATIC_SETTER:
126                 throw new IllegalArgumentException(kind.toString());
127             case VIRTUAL:
128             case SPECIAL:
129             case INTERFACE_VIRTUAL:
130             case INTERFACE_SPECIAL:
131             case INTERFACE_STATIC:
132             case STATIC:
133             case CONSTRUCTOR:
134                 return new DirectMethodHandleDescImpl(kind, owner, name, lookupMethodType);
135             default:
136                 throw new IllegalArgumentException(kind.toString());
137         }
138     }
139 
140     /**
141      * Creates a {@linkplain MethodHandleDesc} corresponding to a method handle
142      * that accesses a field.
143      *
144      * @param kind the kind of the method handle to be described; must be one of {@code GETTER},
145      *             {@code SETTER}, {@code STATIC_GETTER}, or {@code STATIC_SETTER}
146      * @param owner a {@link ClassDesc} describing the class containing the field
147      * @param fieldName the unqualified name of the field
148      * @param fieldType a {@link ClassDesc} describing the type of the field
149      * @return the {@linkplain MethodHandleDesc}
150      * @throws NullPointerException if any of the arguments are null
151      * @throws IllegalArgumentException if the {@code kind} is not one of the
152      * valid values or if the field name is not valid
153      * @jvms 4.2.2 Unqualified Names
154      */
ofField(DirectMethodHandleDesc.Kind kind, ClassDesc owner, String fieldName, ClassDesc fieldType)155     static DirectMethodHandleDesc ofField(DirectMethodHandleDesc.Kind kind,
156                                           ClassDesc owner,
157                                           String fieldName,
158                                           ClassDesc fieldType) {
159         MethodTypeDesc mtr = switch (kind) {
160             case GETTER        -> MethodTypeDesc.of(fieldType, owner);
161             case SETTER        -> MethodTypeDesc.of(CD_void, owner, fieldType);
162             case STATIC_GETTER -> MethodTypeDesc.of(fieldType);
163             case STATIC_SETTER -> MethodTypeDesc.of(CD_void, fieldType);
164             default -> throw new IllegalArgumentException(kind.toString());
165         };
166         return new DirectMethodHandleDescImpl(kind, owner, fieldName, mtr);
167     }
168 
169     /**
170      * Returns a {@linkplain MethodHandleDesc} corresponding to invocation of a constructor
171      *
172      * @param owner a {@link ClassDesc} describing the class containing the
173      *              constructor
174      * @param paramTypes {@link ClassDesc}s describing the parameter types of
175      *                   the constructor
176      * @return the {@linkplain MethodHandleDesc}
177      * @throws NullPointerException if any argument or its contents is {@code null}
178      */
ofConstructor(ClassDesc owner, ClassDesc... paramTypes)179     static DirectMethodHandleDesc ofConstructor(ClassDesc owner,
180                                                 ClassDesc... paramTypes) {
181         return MethodHandleDesc.ofMethod(CONSTRUCTOR, owner, ConstantDescs.DEFAULT_NAME,
182                                          MethodTypeDesc.of(CD_void, paramTypes));
183     }
184 
185     /**
186      * Returns a {@linkplain MethodHandleDesc} that describes this method handle
187      * adapted to a different type, as if by {@link MethodHandle#asType(MethodType)}.
188      *
189      * @param type a {@link MethodHandleDesc} describing the new method type
190      * @return a {@linkplain MethodHandleDesc} for the adapted method handle
191      * @throws NullPointerException if the argument is {@code null}
192      */
asType(MethodTypeDesc type)193     default MethodHandleDesc asType(MethodTypeDesc type) {
194         return (invocationType().equals(type)) ? this : new AsTypeMethodHandleDesc(this, type);
195     }
196 
197     /**
198      * Returns a {@link MethodTypeDesc} describing the invocation type of the
199      * method handle described by this nominal descriptor.  The invocation type
200      * describes the full set of stack values that are consumed by the invocation
201      * (including the receiver, if any).
202      *
203      * @return a {@linkplain MethodHandleDesc} describing the method handle type
204      */
invocationType()205     MethodTypeDesc invocationType();
206 
207     /**
208      * Compares the specified object with this descriptor for equality.  Returns
209      * {@code true} if and only if the specified object is also a
210      * {@linkplain MethodHandleDesc}, and both encode the same nominal description
211      * of a method handle.
212      *
213      * @param o the other object
214      * @return whether this descriptor is equal to the other object
215      */
equals(Object o)216     boolean equals(Object o);
217 }
218