1 /* 2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 package jdk.internal.util.concurrent; 25 26 import java.util.Objects; 27 import java.util.function.BiFunction; 28 29 /** 30 * root-ClassLoaderValue. Each instance defines a separate namespace for 31 * associated values. 32 * <p> 33 * ClassLoaderValue allows associating a 34 * {@link #computeIfAbsent(ClassLoader, BiFunction) computed} non-null value with 35 * a {@code (ClassLoader, keys...)} tuple. The associated value, as well as the 36 * keys are strongly reachable from the associated ClassLoader so care should be 37 * taken to use such keys and values that only reference types resolvable from 38 * the associated ClassLoader. Failing that, ClassLoader leaks are inevitable. 39 * <p> 40 * Example usage: 41 * <pre>{@code 42 * // create a root instance which represents a namespace and declares the type of 43 * // associated values (Class instances in this example) 44 * static final ClassLoaderValue<Class<?>> proxyClasses = new ClassLoaderValue<>(); 45 * 46 * // create a compound key composed of a Module and a list of interfaces 47 * Module module = ...; 48 * List<Class<?>> interfaces = ...; 49 * ClassLoaderValue<Class<?>>.Sub<Module>.Sub<List<Class<?>>> key = 50 * proxyClasses.sub(module).sub(interfaces); 51 * 52 * // use the compound key together with ClassLoader to lazily associate 53 * // the value with tuple (loader, module, interfaces) and return it 54 * ClassLoader loader = ...; 55 * Class<?> proxyClass = key.computeIfAbsent(loader, (ld, ky) -> { 56 * List<Class<?>> intfcs = ky.key(); 57 * Module m = ky.parent().key(); 58 * Class<?> clazz = defineProxyClass(ld, m, intfcs); 59 * return clazz; 60 * }); 61 * }</pre> 62 * <p> 63 * {@code classLoaderValue.<operation>(classLoader, ...)} represents an operation 64 * to {@link #get}, {@link #putIfAbsent}, {@link #computeIfAbsent} or {@link #remove} 65 * a value associated with a (classLoader, classLoaderValue) tuple. ClassLoader 66 * instances and root-{@link ClassLoaderValue} instances are compared using 67 * identity equality while {@link Sub sub}-ClassLoaderValue instances define 68 * {@link #equals(Object) equality} in terms of equality of its 69 * {@link Sub#parent() parent} ClassLoaderValue and its 70 * {@link #key() key} component. 71 * 72 * @param <V> the type of value(s) associated with the root-ClassLoaderValue and 73 * all its {@link #sub(Object) descendants}. 74 * @author Peter Levart 75 * @since 9 76 */ 77 public final class ClassLoaderValue<V> 78 extends AbstractClassLoaderValue<ClassLoaderValue<V>, V> { 79 80 /** 81 * Constructs new root-ClassLoaderValue representing its own namespace. 82 */ 83 public ClassLoaderValue() {} 84 85 /** 86 * @return the key component of this root-ClassLoaderValue (itself). 87 */ 88 @Override 89 public ClassLoaderValue<V> key() { 90 return this; 91 } 92 93 /** 94 * root-ClassLoaderValue can only be equal to itself and has no predecessors. 95 */ 96 @Override 97 public boolean isEqualOrDescendantOf(AbstractClassLoaderValue<?, V> clv) { 98 return equals(Objects.requireNonNull(clv)); 99 } 100 }