Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/jcl/src/java.base/share/classes/java/lang/invoke/FieldVarHandle.java
12521 views
1
/*[INCLUDE-IF Sidecar19-SE & !OPENJDK_METHODHANDLES]*/
2
/*******************************************************************************
3
* Copyright (c) 2016, 2021 IBM Corp. and others
4
*
5
* This program and the accompanying materials are made available under
6
* the terms of the Eclipse Public License 2.0 which accompanies this
7
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
8
* or the Apache License, Version 2.0 which accompanies this distribution and
9
* is available at https://www.apache.org/licenses/LICENSE-2.0.
10
*
11
* This Source Code may also be made available under the following
12
* Secondary Licenses when the conditions for such availability set
13
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
14
* General Public License, version 2 with the GNU Classpath
15
* Exception [1] and GNU General Public License, version 2 with the
16
* OpenJDK Assembly Exception [2].
17
*
18
* [1] https://www.gnu.org/software/classpath/license.html
19
* [2] http://openjdk.java.net/legal/assembly-exception.html
20
*
21
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
22
*******************************************************************************/
23
package java.lang.invoke;
24
25
/*[IF JAVA_SPEC_VERSION >= 12]*/
26
import java.lang.constant.ClassDesc;
27
import java.util.Optional;
28
/*[ENDIF] JAVA_SPEC_VERSION >= 12 */
29
import java.lang.reflect.Field;
30
import java.lang.reflect.Modifier;
31
import static java.lang.invoke.MethodType.*;
32
import java.lang.invoke.MethodHandles.Lookup;
33
34
import com.ibm.oti.vm.VM;
35
36
abstract class FieldVarHandle extends VarHandle {
37
final long vmslot;
38
final String fieldName;
39
40
/* definingClass cannot be a final field since it is modified twice, once in
41
* Java code and once in native code.
42
*/
43
Class<?> definingClass;
44
45
/**
46
* Constructs a VarHandle referencing a field.
47
*
48
* @param lookupClass The class where we start the lookup of the field
49
* @param fieldName The field name
50
* @param fieldType The exact type of the field
51
* @param accessClass The class being used to look up the field
52
* @param isStatic A boolean value indicating whether the field is static
53
* @param coordinateTypes An ordered array of the parameter classes required for invoking an AccessMode on the VarHandle.
54
* @param handleTable The array of MethodHandles implementing the AccessModes.
55
* @param typeTable The VarHandle instance specific MethodTypes used to validate invocations.
56
*/
57
FieldVarHandle(Class<?> lookupClass, String fieldName, Class<?> fieldType, Class<?> accessClass, boolean isStatic, Class<?>[] coordinateTypes, MethodHandle[] handleTable) {
58
super(fieldType, coordinateTypes, handleTable, 0);
59
this.definingClass = lookupClass;
60
this.fieldName = fieldName;
61
int header = (isStatic ? 0 : VM.OBJECT_HEADER_SIZE);
62
63
/* The native lookupField method also modifies the definingClass field. */
64
this.vmslot = lookupField(definingClass, fieldName, MethodTypeHelper.getBytecodeStringName(fieldType), fieldType, isStatic, accessClass) + header;
65
66
checkSetterFieldFinality(handleTable);
67
}
68
69
/**
70
* Constructs a VarHandle referencing the field represented by the {@link java.lang.reflect.Field}.
71
*
72
* @param field The {@link java.lang.reflect.Field} to create a VarHandle for.
73
* @param isStatic A boolean value indicating whether the field is static
74
* @param coordinateTypes An ordered array of the parameter classes required for invoking an AccessMode on the VarHandle.
75
* @param handleTable The array of MethodHandles implementing the AccessModes.
76
* @param typeTable The VarHandle instance specific MethodTypes used to validate invocations.
77
*/
78
FieldVarHandle(Field field, boolean isStatic, Class<?>[] coordinateTypes, MethodHandle[] handleTable) {
79
super(field.getType(), coordinateTypes, handleTable, 0);
80
this.definingClass = field.getDeclaringClass();
81
this.fieldName = field.getName();
82
int header = (isStatic ? 0 : VM.OBJECT_HEADER_SIZE);
83
this.vmslot = unreflectField(field, isStatic) + header;
84
checkSetterFieldFinality(handleTable);
85
}
86
87
/*[IF JAVA_SPEC_VERSION >= 12]*/
88
@Override
89
public Optional<VarHandleDesc> describeConstable() {
90
VarHandleDesc result = null;
91
Optional<ClassDesc> fieldTypeOp = fieldType.describeConstable();
92
Optional<ClassDesc> declaringClassOp = definingClass.describeConstable();
93
94
if (fieldTypeOp.isPresent() && declaringClassOp.isPresent()) {
95
if (this instanceof InstanceFieldVarHandle) {
96
result = VarHandleDesc.ofField(declaringClassOp.get(), fieldName, fieldTypeOp.get());
97
} else { /* static */
98
result = VarHandleDesc.ofStaticField(declaringClassOp.get(), fieldName, fieldTypeOp.get());
99
}
100
}
101
return Optional.ofNullable(result);
102
}
103
/*[ENDIF] JAVA_SPEC_VERSION >= 12 */
104
105
/**
106
* Checks whether the field referenced by this VarHandle, is final.
107
* If so, MethodHandles in the handleTable that represent access modes that may modify the field,
108
* are replaced by a MethodHandle that throws an exception when invoked.
109
*
110
* @param handleTable The array of MethodHandles implementing the AccessModes.
111
*/
112
void checkSetterFieldFinality(MethodHandle[] handleTable) {
113
if (Modifier.isFinal(modifiers)) {
114
MethodHandle exceptionThrower;
115
try {
116
exceptionThrower = MethodHandles.Lookup.IMPL_LOOKUP.findStatic(FieldVarHandle.class, "finalityCheckFailedExceptionThrower", methodType(void.class));
117
} catch (IllegalAccessException | NoSuchMethodException e) {
118
throw new InternalError(e);
119
}
120
for (AccessMode mode : AccessMode.values()) {
121
if (mode.isSetter) {
122
MethodHandle mh = handleTable[mode.ordinal()];
123
Class<?>[] args = mh.type().ptypes();
124
handleTable[mode.ordinal()] = MethodHandles.dropArguments(exceptionThrower, 0, args);
125
}
126
}
127
}
128
}
129
130
/**
131
* checkSetterFieldFinality replaces MethodHandles in the handleTable with this method
132
* to throw an exception when the field referenced by the VarHandle is final.
133
*/
134
private static void finalityCheckFailedExceptionThrower() {
135
/*[MSG "K0629", "Modification access modes are not allowed on final fields."]*/
136
throw new UnsupportedOperationException(com.ibm.oti.util.Msg.getString("K0629")); //$NON-NLS-1$
137
}
138
139
/**
140
* Looks up a field in a class (lookupClass) given a name and a signature.
141
*
142
* @param lookupClass The class where we start the lookup of the field
143
* @param name The field name
144
* @param signature Equivalent of the String returned by MethodTypeHelper.getBytecodeStringName
145
* @param type The exact type of the field. This must match the signature.
146
* @param isStatic A boolean value indicating whether the field is static.
147
* @param accessClass The class being used to look up the field.
148
* @return This is the value that should be assigned to the vmslot field.
149
* It represents the offset to access the field. In the error cases,
150
* this method returns -1 for instance fields, and 0 for static fields.
151
*
152
* This method may throw any of the following exceptions or others related to field resolution.
153
* @throws IllegalAccessError
154
* @throws IncompatibleClassChangeError
155
* @throws NoSuchFieldError
156
* @throws LinkageError
157
* @throws OutOfMemoryError
158
*/
159
native long lookupField(Class<?> lookupClass, String name, String signature, Class<?> type, boolean isStatic, Class<?> accessClass);
160
161
/**
162
* Gets the offset for a field given a {@link java.lang.reflect.Field}. This method also sets the modifiers.
163
*
164
* @param field The {@link java.lang.reflect.Field} to get the offset for.
165
* @param isStatic A boolean value indicating whether the field is static.
166
* @return
167
*/
168
native long unreflectField(Field field, boolean isStatic);
169
170
@Override
171
final Class<?> getDefiningClass() {
172
return definingClass;
173
}
174
175
@Override
176
final String getFieldName() {
177
return fieldName;
178
}
179
180
/*[IF JAVA_SPEC_VERSION >= 16]*/
181
public VarHandle withInvokeExactBehavior() {
182
throw OpenJDKCompileStub.OpenJDKCompileStubThrowError();
183
}
184
185
public VarHandle withInvokeBehavior() {
186
throw OpenJDKCompileStub.OpenJDKCompileStubThrowError();
187
}
188
/*[ENDIF] JAVA_SPEC_VERSION >= 16 */
189
}
190
191