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 ClassValue to cache information needed to
perform the message send quickly, for each class encountered.
The basic operation of a ClassValue is get, which
returns the associated value, initially created by an invocation to computeValue; multiple invocations may happen under race, but
exactly one value is associated to a Class and returned.
Another operation is 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:
getcomputeValue by
getremoveget call always include at least one access; a remove call
always has exactly one access; a computeValue call always happens
between two accesses. This establishes the order of computeValue
calls with respect to remove calls and determines whether the
results of a computeValue can be successfully associated by a get.
| Modifier and Type | Class and Description |
|---|---|
| pack-priv static class | ClassValue.
A backing map for all ClassValues. |
| pack-priv static class | |
| pack-priv static class | ClassValue.
Private key for retrieval of this object from ClassValueMap. |
| private static class | ClassValue.
Besides a value (represented by an Entry), a "removal token" object,
including the value |
| pack-priv static record |
| Modifier and Type | Field and Description |
|---|---|
| private static final Object | |
| private static final ClassValue. | EMPTY_CACHE
Initial, one-element, empty cache used by all Class instances. |
| private static final int | HASH_INCREMENT
Good for power-of-two tables. |
| pack-priv static final int | HASH_MASK
Mask a hash code to be positive but not too large, to prevent wraparound. |
| pack-priv final int | hashCodeForCache
Internal hash code for accessing Class.classValueMap.cacheArray. |
| pack-priv final ClassValue. | identity
This ClassValue's identity, expressed as an opaque object. |
| private static final AtomicInteger | nextHashCode
Value stream for hashCodeForCache. |
| private static final Unsafe | |
| private volatile ClassValue. | version
Current version for retrieving this class value from the cache. |
| Access | Constructor and Description |
|---|---|
| protected |
| Modifier and Type | Method and Description |
|---|---|
| pack-priv void | |
| pack-priv ClassValue. | |
| protected abstract T | Returns: the newly computed value to associatethe type)Class to associate a value toComputes the value to associate to the given |
| public T | |
| private static ClassValue. | |
| private T | getFromBackup(ClassValue.
Slow tail of ClassValue.get to retry at nearby locations in the cache, or take a slow lock and check the hash table. |
| private T | |
| private static ClassValue. | |
| private static ClassValue. | |
| pack-priv static <T> ClassValue. | |
| pack-priv boolean | |
| pack-priv void | |
| public void |
| CRITICAL_SECTION | back to summary |
|---|---|
| private static final Object CRITICAL_SECTION | |
| EMPTY_CACHE | back to summary |
|---|---|
| private static final ClassValue. Initial, one-element, empty cache used by all Class instances. Must never be filled. | |
| HASH_INCREMENT | back to summary |
|---|---|
| private static final int HASH_INCREMENT Good for power-of-two tables. See similar structure in ThreadLocal. | |
| HASH_MASK | back to summary |
|---|---|
| pack-priv static final int HASH_MASK Mask a hash code to be positive but not too large, to prevent wraparound. | |
| hashCodeForCache | back to summary |
|---|---|
| pack-priv final int hashCodeForCache Internal hash code for accessing Class.classValueMap.cacheArray. | |
| identity | back to summary |
|---|---|
| pack-priv final ClassValue. This ClassValue's identity, expressed as an opaque object.
The main object | |
| nextHashCode | back to summary |
|---|---|
| private static final AtomicInteger nextHashCode Value stream for hashCodeForCache. See similar structure in ThreadLocal. | |
| UNSAFE | back to summary |
|---|---|
| private static final Unsafe UNSAFE | |
| version | back to summary |
|---|---|
| private volatile ClassValue. Current version for retrieving this class value from the cache. Any number of computeValue calls can be cached in association with one version. But the version changes when a remove (on any type) is executed. A version change invalidates all cache entries for the affected ClassValue, by marking them as stale. Stale cache entries do not force another call to computeValue, but they do require a synchronized visit to a backing map. 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. | |
| ClassValue | back to summary |
|---|---|
| protected ClassValue() Sole constructor. (For invocation by subclass constructors, typically implicit.) | |
| bumpVersion | back to summary |
|---|---|
| pack-priv void bumpVersion() | |
| castEntry | back to summary |
|---|---|
pack-priv ClassValue.
| |
| computeValue | back to summary |
|---|---|
| protected abstract T computeValue(Class<?> type) Computes the value to associate to the given
This method is invoked when the initial read-only access by
If this method throws an exception, the initiating Otherwise, the value is computed and returned. An attempt to associate the return value happens, with one of the following outcomes:
API Note A | |
| get | back to summary |
|---|---|
| public T get(Class<?> type) Returns the value associated to the given
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
This method may throw an exception from a
| |
| getCacheCarefully | back to summary |
|---|---|
| private static ClassValue. Return the cache, if it exists, else a dummy empty cache. | |
| getFromBackup | back to summary |
|---|---|
| private T getFromBackup(ClassValue. Slow tail of ClassValue.get to retry at nearby locations in the cache, or take a slow lock and check the hash table. Called only if the first probe was empty or a collision. This is a separate method, so compilers can process it independently. | |
| getFromHashMap | back to summary |
|---|---|
| private T getFromHashMap(Class<?> type) Called when the fast path of get fails, and cache reprobe also fails. | |
| getMap | back to summary |
|---|---|
| private static ClassValue. Return the backing map associated with this type. | |
| initializeMap | back to summary |
|---|---|
| private static ClassValue. | |
| makeEntry | back to summary |
|---|---|
| pack-priv static <T> ClassValue. | |
| match | back to summary |
|---|---|
| pack-priv boolean match(ClassValue. Check that e is non-null, matches this ClassValue, and is live. | |
| put | back to summary |
|---|---|
| pack-priv void put(Class<?> type, T value) | |
| remove | back to summary |
|---|---|
| public void remove(Class<?> type) Removes the associated value for the given
| |
| Modifier and Type | Field and Description |
|---|---|
| private static final int | CACHE_LOAD_LIMIT
Percent loading of cache before resize. |
| private ClassValue. | |
| private int | |
| private int | |
| private static final int | INITIAL_ENTRIES
Number of entries initially allocated to each type when first used with any ClassValue. |
| private static final int | PROBE_LIMIT
Maximum number of probes to attempt. |
| Access | Constructor and Description |
|---|---|
| pack-priv |
| Modifier and Type | Method and Description |
|---|---|
| private <T> void | addToCache(ClassValue.
Add the given entry to the cache, in its home location, unless it is out of date. |
| private <T> void | addToCache(ClassValue<T> classValue, ClassValue.
Add the given entry to the cache, in its home location. |
| pack-priv synchronized <T> Object | |
| private void | |
| private static int | entryDislocation(ClassValue.
How far out of place is e? |
| private ClassValue. | findReplacement(ClassValue.
Clearing a cache slot risks disconnecting following entries from the head of a non-null run, which would allow them to be found via reprobes. |
| pack-priv synchronized <T> void | |
| pack-priv ClassValue. | |
| pack-priv static ClassValue. | loadFromCache(ClassValue.
Load the cache entry at the given (hashed) location. |
| private <T> ClassValue. | |
| private ClassValue. | placeInCache(ClassValue.
Store the given entry. |
| pack-priv static <T> ClassValue. | probeBackupLocations(ClassValue.
Given that first probe was a collision, retry at nearby locations. |
| pack-priv static <T> ClassValue. | probeHomeLocation(ClassValue.
Look in the cache, at the home location for the given ClassValue. |
| pack-priv synchronized <T> Object | |
| private void | |
| pack-priv synchronized void | |
| private void | removeStaleEntries(ClassValue.
Remove stale entries in the given range. |
| private void | |
| private void | |
| private void | sizeCache(int length)
<hr> Below this line all functions are private, and assume synchronized access. |
| CACHE_LOAD_LIMIT | back to summary |
|---|---|
| private static final int CACHE_LOAD_LIMIT Percent loading of cache before resize. | |
| cacheArray | back to summary |
|---|---|
| private ClassValue. | |
| cacheLoad | back to summary |
|---|---|
| private int cacheLoad | |
| cacheLoadLimit | back to summary |
|---|---|
| private int cacheLoadLimit | |
| INITIAL_ENTRIES | back to summary |
|---|---|
| private static final int INITIAL_ENTRIES Number of entries initially allocated to each type when first used with any ClassValue. It would be pointless to make this much smaller than the Class and ClassValueMap objects themselves. Must be a power of 2. | |
| PROBE_LIMIT | back to summary |
|---|---|
| private static final int PROBE_LIMIT Maximum number of probes to attempt. | |
| ClassValueMap | back to summary |
|---|---|
| pack-priv ClassValueMap() Build a backing map for ClassValues. Also, create an empty cache array and install it on the class. | |
| addToCache | back to summary |
|---|---|
| private <T> void addToCache(ClassValue. Add the given entry to the cache, in its home location, unless it is out of date. | |
| addToCache | back to summary |
|---|---|
| private <T> void addToCache(ClassValue<T> classValue, ClassValue. Add the given entry to the cache, in its home location. | |
| associateAccess | back to summary |
|---|---|
| pack-priv synchronized <T> Object associateAccess(ClassValue<T> classValue, ClassValue. | |
| checkCacheLoad | back to summary |
|---|---|
| private void checkCacheLoad() Make sure the cache load stays below its limit, if possible. | |
| entryDislocation | back to summary |
|---|---|
| private static int entryDislocation(ClassValue. How far out of place is e? | |
| findReplacement | back to summary |
|---|---|
| private ClassValue. Clearing a cache slot risks disconnecting following entries from the head of a non-null run, which would allow them to be found via reprobes. Find an entry after cache[begin] to plug into the hole, or return null if none is needed. | |
| forcedAssociateAccess | back to summary |
|---|---|
| pack-priv synchronized <T> void forcedAssociateAccess(ClassValue<T> classValue, T value) | |
| getCache | back to summary |
|---|---|
| pack-priv ClassValue. | |
| loadFromCache | back to summary |
|---|---|
| pack-priv static ClassValue. Load the cache entry at the given (hashed) location. | |
| overwrittenEntry | back to summary |
|---|---|
| private <T> ClassValue. Note an entry that is about to be overwritten. If it is not live, quietly replace it by null. If it is an actual null, increment cacheLoad, because the caller is going to store something in its place. | |
| placeInCache | back to summary |
|---|---|
| private ClassValue. Store the given entry. Update cacheLoad, and return any live victim. 'Gently' means return self rather than dislocating a live victim. | |
| probeBackupLocations | back to summary |
|---|---|
| pack-priv static <T> ClassValue. Given that first probe was a collision, retry at nearby locations. | |
| probeHomeLocation | back to summary |
|---|---|
| pack-priv static <T> ClassValue. Look in the cache, at the home location for the given ClassValue. | |
| readAccess | back to summary |
|---|---|
| pack-priv synchronized <T> Object readAccess(ClassValue<T> classValue) | |
| reduceCacheLoad | back to summary |
|---|---|
| private void reduceCacheLoad() | |
| removeAccess | back to summary |
|---|---|
| pack-priv synchronized void removeAccess(ClassValue<?> classValue) | |
| removeStaleEntries | back to summary |
|---|---|
| private void removeStaleEntries(ClassValue. Remove stale entries in the given range. Should be executed under a Map lock. | |
| removeStaleEntries | back to summary |
|---|---|
| private void removeStaleEntries(ClassValue<?> classValue) Remove stale entries in the range near classValue. | |
| removeStaleEntries | back to summary |
|---|---|
| private void removeStaleEntries() Remove all stale entries, everywhere. | |
| sizeCache | back to summary |
|---|---|
private void sizeCache(int length)Below this line all functions are private, and assume synchronized access. | |
| Modifier and Type | Field and Description |
|---|---|
| pack-priv static final ClassValue. | |
| pack-priv final T | |
| pack-priv final WeakReference |
| Access | Constructor and Description |
|---|---|
| pack-priv |
| Modifier and Type | Method and Description |
|---|---|
| pack-priv ClassValue | |
| pack-priv boolean | |
| pack-priv ClassValue. | |
| pack-priv ClassValue. |
| DEAD_ENTRY | back to summary |
|---|---|
| pack-priv static final ClassValue. | |
| value | back to summary |
|---|---|
| pack-priv final T value | |
| version | back to summary |
|---|---|
| pack-priv final WeakReference<ClassValue. | |
| Entry | back to summary |
|---|---|
| pack-priv Entry(ClassValue. | |
| classValueOrNull | back to summary |
|---|---|
| pack-priv ClassValue | |
| isLive | back to summary |
|---|---|
| pack-priv boolean isLive() | |
| refreshVersion | back to summary |
|---|---|
| pack-priv ClassValue. | |
| version | back to summary |
|---|---|
| pack-priv ClassValue. | |
| Access | Constructor and Description |
|---|---|
| pack-priv |
| Identity | back to summary |
|---|---|
| pack-priv Identity() | |
null, can be present at a ClassValue-Class
coordinate. A removal token indicates whether the value from a
computation is up-to-date; the value is up-to-date if the token is the
same before and after computation (no removal during this period), or if
the token is from the same thread (removed during computeValue).
null is the initial state, meaning all computations are valid.
Later tokens are always non-null, no matter if they replace existing
entries or outdated tokens.
| Modifier and Type | Field and Description |
|---|---|
| private final long |
| Access | Constructor and Description |
|---|---|
| private |
| Modifier and Type | Method and Description |
|---|---|
| private static boolean |
| actorId | back to summary |
|---|---|
| private final long actorId | |
| RemovalToken | back to summary |
|---|---|
| private RemovalToken() | |
| allowsAssociation | back to summary |
|---|---|
| private static boolean allowsAssociation(ClassValue. | |
| Modifier and Type | Field and Description |
|---|---|
| private final ClassValue | classValue
Record Component accessed by classValue(). |
| Access | Constructor and Description |
|---|---|
| pack-priv |
| Modifier and Type | Method and Description |
|---|---|
| public ClassValue | |
| public final boolean | equals(Object o)
Implements abstract java. Indicates whether some other object is "equal to" this one. |
| public final int | |
| pack-priv boolean | |
| public final String | toString()
Implements abstract java. Returns a string representation of the record. |
| classValue | back to summary |
|---|---|
| private final ClassValue<T> classValue Record Component accessed by classValue(). | |
| Version | back to summary |
|---|---|
| pack-priv Version(ClassValue<T> classValue) | |
| classValue | back to summary |
|---|---|
| public ClassValue Record Component getter of classValue. | |
| equals | back to summary |
|---|---|
| public final boolean equals(Object o) Implements abstract java. Doc from java. Indicates whether some other object is "equal to" this one. In addition
to the general contract of
R copy = new R(r.c1(), r.c2(), ..., r.cn());
then it must be the case that r.equals(copy).
| |
| hashCode | back to summary |
|---|---|
| public final int hashCode() Implements abstract java. Doc from java. Returns a hash code value for the record.
Obeys the general contract of | |
| isLive | back to summary |
|---|---|
| pack-priv boolean isLive() | |
| toString | back to summary |
|---|---|
| public final String toString() Implements abstract java. Doc from java. Returns a string representation of the record.
In accordance with the general contract of In addition to this general contract, record classes must further participate in the invariant that any two records which are equal must produce equal strings. This invariant is necessarily relaxed in the rare case where corresponding equal component values might fail to produce equal strings for themselves. | |