< prev index next >

src/java.base/share/classes/java/lang/invoke/VarHandles.java

Print this page

 42 
 43 import static java.lang.invoke.MethodHandleStatics.UNSAFE;
 44 import static java.lang.invoke.MethodHandleStatics.VAR_HANDLE_SEGMENT_FORCE_EXACT;
 45 import static java.lang.invoke.MethodHandleStatics.VAR_HANDLE_IDENTITY_ADAPT;
 46 import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException;
 47 
 48 final class VarHandles {
 49 
 50     static ClassValue<ConcurrentMap<Integer, MethodHandle>> ADDRESS_FACTORIES = new ClassValue<>() {
 51         @Override
 52         protected ConcurrentMap<Integer, MethodHandle> computeValue(Class<?> type) {
 53             return new ConcurrentHashMap<>();
 54         }
 55     };
 56 
 57     static VarHandle makeFieldHandle(MemberName f, Class<?> refc, boolean isWriteAllowedOnFinalFields) {
 58         if (!f.isStatic()) {
 59             long foffset = MethodHandleNatives.objectFieldOffset(f);
 60             Class<?> type = f.getFieldType();
 61             if (!type.isPrimitive()) {
 62                 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
 63                        ? new VarHandleReferences.FieldInstanceReadOnly(refc, foffset, type)
 64                        : new VarHandleReferences.FieldInstanceReadWrite(refc, foffset, type));






 65             }
 66             else if (type == boolean.class) {
 67                 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
 68                        ? new VarHandleBooleans.FieldInstanceReadOnly(refc, foffset)
 69                        : new VarHandleBooleans.FieldInstanceReadWrite(refc, foffset));
 70             }
 71             else if (type == byte.class) {
 72                 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
 73                        ? new VarHandleBytes.FieldInstanceReadOnly(refc, foffset)
 74                        : new VarHandleBytes.FieldInstanceReadWrite(refc, foffset));
 75             }
 76             else if (type == short.class) {
 77                 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
 78                        ? new VarHandleShorts.FieldInstanceReadOnly(refc, foffset)
 79                        : new VarHandleShorts.FieldInstanceReadWrite(refc, foffset));
 80             }
 81             else if (type == char.class) {
 82                 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
 83                        ? new VarHandleChars.FieldInstanceReadOnly(refc, foffset)
 84                        : new VarHandleChars.FieldInstanceReadWrite(refc, foffset));

104                        : new VarHandleDoubles.FieldInstanceReadWrite(refc, foffset));
105             }
106             else {
107                 throw new UnsupportedOperationException();
108             }
109         }
110         else {
111             Class<?> decl = f.getDeclaringClass();
112             var vh = makeStaticFieldVarHandle(decl, f, isWriteAllowedOnFinalFields);
113             return maybeAdapt(UNSAFE.shouldBeInitialized(decl)
114                     ? new LazyInitializingVarHandle(vh, decl)
115                     : vh);
116         }
117     }
118 
119     static VarHandle makeStaticFieldVarHandle(Class<?> decl, MemberName f, boolean isWriteAllowedOnFinalFields) {
120         Object base = MethodHandleNatives.staticFieldBase(f);
121         long foffset = MethodHandleNatives.staticFieldOffset(f);
122         Class<?> type = f.getFieldType();
123         if (!type.isPrimitive()) {
124             return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
125                     ? new VarHandleReferences.FieldStaticReadOnly(decl, base, foffset, type)
126                     : new VarHandleReferences.FieldStaticReadWrite(decl, base, foffset, type));






127         }
128         else if (type == boolean.class) {
129             return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
130                     ? new VarHandleBooleans.FieldStaticReadOnly(decl, base, foffset)
131                     : new VarHandleBooleans.FieldStaticReadWrite(decl, base, foffset));
132         }
133         else if (type == byte.class) {
134             return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
135                     ? new VarHandleBytes.FieldStaticReadOnly(decl, base, foffset)
136                     : new VarHandleBytes.FieldStaticReadWrite(decl, base, foffset));
137         }
138         else if (type == short.class) {
139             return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
140                     ? new VarHandleShorts.FieldStaticReadOnly(decl, base, foffset)
141                     : new VarHandleShorts.FieldStaticReadWrite(decl, base, foffset));
142         }
143         else if (type == char.class) {
144             return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
145                     ? new VarHandleChars.FieldStaticReadOnly(decl, base, foffset)
146                     : new VarHandleChars.FieldStaticReadWrite(decl, base, foffset));

194 
195             if (offset == UNSAFE.staticFieldOffset(f)) {
196                 assert f.getType() == fieldType;
197                 return f;
198             }
199         }
200         throw new InternalError("Static field not found at offset");
201     }
202 
203     static VarHandle makeArrayElementHandle(Class<?> arrayClass) {
204         if (!arrayClass.isArray())
205             throw new IllegalArgumentException("not an array: " + arrayClass);
206 
207         Class<?> componentType = arrayClass.getComponentType();
208 
209         int aoffset = UNSAFE.arrayBaseOffset(arrayClass);
210         int ascale = UNSAFE.arrayIndexScale(arrayClass);
211         int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
212 
213         if (!componentType.isPrimitive()) {
214             return maybeAdapt(new VarHandleReferences.Array(aoffset, ashift, arrayClass));


215         }
216         else if (componentType == boolean.class) {
217             return maybeAdapt(new VarHandleBooleans.Array(aoffset, ashift));
218         }
219         else if (componentType == byte.class) {
220             return maybeAdapt(new VarHandleBytes.Array(aoffset, ashift));
221         }
222         else if (componentType == short.class) {
223             return maybeAdapt(new VarHandleShorts.Array(aoffset, ashift));
224         }
225         else if (componentType == char.class) {
226             return maybeAdapt(new VarHandleChars.Array(aoffset, ashift));
227         }
228         else if (componentType == int.class) {
229             return maybeAdapt(new VarHandleInts.Array(aoffset, ashift));
230         }
231         else if (componentType == long.class) {
232             return maybeAdapt(new VarHandleLongs.Array(aoffset, ashift));
233         }
234         else if (componentType == float.class) {

613 
614     static void handleCheckedExceptions(Throwable throwable) throws Throwable {
615         if (isCheckedException(throwable.getClass())) {
616             throw new IllegalStateException("Adapter handle threw checked exception", throwable);
617         }
618         throw throwable;
619     }
620 
621     static Class<?>[] exceptionTypes(MethodHandle handle) {
622         if (handle instanceof DirectMethodHandle directHandle) {
623             byte refKind = directHandle.member.getReferenceKind();
624             MethodHandleInfo info = new InfoFromMemberName(
625                     MethodHandles.Lookup.IMPL_LOOKUP,
626                     directHandle.member,
627                     refKind);
628             if (MethodHandleNatives.refKindIsMethod(refKind)) {
629                 return info.reflectAs(Method.class, MethodHandles.Lookup.IMPL_LOOKUP)
630                         .getExceptionTypes();
631             } else if (MethodHandleNatives.refKindIsField(refKind)) {
632                 return new Class<?>[0];
633             } else if (MethodHandleNatives.refKindIsConstructor(refKind)) {
634                 return info.reflectAs(Constructor.class, MethodHandles.Lookup.IMPL_LOOKUP)
635                         .getExceptionTypes();
636             } else {
637                 throw new AssertionError("Cannot get here");
638             }
639         } else if (handle instanceof DelegatingMethodHandle delegatingMh) {
640             return exceptionTypes(delegatingMh.getTarget());
641         } else if (handle instanceof NativeMethodHandle) {
642             return new Class<?>[0];
643         }
644 
645         assert handle instanceof BoundMethodHandle : "Unexpected handle type: " + handle;
646         // unknown
647         return null;
648     }
649 
650     private static boolean isCheckedException(Class<?> clazz) {
651         return Throwable.class.isAssignableFrom(clazz) &&
652                 !RuntimeException.class.isAssignableFrom(clazz) &&
653                 !Error.class.isAssignableFrom(clazz);

 42 
 43 import static java.lang.invoke.MethodHandleStatics.UNSAFE;
 44 import static java.lang.invoke.MethodHandleStatics.VAR_HANDLE_SEGMENT_FORCE_EXACT;
 45 import static java.lang.invoke.MethodHandleStatics.VAR_HANDLE_IDENTITY_ADAPT;
 46 import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException;
 47 
 48 final class VarHandles {
 49 
 50     static ClassValue<ConcurrentMap<Integer, MethodHandle>> ADDRESS_FACTORIES = new ClassValue<>() {
 51         @Override
 52         protected ConcurrentMap<Integer, MethodHandle> computeValue(Class<?> type) {
 53             return new ConcurrentHashMap<>();
 54         }
 55     };
 56 
 57     static VarHandle makeFieldHandle(MemberName f, Class<?> refc, boolean isWriteAllowedOnFinalFields) {
 58         if (!f.isStatic()) {
 59             long foffset = MethodHandleNatives.objectFieldOffset(f);
 60             Class<?> type = f.getFieldType();
 61             if (!type.isPrimitive()) {
 62                 if (f.isFlat()) {
 63                     return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
 64                         ? new VarHandleValues.FieldInstanceReadOnly(refc, foffset, type, f.isNullRestricted())
 65                         : new VarHandleValues.FieldInstanceReadWrite(refc, foffset, type, f.isNullRestricted()));
 66                 } else {
 67                     return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
 68                        ? new VarHandleReferences.FieldInstanceReadOnly(refc, foffset, type, f.isNullRestricted())
 69                        : new VarHandleReferences.FieldInstanceReadWrite(refc, foffset, type, f.isNullRestricted()));
 70                 }
 71             }
 72             else if (type == boolean.class) {
 73                 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
 74                        ? new VarHandleBooleans.FieldInstanceReadOnly(refc, foffset)
 75                        : new VarHandleBooleans.FieldInstanceReadWrite(refc, foffset));
 76             }
 77             else if (type == byte.class) {
 78                 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
 79                        ? new VarHandleBytes.FieldInstanceReadOnly(refc, foffset)
 80                        : new VarHandleBytes.FieldInstanceReadWrite(refc, foffset));
 81             }
 82             else if (type == short.class) {
 83                 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
 84                        ? new VarHandleShorts.FieldInstanceReadOnly(refc, foffset)
 85                        : new VarHandleShorts.FieldInstanceReadWrite(refc, foffset));
 86             }
 87             else if (type == char.class) {
 88                 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
 89                        ? new VarHandleChars.FieldInstanceReadOnly(refc, foffset)
 90                        : new VarHandleChars.FieldInstanceReadWrite(refc, foffset));

110                        : new VarHandleDoubles.FieldInstanceReadWrite(refc, foffset));
111             }
112             else {
113                 throw new UnsupportedOperationException();
114             }
115         }
116         else {
117             Class<?> decl = f.getDeclaringClass();
118             var vh = makeStaticFieldVarHandle(decl, f, isWriteAllowedOnFinalFields);
119             return maybeAdapt(UNSAFE.shouldBeInitialized(decl)
120                     ? new LazyInitializingVarHandle(vh, decl)
121                     : vh);
122         }
123     }
124 
125     static VarHandle makeStaticFieldVarHandle(Class<?> decl, MemberName f, boolean isWriteAllowedOnFinalFields) {
126         Object base = MethodHandleNatives.staticFieldBase(f);
127         long foffset = MethodHandleNatives.staticFieldOffset(f);
128         Class<?> type = f.getFieldType();
129         if (!type.isPrimitive()) {
130             if (f.isFlat()) {
131                 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
132                         ? new VarHandleValues.FieldStaticReadOnly(decl, base, foffset, type, f.isNullRestricted())
133                         : new VarHandleValues.FieldStaticReadWrite(decl, base, foffset, type, f.isNullRestricted()));
134             } else {
135                 return f.isFinal() && !isWriteAllowedOnFinalFields
136                         ? new VarHandleReferences.FieldStaticReadOnly(decl, base, foffset, type, f.isNullRestricted())
137                         : new VarHandleReferences.FieldStaticReadWrite(decl, base, foffset, type, f.isNullRestricted());
138             }
139         }
140         else if (type == boolean.class) {
141             return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
142                     ? new VarHandleBooleans.FieldStaticReadOnly(decl, base, foffset)
143                     : new VarHandleBooleans.FieldStaticReadWrite(decl, base, foffset));
144         }
145         else if (type == byte.class) {
146             return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
147                     ? new VarHandleBytes.FieldStaticReadOnly(decl, base, foffset)
148                     : new VarHandleBytes.FieldStaticReadWrite(decl, base, foffset));
149         }
150         else if (type == short.class) {
151             return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
152                     ? new VarHandleShorts.FieldStaticReadOnly(decl, base, foffset)
153                     : new VarHandleShorts.FieldStaticReadWrite(decl, base, foffset));
154         }
155         else if (type == char.class) {
156             return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
157                     ? new VarHandleChars.FieldStaticReadOnly(decl, base, foffset)
158                     : new VarHandleChars.FieldStaticReadWrite(decl, base, foffset));

206 
207             if (offset == UNSAFE.staticFieldOffset(f)) {
208                 assert f.getType() == fieldType;
209                 return f;
210             }
211         }
212         throw new InternalError("Static field not found at offset");
213     }
214 
215     static VarHandle makeArrayElementHandle(Class<?> arrayClass) {
216         if (!arrayClass.isArray())
217             throw new IllegalArgumentException("not an array: " + arrayClass);
218 
219         Class<?> componentType = arrayClass.getComponentType();
220 
221         int aoffset = UNSAFE.arrayBaseOffset(arrayClass);
222         int ascale = UNSAFE.arrayIndexScale(arrayClass);
223         int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
224 
225         if (!componentType.isPrimitive()) {
226             return maybeAdapt(UNSAFE.isFlattenedArray(arrayClass)
227                 ? new VarHandleValues.Array(aoffset, ashift, arrayClass)
228                 : new VarHandleReferences.Array(aoffset, ashift, arrayClass));
229         }
230         else if (componentType == boolean.class) {
231             return maybeAdapt(new VarHandleBooleans.Array(aoffset, ashift));
232         }
233         else if (componentType == byte.class) {
234             return maybeAdapt(new VarHandleBytes.Array(aoffset, ashift));
235         }
236         else if (componentType == short.class) {
237             return maybeAdapt(new VarHandleShorts.Array(aoffset, ashift));
238         }
239         else if (componentType == char.class) {
240             return maybeAdapt(new VarHandleChars.Array(aoffset, ashift));
241         }
242         else if (componentType == int.class) {
243             return maybeAdapt(new VarHandleInts.Array(aoffset, ashift));
244         }
245         else if (componentType == long.class) {
246             return maybeAdapt(new VarHandleLongs.Array(aoffset, ashift));
247         }
248         else if (componentType == float.class) {

627 
628     static void handleCheckedExceptions(Throwable throwable) throws Throwable {
629         if (isCheckedException(throwable.getClass())) {
630             throw new IllegalStateException("Adapter handle threw checked exception", throwable);
631         }
632         throw throwable;
633     }
634 
635     static Class<?>[] exceptionTypes(MethodHandle handle) {
636         if (handle instanceof DirectMethodHandle directHandle) {
637             byte refKind = directHandle.member.getReferenceKind();
638             MethodHandleInfo info = new InfoFromMemberName(
639                     MethodHandles.Lookup.IMPL_LOOKUP,
640                     directHandle.member,
641                     refKind);
642             if (MethodHandleNatives.refKindIsMethod(refKind)) {
643                 return info.reflectAs(Method.class, MethodHandles.Lookup.IMPL_LOOKUP)
644                         .getExceptionTypes();
645             } else if (MethodHandleNatives.refKindIsField(refKind)) {
646                 return new Class<?>[0];
647             } else if (MethodHandleNatives.refKindIsObjectConstructor(refKind)) {
648                 return info.reflectAs(Constructor.class, MethodHandles.Lookup.IMPL_LOOKUP)
649                         .getExceptionTypes();
650             } else {
651                 throw new AssertionError("Cannot get here");
652             }
653         } else if (handle instanceof DelegatingMethodHandle delegatingMh) {
654             return exceptionTypes(delegatingMh.getTarget());
655         } else if (handle instanceof NativeMethodHandle) {
656             return new Class<?>[0];
657         }
658 
659         assert handle instanceof BoundMethodHandle : "Unexpected handle type: " + handle;
660         // unknown
661         return null;
662     }
663 
664     private static boolean isCheckedException(Class<?> clazz) {
665         return Throwable.class.isAssignableFrom(clazz) &&
666                 !RuntimeException.class.isAssignableFrom(clazz) &&
667                 !Error.class.isAssignableFrom(clazz);
< prev index next >