1 /*
2 * Copyright 2014 - 2020 Rafael Winterhalter
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package net.bytebuddy.utility;
17
18 import net.bytebuddy.build.CachedReturnPlugin;
19 import net.bytebuddy.description.type.TypeDefinition;
20 import net.bytebuddy.description.type.TypeDescription;
21 import net.bytebuddy.description.type.TypeList;
22 import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
23 import net.bytebuddy.jar.asm.Opcodes;
24
25 import java.io.Serializable;
26 import java.lang.reflect.*;
27
28 /**
29 * Representations of Java types that do not exist in Java 6 but that have a special meaning to the JVM.
30 */
31 public enum JavaType {
32
33 /**
34 * The Java 12 {@code java.lang.constant.Constable} type.
35 */
36 CONSTABLE("java.lang.constant.Constable", Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE, TypeDescription.UNDEFINED),
37
38 /**
39 * The Java 12 {@code java.lang.invoke.TypeDescriptor} type.
40 */
41 TYPE_DESCRIPTOR("java.lang.invoke.TypeDescriptor", Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE, TypeDescription.UNDEFINED),
42
43 /**
44 * The Java 12 {@code java.lang.invoke.TypeDescriptor$OfMethod} type.
45 */
46 TYPE_DESCRIPTOR_OF_FIELD("java.lang.invoke.TypeDescriptor$OfField",
47 Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE,
48 TypeDescription.UNDEFINED,
49 TYPE_DESCRIPTOR.getTypeStub()),
50
51 /**
52 * The Java 12 {@code java.lang.invoke.TypeDescriptor$OfMethod} type.
53 */
54 TYPE_DESCRIPTOR_OF_METHOD("java.lang.invoke.TypeDescriptor$OfMethod",
55 Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE,
56 TypeDescription.UNDEFINED,
57 TYPE_DESCRIPTOR.getTypeStub()),
58
59 /**
60 * The Java 12 {@code java.lang.constant.ConstableDesc} type.
61 */
62 CONSTANT_DESCRIPTION("java.lang.constant.ConstantDesc", Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE, TypeDescription.UNDEFINED),
63
64 /**
65 * The Java 12 {@code java.lang.constant.DynamicConstantDesc} type.
66 */
67 DYNAMIC_CONSTANT_DESCRIPTION("java.lang.constant.DynamicConstantDesc",
68 Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT,
69 TypeDescription.OBJECT,
70 CONSTANT_DESCRIPTION.getTypeStub()),
71
72 /**
73 * The Java 12 {@code java.lang.constant.ClassDesc} type.
74 */
75 CLASS_DESCRIPTION("java.lang.constant.ClassDesc",
76 Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE,
77 TypeDescription.UNDEFINED,
78 CONSTANT_DESCRIPTION.getTypeStub(),
79 TYPE_DESCRIPTOR_OF_FIELD.getTypeStub()),
80
81 /**
82 * The Java 12 {@code java.lang.constant.MethodTypeDesc} type.
83 */
84 METHOD_TYPE_DESCRIPTION("java.lang.constant.MethodTypeDesc",
85 Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE,
86 TypeDescription.UNDEFINED,
87 CONSTANT_DESCRIPTION.getTypeStub(),
88 TYPE_DESCRIPTOR_OF_METHOD.getTypeStub()),
89
90 /**
91 * The Java 12 {@code java.lang.constant.MethodHandleDesc} type.
92 */
93 METHOD_HANDLE_DESCRIPTION("java.lang.constant.MethodHandleDesc",
94 Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE,
95 TypeDescription.UNDEFINED,
96 CONSTANT_DESCRIPTION.getTypeStub()),
97
98 /**
99 * The Java 12 {@code java.lang.constant.DirectMethodHandleDesc} type.
100 */
101 DIRECT_METHOD_HANDLE_DESCRIPTION("java.lang.constant.DirectMethodHandleDesc",
102 Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE,
103 TypeDescription.UNDEFINED,
104 METHOD_HANDLE_DESCRIPTION.getTypeStub()),
105
106 /**
107 * The Java 7 {@code java.lang.invoke.MethodHandle} type.
108 */
109 METHOD_HANDLE("java.lang.invoke.MethodHandle", Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT, TypeDescription.OBJECT, CONSTABLE.getTypeStub()),
110
111 /**
112 * The Java 7 {@code java.lang.invoke.MethodHandles} type.
113 */
114 METHOD_HANDLES("java.lang.invoke.MethodHandles", Opcodes.ACC_PUBLIC, Object.class),
115
116 /**
117 * The Java 7 {@code java.lang.invoke.MethodType} type.
118 */
119 METHOD_TYPE("java.lang.invoke.MethodType",
120 Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL,
121 TypeDescription.OBJECT,
122 CONSTABLE.getTypeStub(),
123 TYPE_DESCRIPTOR_OF_METHOD.getTypeStub(),
124 TypeDescription.ForLoadedType.of(Serializable.class)),
125
126 /**
127 * The Java 7 {@code java.lang.invoke.MethodTypes.Lookup} type.
128 */
129 METHOD_HANDLES_LOOKUP("java.lang.invoke.MethodHandles$Lookup", Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL, Object.class),
130
131 /**
132 * The Java 7 {@code java.lang.invoke.CallSite} type.
133 */
134 CALL_SITE("java.lang.invoke.CallSite", Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT, Object.class),
135
136 /**
137 * The Java 9 {@code java.lang.invoke.VarHandle} type.
138 */
139 VAR_HANDLE("java.lang.invoke.VarHandle", Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT, TypeDescription.Generic.OBJECT, CONSTABLE.getTypeStub()),
140
141 /**
142 * The Java 8 {@code java.lang.reflect.Parameter} type.
143 */
144 PARAMETER("java.lang.reflect.Parameter", Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, Object.class, AnnotatedElement.class),
145
146 /**
147 * The Java 7 {@code java.lang.reflect.Executable} type.
148 */
149 EXECUTABLE("java.lang.reflect.Executable", Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT, AccessibleObject.class, Member.class, GenericDeclaration.class),
150
151 /**
152 * The Java 9 {@code java.lang.Module} type.
153 */
154 MODULE("java.lang.Module", Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, Object.class, AnnotatedElement.class),
155
156 /**
157 * The Java 14 {@code java.lang.Record} type.
158 */
159 RECORD("java.lang.Record", Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT, Object.class),
160
161 /**
162 * The Java 14 {@code java.lang.runtime.ObjectMethods} type.
163 */
164 OBJECT_METHODS("java.lang.runtime.ObjectMethods", Opcodes.ACC_PUBLIC, Object.class);
165
166 /**
167 * The type description to represent this type which is either a loaded type or a stub.
168 */
169 private final TypeDescription typeDescription;
170
171 /**
172 * Creates a new java type representation.
173 *
174 * @param typeName The binary name of this type.
175 * @param modifiers The modifiers of this type when creating a stub.
176 * @param superClass The super class of this type when creating a stub.
177 * @param anInterface The interfaces of this type when creating a stub.
178 */
179 JavaType(String typeName, int modifiers, Type superClass, Type... anInterface) {
180 this(typeName, modifiers, superClass == null
181 ? TypeDescription.Generic.UNDEFINED
182 : TypeDescription.Generic.Sort.describe(superClass), new TypeList.Generic.ForLoadedTypes(anInterface));
183 }
184
185 /**
186 * Creates a new java type representation.
187 *
188 * @param typeName The binary name of this type.
189 * @param modifiers The modifiers of this type when creating a stub.
190 * @param superClass The super class of this type when creating a stub.
191 * @param anInterface The interfaces of this type when creating a stub.
192 */
193 JavaType(String typeName, int modifiers, TypeDefinition superClass, TypeDefinition... anInterface) {
194 this(typeName, modifiers, superClass == null
195 ? TypeDescription.Generic.UNDEFINED
196 : superClass.asGenericType(), new TypeList.Generic.Explicit(anInterface));
197 }
198
199 /**
200 * Creates a new java type representation.
201 *
202 * @param typeName The binary name of this type.
203 * @param modifiers The modifiers of this type when creating a stub.
204 * @param superClass The super class of this type when creating a stub.
205 * @param interfaces The interfaces of this type when creating a stub.
206 */
207 JavaType(String typeName, int modifiers, TypeDescription.Generic superClass, TypeList.Generic interfaces) {
208 typeDescription = new TypeDescription.Latent(typeName, modifiers, superClass, interfaces);
209 }
210
211 /**
212 * Returns at least a stub representing this type where the stub does not define any methods or fields. If a type exists for
213 * the current runtime, a loaded type representation is returned.
214 *
215 * @return A type description for this Java type.
216 */
217 public TypeDescription getTypeStub() {
218 return typeDescription;
219 }
220
221 /**
222 * Loads the class that is represented by this Java type.
223 *
224 * @return A loaded type of this Java type.
225 * @throws ClassNotFoundException If the represented type cannot be loaded.
226 */
227 @CachedReturnPlugin.Enhance
228 public Class<?> load() throws ClassNotFoundException {
229 return Class.forName(typeDescription.getName(), false, ClassLoadingStrategy.BOOTSTRAP_LOADER);
230 }
231
232 /**
233 * Loads the class that is represented by this Java type and represents it as a {@link TypeDescription}.
234 *
235 * @return A loaded type of this Java type.
236 * @throws ClassNotFoundException If the represented type cannot be loaded.
237 */
238 public TypeDescription loadAsDescription() throws ClassNotFoundException {
239 return TypeDescription.ForLoadedType.of(load());
240 }
241
242 /**
243 * Returns {@code true} if this type is available on the current JVM.
244 *
245 * @return {@code true} if this type is available on the current JVM.
246 */
247 @CachedReturnPlugin.Enhance
248 public boolean isAvailable() {
249 try {
250 load();
251 return true;
252 } catch (ClassNotFoundException ignored) {
253 return false;
254 }
255 }
256
257 /**
258 * Checks if the supplied object is an instance of this type.
259 *
260 * @param instance The instance to check.
261 * @return {@code true} if the supplied object is an instance of this type.
262 */
263 public boolean isInstance(Object instance) {
264 if (!isAvailable()) {
265 return false;
266 }
267 try {
268 return load().isInstance(instance);
269 } catch (ClassNotFoundException ignored) {
270 return false;
271 }
272 }
273 }
274