/* * Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package java.lang; import java.util.WeakHashMap; import java.lang.ref.WeakReference; import java.util.concurrent.atomic.AtomicInteger; import jdk.internal.misc.Unsafe; import static java.lang.ClassValue.ClassValueMap.probeHomeLocation; import static java.lang.ClassValue.ClassValueMap.probeBackupLocations; /** * Lazily associate a computed value with any {@code Class} object. * For example, if a dynamic language needs to construct a message dispatch * table for each class encountered at a message send call site, * it can use a {@code ClassValue} to cache information needed to * perform the message send quickly, for each class encountered. *
* The basic operation of a {@code ClassValue} is {@link #get get}, which * returns the associated value, initially created by an invocation to {@link * #computeValue computeValue}; multiple invocations may happen under race, but * exactly one value is associated to a {@code Class} and returned. *
* Another operation is {@link #remove remove}: it clears the associated value * (if it exists), and ensures the next associated value is computed with input * states up-to-date with the removal. *
* For a particular association, there is a total order for accesses to the * associated value. Accesses are atomic; they include: *
* This method is invoked when the initial read-only access by {@link #get * get} finds no associated value. *
* If this method throws an exception, the initiating {@code get} call will * not attempt to associate a value, and may terminate by returning the * associated value if it exists, or by propagating that exception otherwise. *
* Otherwise, the value is computed and returned. An attempt to associate * the return value happens, with one of the following outcomes: *
* This method first performs a read-only access, and returns the associated * value if it exists. Otherwise, this method tries to associate a value * from a {@link #computeValue computeValue} invocation until the associated * value exists, which could be associated by a competing thread. *
* This method may throw an exception from a {@code computeValue} invocation.
* In this case, no association happens.
*
* @param type the {@code Class} to retrieve the associated value for
* @throws NullPointerException if the argument is {@code null}
* @see #remove
* @see #computeValue
*/
public T get(Class> type) {
// non-racing this.hashCodeForCache : final int
Entry>[] cache;
Entry
* All user-visible state changes on the ClassValue take place under
* a lock inside the synchronized methods of ClassValueMap.
* Readers (of ClassValue.get) are notified of such state changes
* when this.version is bumped to a new token.
* This variable must be volatile so that an unsynchronized reader
* will receive the notification without delay.
*
* If version were not volatile, one thread T1 could persistently hold onto
* a stale value this.value == V1, while another thread T2 advances
* (under a lock) to this.value == V2. This will typically be harmless,
* but if T1 and T2 interact causally via some other channel, such that
* T1's further actions are constrained (in the JMM) to happen after
* the V2 event, then T1's observation of V1 will be an error.
*
* The practical effect of making this.version be volatile is that it cannot
* be hoisted out of a loop (by an optimizing JIT) or otherwise cached.
* Some machines may also require a barrier instruction to execute
* before this.version.
*/
private volatile Version
*
* Once an entry goes stale, it can be reset at any time
* into the dead state.
*/
static final class Entry