jdk/src/java.base/share/classes/java/lang/reflect/WeakCache.java
author rriggs
Tue, 16 Feb 2016 11:36:20 -0500
changeset 35978 752d505da547
parent 25859 3317bb8137f4
permissions -rw-r--r--
8148775: Spec for j.l.ProcessBuilder.Redirect.DISCARD need to be improved Reviewed-by: martin
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
     1
/*
23061
c441853d95af 8036744: Fix raw lint warnings in java.lang.reflect.WeakCache
darcy
parents: 17188
diff changeset
     2
 * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
     4
 *
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    10
 *
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    15
 * accompanied this code).
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    16
 *
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    20
 *
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    23
 * questions.
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    24
 */
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    25
package java.lang.reflect;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    26
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    27
import java.lang.ref.ReferenceQueue;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    28
import java.lang.ref.WeakReference;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    29
import java.util.Objects;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    30
import java.util.concurrent.ConcurrentHashMap;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    31
import java.util.concurrent.ConcurrentMap;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    32
import java.util.function.BiFunction;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    33
import java.util.function.Supplier;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    34
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    35
/**
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    36
 * Cache mapping pairs of {@code (key, sub-key) -> value}. Keys and values are
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    37
 * weakly but sub-keys are strongly referenced.  Keys are passed directly to
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    38
 * {@link #get} method which also takes a {@code parameter}. Sub-keys are
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    39
 * calculated from keys and parameters using the {@code subKeyFactory} function
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    40
 * passed to the constructor. Values are calculated from keys and parameters
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    41
 * using the {@code valueFactory} function passed to the constructor.
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    42
 * Keys can be {@code null} and are compared by identity while sub-keys returned by
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    43
 * {@code subKeyFactory} or values returned by {@code valueFactory}
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    44
 * can not be null. Sub-keys are compared using their {@link #equals} method.
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    45
 * Entries are expunged from cache lazily on each invocation to {@link #get},
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    46
 * {@link #containsValue} or {@link #size} methods when the WeakReferences to
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    47
 * keys are cleared. Cleared WeakReferences to individual values don't cause
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    48
 * expunging, but such entries are logically treated as non-existent and
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    49
 * trigger re-evaluation of {@code valueFactory} on request for their
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    50
 * key/subKey.
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    51
 *
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    52
 * @author Peter Levart
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    53
 * @param <K> type of keys
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    54
 * @param <P> type of parameters
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    55
 * @param <V> type of values
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    56
 */
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    57
final class WeakCache<K, P, V> {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    58
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    59
    private final ReferenceQueue<K> refQueue
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    60
        = new ReferenceQueue<>();
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    61
    // the key type is Object for supporting null key
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    62
    private final ConcurrentMap<Object, ConcurrentMap<Object, Supplier<V>>> map
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    63
        = new ConcurrentHashMap<>();
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    64
    private final ConcurrentMap<Supplier<V>, Boolean> reverseMap
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    65
        = new ConcurrentHashMap<>();
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    66
    private final BiFunction<K, P, ?> subKeyFactory;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    67
    private final BiFunction<K, P, V> valueFactory;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    68
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    69
    /**
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    70
     * Construct an instance of {@code WeakCache}
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    71
     *
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    72
     * @param subKeyFactory a function mapping a pair of
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    73
     *                      {@code (key, parameter) -> sub-key}
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    74
     * @param valueFactory  a function mapping a pair of
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    75
     *                      {@code (key, parameter) -> value}
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    76
     * @throws NullPointerException if {@code subKeyFactory} or
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    77
     *                              {@code valueFactory} is null.
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    78
     */
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    79
    public WeakCache(BiFunction<K, P, ?> subKeyFactory,
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    80
                     BiFunction<K, P, V> valueFactory) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    81
        this.subKeyFactory = Objects.requireNonNull(subKeyFactory);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    82
        this.valueFactory = Objects.requireNonNull(valueFactory);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    83
    }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    84
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    85
    /**
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    86
     * Look-up the value through the cache. This always evaluates the
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    87
     * {@code subKeyFactory} function and optionally evaluates
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    88
     * {@code valueFactory} function if there is no entry in the cache for given
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    89
     * pair of (key, subKey) or the entry has already been cleared.
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    90
     *
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    91
     * @param key       possibly null key
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    92
     * @param parameter parameter used together with key to create sub-key and
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    93
     *                  value (should not be null)
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    94
     * @return the cached value (never null)
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    95
     * @throws NullPointerException if {@code parameter} passed in or
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    96
     *                              {@code sub-key} calculated by
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    97
     *                              {@code subKeyFactory} or {@code value}
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    98
     *                              calculated by {@code valueFactory} is null.
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
    99
     */
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   100
    public V get(K key, P parameter) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   101
        Objects.requireNonNull(parameter);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   102
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   103
        expungeStaleEntries();
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   104
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   105
        Object cacheKey = CacheKey.valueOf(key, refQueue);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   106
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   107
        // lazily install the 2nd level valuesMap for the particular cacheKey
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   108
        ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   109
        if (valuesMap == null) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   110
            ConcurrentMap<Object, Supplier<V>> oldValuesMap
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   111
                = map.putIfAbsent(cacheKey,
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   112
                                  valuesMap = new ConcurrentHashMap<>());
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   113
            if (oldValuesMap != null) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   114
                valuesMap = oldValuesMap;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   115
            }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   116
        }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   117
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   118
        // create subKey and retrieve the possible Supplier<V> stored by that
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   119
        // subKey from valuesMap
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   120
        Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   121
        Supplier<V> supplier = valuesMap.get(subKey);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   122
        Factory factory = null;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   123
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   124
        while (true) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   125
            if (supplier != null) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   126
                // supplier might be a Factory or a CacheValue<V> instance
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   127
                V value = supplier.get();
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   128
                if (value != null) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   129
                    return value;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   130
                }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   131
            }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   132
            // else no supplier in cache
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   133
            // or a supplier that returned null (could be a cleared CacheValue
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   134
            // or a Factory that wasn't successful in installing the CacheValue)
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   135
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   136
            // lazily construct a Factory
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   137
            if (factory == null) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   138
                factory = new Factory(key, parameter, subKey, valuesMap);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   139
            }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   140
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   141
            if (supplier == null) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   142
                supplier = valuesMap.putIfAbsent(subKey, factory);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   143
                if (supplier == null) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   144
                    // successfully installed Factory
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   145
                    supplier = factory;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   146
                }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   147
                // else retry with winning supplier
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   148
            } else {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   149
                if (valuesMap.replace(subKey, supplier, factory)) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   150
                    // successfully replaced
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   151
                    // cleared CacheEntry / unsuccessful Factory
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   152
                    // with our Factory
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   153
                    supplier = factory;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   154
                } else {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   155
                    // retry with current supplier
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   156
                    supplier = valuesMap.get(subKey);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   157
                }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   158
            }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   159
        }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   160
    }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   161
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   162
    /**
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   163
     * Checks whether the specified non-null value is already present in this
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   164
     * {@code WeakCache}. The check is made using identity comparison regardless
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   165
     * of whether value's class overrides {@link Object#equals} or not.
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   166
     *
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   167
     * @param value the non-null value to check
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   168
     * @return true if given {@code value} is already cached
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   169
     * @throws NullPointerException if value is null
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   170
     */
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   171
    public boolean containsValue(V value) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   172
        Objects.requireNonNull(value);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   173
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   174
        expungeStaleEntries();
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   175
        return reverseMap.containsKey(new LookupValue<>(value));
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   176
    }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   177
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   178
    /**
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   179
     * Returns the current number of cached entries that
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   180
     * can decrease over time when keys/values are GC-ed.
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   181
     */
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   182
    public int size() {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   183
        expungeStaleEntries();
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   184
        return reverseMap.size();
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   185
    }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   186
23061
c441853d95af 8036744: Fix raw lint warnings in java.lang.reflect.WeakCache
darcy
parents: 17188
diff changeset
   187
    @SuppressWarnings("unchecked") // refQueue.poll actually returns CacheKey<K>
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   188
    private void expungeStaleEntries() {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   189
        CacheKey<K> cacheKey;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   190
        while ((cacheKey = (CacheKey<K>)refQueue.poll()) != null) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   191
            cacheKey.expungeFrom(map, reverseMap);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   192
        }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   193
    }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   194
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   195
    /**
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   196
     * A factory {@link Supplier} that implements the lazy synchronized
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   197
     * construction of the value and installment of it into the cache.
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   198
     */
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   199
    private final class Factory implements Supplier<V> {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   200
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   201
        private final K key;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   202
        private final P parameter;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   203
        private final Object subKey;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   204
        private final ConcurrentMap<Object, Supplier<V>> valuesMap;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   205
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   206
        Factory(K key, P parameter, Object subKey,
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   207
                ConcurrentMap<Object, Supplier<V>> valuesMap) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   208
            this.key = key;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   209
            this.parameter = parameter;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   210
            this.subKey = subKey;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   211
            this.valuesMap = valuesMap;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   212
        }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   213
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   214
        @Override
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   215
        public synchronized V get() { // serialize access
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   216
            // re-check
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   217
            Supplier<V> supplier = valuesMap.get(subKey);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   218
            if (supplier != this) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   219
                // something changed while we were waiting:
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   220
                // might be that we were replaced by a CacheValue
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   221
                // or were removed because of failure ->
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   222
                // return null to signal WeakCache.get() to retry
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   223
                // the loop
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   224
                return null;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   225
            }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   226
            // else still us (supplier == this)
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   227
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   228
            // create new value
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   229
            V value = null;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   230
            try {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   231
                value = Objects.requireNonNull(valueFactory.apply(key, parameter));
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   232
            } finally {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   233
                if (value == null) { // remove us on failure
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   234
                    valuesMap.remove(subKey, this);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   235
                }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   236
            }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   237
            // the only path to reach here is with non-null value
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   238
            assert value != null;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   239
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   240
            // wrap value with CacheValue (WeakReference)
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   241
            CacheValue<V> cacheValue = new CacheValue<>(value);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   242
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   243
            // try replacing us with CacheValue (this should always succeed)
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   244
            if (valuesMap.replace(subKey, this, cacheValue)) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   245
                // put also in reverseMap
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   246
                reverseMap.put(cacheValue, Boolean.TRUE);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   247
            } else {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   248
                throw new AssertionError("Should not reach here");
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   249
            }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   250
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   251
            // successfully replaced us with new CacheValue -> return the value
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   252
            // wrapped by it
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   253
            return value;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   254
        }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   255
    }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   256
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   257
    /**
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   258
     * Common type of value suppliers that are holding a referent.
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   259
     * The {@link #equals} and {@link #hashCode} of implementations is defined
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   260
     * to compare the referent by identity.
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   261
     */
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   262
    private interface Value<V> extends Supplier<V> {}
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   263
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   264
    /**
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   265
     * An optimized {@link Value} used to look-up the value in
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   266
     * {@link WeakCache#containsValue} method so that we are not
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   267
     * constructing the whole {@link CacheValue} just to look-up the referent.
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   268
     */
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   269
    private static final class LookupValue<V> implements Value<V> {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   270
        private final V value;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   271
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   272
        LookupValue(V value) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   273
            this.value = value;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   274
        }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   275
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   276
        @Override
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   277
        public V get() {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   278
            return value;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   279
        }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   280
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   281
        @Override
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   282
        public int hashCode() {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   283
            return System.identityHashCode(value); // compare by identity
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   284
        }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   285
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   286
        @Override
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   287
        public boolean equals(Object obj) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   288
            return obj == this ||
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   289
                   obj instanceof Value &&
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   290
                   this.value == ((Value<?>) obj).get();  // compare by identity
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   291
        }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   292
    }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   293
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   294
    /**
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   295
     * A {@link Value} that weakly references the referent.
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   296
     */
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   297
    private static final class CacheValue<V>
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   298
        extends WeakReference<V> implements Value<V>
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   299
    {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   300
        private final int hash;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   301
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   302
        CacheValue(V value) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   303
            super(value);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   304
            this.hash = System.identityHashCode(value); // compare by identity
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   305
        }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   306
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   307
        @Override
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   308
        public int hashCode() {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   309
            return hash;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   310
        }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   311
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   312
        @Override
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   313
        public boolean equals(Object obj) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   314
            V value;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   315
            return obj == this ||
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   316
                   obj instanceof Value &&
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   317
                   // cleared CacheValue is only equal to itself
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   318
                   (value = get()) != null &&
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   319
                   value == ((Value<?>) obj).get(); // compare by identity
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   320
        }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   321
    }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   322
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   323
    /**
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   324
     * CacheKey containing a weakly referenced {@code key}. It registers
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   325
     * itself with the {@code refQueue} so that it can be used to expunge
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   326
     * the entry when the {@link WeakReference} is cleared.
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   327
     */
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   328
    private static final class CacheKey<K> extends WeakReference<K> {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   329
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   330
        // a replacement for null keys
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   331
        private static final Object NULL_KEY = new Object();
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   332
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   333
        static <K> Object valueOf(K key, ReferenceQueue<K> refQueue) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   334
            return key == null
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   335
                   // null key means we can't weakly reference it,
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   336
                   // so we use a NULL_KEY singleton as cache key
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   337
                   ? NULL_KEY
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   338
                   // non-null key requires wrapping with a WeakReference
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   339
                   : new CacheKey<>(key, refQueue);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   340
        }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   341
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   342
        private final int hash;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   343
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   344
        private CacheKey(K key, ReferenceQueue<K> refQueue) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   345
            super(key, refQueue);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   346
            this.hash = System.identityHashCode(key);  // compare by identity
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   347
        }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   348
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   349
        @Override
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   350
        public int hashCode() {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   351
            return hash;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   352
        }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   353
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   354
        @Override
23061
c441853d95af 8036744: Fix raw lint warnings in java.lang.reflect.WeakCache
darcy
parents: 17188
diff changeset
   355
        @SuppressWarnings("unchecked")
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   356
        public boolean equals(Object obj) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   357
            K key;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   358
            return obj == this ||
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   359
                   obj != null &&
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   360
                   obj.getClass() == this.getClass() &&
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   361
                   // cleared CacheKey is only equal to itself
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   362
                   (key = this.get()) != null &&
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   363
                   // compare key by identity
23061
c441853d95af 8036744: Fix raw lint warnings in java.lang.reflect.WeakCache
darcy
parents: 17188
diff changeset
   364
                   key == ((CacheKey<K>) obj).get(); // Cast is safe from getClass check
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   365
        }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   366
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   367
        void expungeFrom(ConcurrentMap<?, ? extends ConcurrentMap<?, ?>> map,
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   368
                         ConcurrentMap<?, Boolean> reverseMap) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   369
            // removing just by key is always safe here because after a CacheKey
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   370
            // is cleared and enqueue-ed it is only equal to itself
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   371
            // (see equals method)...
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   372
            ConcurrentMap<?, ?> valuesMap = map.remove(this);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   373
            // remove also from reverseMap if needed
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   374
            if (valuesMap != null) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   375
                for (Object cacheValue : valuesMap.values()) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   376
                    reverseMap.remove(cacheValue);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   377
                }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   378
            }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   379
        }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   380
    }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents:
diff changeset
   381
}