Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename CacheClass to ClassByNameCache to avoid OpenJDK conflict #515

Merged
merged 1 commit into from
May 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
/*
* ===========================================================================
* (c) Copyright IBM Corp. 2017, 2019 All Rights Reserved
* ===========================================================================
*
* ===========================================================================
* (c) Copyright IBM Corp. 2017, 2022 All Rights Reserved
* ===========================================================================
*
* 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.
* published by the Free Software Foundation.
*
* IBM designates this particular file as subject to the "Classpath" exception
* IBM designates this particular file as subject to the "Classpath" exception
* as provided by IBM in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
Expand All @@ -18,9 +18,9 @@
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, see <http://www.gnu.org/licenses/>.
*
*
* ===========================================================================
*/
*/

package java.io;

Expand All @@ -30,19 +30,18 @@
import java.security.PrivilegedAction;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
/* ClassCache is Primarily responsible for Caching the results of the className lookups and hence to avoid
/* ClassByNameCache is Primarily responsible for Caching the results of the className lookups and hence to avoid
* multiple Lookup for same Class Instance.
* ClassCache provides a ConcurrentHash based ClassCache which is looked up prior to calling the class.forName
* ClassByNameCache provides a ConcurrentHash based ClassByNameCache which is looked up prior to calling the class.forName
* Method resolveClass() from ObjectInputStream uses this Cache.
*
*
* Caching is done only when the actually used loader for a Class is one of the Sytem loaders (ie) App Class Loader,
* System Extension loader and BootStrap loader
*
* System Extension loader and BootStrap loader.
*/
final class ClassCache {
final class ClassByNameCache {
/* Main Cache for storing the Class.forName results Here Key used would be CacheKey */
private final ConcurrentHashMap<Key,Object> cache =
new ConcurrentHashMap<Key,Object>();
new ConcurrentHashMap<Key,Object>();
/* Initiating Loader to CacheKey mapping in the Cache used by Reaper thread for removal on stale Loaders */
private final ConcurrentHashMap<LoaderRef,CacheKey> loaderKeys =
new ConcurrentHashMap<LoaderRef,CacheKey>();
Expand All @@ -56,9 +55,9 @@ final class ClassCache {
* Constructor Populates Canonical Loader Refs with System Loader Entries and initializes the reaper thread which
* monitors the ReferenceQueue for stale loaders
*/
public ClassCache() {
ClassLoader loader = ClassLoader.getSystemClassLoader();

public ClassByNameCache() {
ClassLoader loader = ClassLoader.getSystemClassLoader();
while (loader != null) {
setCanonicalSystemLoaderRef(loader);
loader = loader.getParent();
Expand All @@ -75,7 +74,7 @@ private void setCanonicalSystemLoaderRef(ClassLoader loader) {
LoaderRef newKey = new LoaderRef(loader, staleLoaderRefs, true);
assert (canonicalLoaderRefs.put(newKey, newKey) == null);
}

/*
* get Canonical Loader reference for the loader
*/
Expand Down Expand Up @@ -108,7 +107,7 @@ void removeStaleRef(LoaderRef loaderRef) {
}

/*
* Identifies if the loader used to load is one of the system loaders,
* Identifies if the loader used to load is one of the system loaders,
* if so updates the cache and the LoaderKey, and also a StaleLoaderReference for the initiating LoaderObject
* via LoaderRef Constructor
*/
Expand Down Expand Up @@ -137,7 +136,7 @@ void update(CacheKey key, Class<?> result) {
}
}
/*
* Creates a New Entry in the Cache
* Creates a New Entry in the Cache
*/
private Object createEntry(CacheKey key) {
FutureValue newValue = new FutureValue(key, this); //Does actual call to class.forName as required.
Expand All @@ -146,7 +145,7 @@ private Object createEntry(CacheKey key) {
return value;
}
/*
* This is the entry point in to the cache from ObjectInputStream. First Lookup is done based on the className and Loader
* This is the entry point in to the cache from ObjectInputStream. First Lookup is done based on the className and Loader
*/
public Class<?> get(String className, ClassLoader loader)
throws ClassNotFoundException {
Expand All @@ -157,24 +156,24 @@ public Class<?> get(String className, ClassLoader loader)
}

if (value instanceof FutureValue) {

return ((FutureValue)value).get();
}

return (Class<?>)value;
}

/*
* FutureValue implements Future Mechanics that is required for addressing contention issues in the HashMap
*/

private static final class FutureValue {
private final CacheKey key;
private final LoaderRef loaderRef;
private final ClassCache cache;
private final ClassByNameCache cache;
private Class<?> value = null;

FutureValue(CacheKey key, ClassCache cache) {
FutureValue(CacheKey key, ClassByNameCache cache) {
this.key = key;
this.loaderRef = key.loaderRef;
this.cache = cache;
Expand All @@ -200,27 +199,27 @@ Class<?> get() throws ClassNotFoundException {

private static final class CreateReaperAction
implements PrivilegedAction<Thread> {
private final ClassCache cache;
private final ClassByNameCache cache;
private final ReferenceQueue<Object> queue;

CreateReaperAction(ClassCache cache, ReferenceQueue<Object> queue) {
CreateReaperAction(ClassByNameCache cache, ReferenceQueue<Object> queue) {
this.cache = cache;
this.queue = queue;
}

public Thread run() {
Reaper reaper = new Reaper(cache, queue);
return com.ibm.oti.vm.VM.getVMLangAccess().createThread(reaper, "ClassCache Reaper", true, false, true, null);
return com.ibm.oti.vm.VM.getVMLangAccess().createThread(reaper, "ClassByNameCache Reaper", true, false, true, null);
}
}

private static final class Reaper implements Runnable {
private final WeakReference<ClassCache> cacheRef;
private final WeakReference<ClassByNameCache> cacheRef;
private final ReferenceQueue<Object> queue;

Reaper(ClassCache cache, ReferenceQueue<Object> queue) {
Reaper(ClassByNameCache cache, ReferenceQueue<Object> queue) {
this.queue = queue;
cacheRef = new WeakReference<ClassCache>(cache, queue);
cacheRef = new WeakReference<ClassByNameCache>(cache, queue);
}

/*
Expand All @@ -240,24 +239,24 @@ public void run() {
}

private void processStaleRef(LoaderRef staleRef) {
ClassCache cache = cacheRef.get();
ClassByNameCache cache = cacheRef.get();
if (cache == null) return;

cache.removeStaleRef(staleRef);
}
}

/*
* The use of the loaderRefs map is to allow efficient processing
* of one Weak Reference for each stale ClassLoader, rather than one WR for each entry in the cache.
*
* of one Weak Reference for each stale ClassLoader, rather than one WR for each entry in the cache.
*
* CacheKey as well as Lookup Key will be refering to this LoaderRef.
*
* Initiating Class Loaders needs to be referred for both lookup and Caching,so for performance reasons
* a LoaderRef is maintained which would be used by both LookupKey and CachingKey
* (ie) LookupKey will actually store the LoaderObj, but it will be canonically refered via a loaderRed
* by the caching Key
* LoaderKey has LoaderRef Objects as well and is used to Link the Initiating Loader with the actual cache Entries
* LoaderKey has LoaderRef Objects as well and is used to Link the Initiating Loader with the actual cache Entries
* which is used to remove Stale reference entries.
*/

Expand All @@ -278,9 +277,9 @@ static Object getLoaderObj(ClassLoader loader) {
boolean isSystem) {
this(isSystem, getLoaderObj(loader), queue);
}

/*
* Creates a new weak reference that refers to the given object and is registered with the given queue.
* Creates a new weak reference that refers to the given object and is registered with the given queue.
*/

private LoaderRef(boolean isSystem, Object loaderObj,
Expand Down Expand Up @@ -313,9 +312,9 @@ ClassLoader getActiveLoader() {
/*
* For better clarity and to avoid multiple lookups to the cache. Key is implemented to have
* one abstract key to final sub classes which serve specific purpose
* LookupKey - This is a short lived key, not part of any hashmap and stores the strong reference to
* LookupKey - This is a short lived key, not part of any hashmap and stores the strong reference to
* loaderobject
* CachingKey - uses the same hash as LookupKey and has a means to be generated from LookupKey and has reference
* CachingKey - uses the same hash as LookupKey and has a means to be generated from LookupKey and has reference
* to the Loaderobj via a weakreference.
*/

Expand Down Expand Up @@ -345,13 +344,13 @@ public final int hashCode() {
}
}
/*
* Lookup Key hash code is framed using loadername hash + loader's system identity hashcode. This
* Lookup Key hash code is framed using loadername hash + loader's system identity hashcode. This
* is same as the hashcode maintained in CacheKey
*/

private static final class LookupKey extends Key {
private final Object loaderObj;
private final ClassCache cache;
private final ClassByNameCache cache;

private static int hashCode(String className, ClassLoader loader) {
int hashcode = className.hashCode();
Expand All @@ -363,7 +362,7 @@ private static int hashCode(String className, ClassLoader loader) {
}

public LookupKey(String className, ClassLoader loader,
ClassCache cache) {
ClassByNameCache cache) {
super(Objects.requireNonNull(className),
hashCode(className, loader));
loaderObj = LoaderRef.getLoaderObj(loader);
Expand All @@ -381,9 +380,9 @@ CacheKey createCacheKey() {
}

/*
* CacheKey is the actual key that is stored in the cache, and it stores the weakreference
* CacheKey is the actual key that is stored in the cache, and it stores the weakreference
* of the Initiating loader object via loaderRef
*
*
*/
private static final class CacheKey extends Key {
public final LoaderRef loaderRef;
Expand Down
12 changes: 6 additions & 6 deletions src/java.base/share/classes/java/io/ObjectInputStream.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
*/
/*
* ===========================================================================
* (c) Copyright IBM Corp. 2018, 2020 All Rights Reserved
* (c) Copyright IBM Corp. 2018, 2022 All Rights Reserved
* ===========================================================================
*/

Expand Down Expand Up @@ -354,13 +354,13 @@ private static class Logging {
* read* requests
*/

/* ClassCache Entry for caching class.forName results upon enableClassCaching */
private static final ClassCache classCache;
/* ClassByNameCache Entry for caching class.forName results upon enableClassCaching */
private static final ClassByNameCache classByNameCache;
private static final boolean isClassCachingEnabled;
static {
isClassCachingEnabled =
AccessController.doPrivileged(new GetClassCachingSettingAction());
classCache = (isClassCachingEnabled ? new ClassCache() : null);
classByNameCache = (isClassCachingEnabled ? new ClassByNameCache() : null);
}


Expand Down Expand Up @@ -867,14 +867,14 @@ protected Class<?> resolveClass(ObjectStreamClass desc)
{
String name = desc.getName();
try {
if (null == classCache) {
if (null == classByNameCache) {
return Class.forName(name, false, latestUserDefinedLoader());
} else {
if (refreshLudcl) {
cachedLudcl = latestUserDefinedLoader();
refreshLudcl = false;
}
return classCache.get(name, cachedLudcl);
return classByNameCache.get(name, cachedLudcl);
}
} catch (ClassNotFoundException ex) {
Class<?> cl = primClasses.get(name);
Expand Down