Skip to content

Commit

Permalink
For ProxyClassLoader:
Browse files Browse the repository at this point in the history
- Use ConcurrentMap for 'packages' map and remove some synchronized blocks
- Use ConcurrentHashMap.newKeySet() instead of
  Collections.synchronizedSet for 'ARBITRARY_LOAD_WARNINGS' set
- Remove unused variables
For ProxyClassPackages:
- Use ConcurrentMap for 'PACKAGE_COVERAGE' map and remove the
  synchronized methods for get and remove operations
- Use synchronized on the 'PACKAGE_COVERAGE' map for the add operation. It
  needs to be linearizable.
- Regenerate signatures for 'o.n.bootstrap' module
  • Loading branch information
pepness committed Aug 6, 2023
1 parent 7d16bfe commit 3f6476b
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 67 deletions.
4 changes: 2 additions & 2 deletions platform/o.n.bootstrap/nbproject/org-netbeans-bootstrap.sig
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#Signature file v4.1
#Version 2.99
#Version 2.101

CLSS public java.awt.datatransfer.Clipboard
cons public init(java.lang.String)
Expand Down Expand Up @@ -525,7 +525,7 @@ meth public java.util.Enumeration<java.net.URL> findResources(java.lang.String)
meth public void append(java.lang.ClassLoader[])
meth public void destroy()
supr java.lang.ClassLoader
hfds LOGGER,LOG_LOADING,TOP_CL,arbitraryLoadWarnings,delegatingPredicate,packages,parents,sclPackages
hfds ARBITRARY_LOAD_WARNINGS,LOGGER,LOG_LOADING,TOP_CL,delegatingPredicate,packages,parents,sclPackages

CLSS public org.netbeans.ProxyURLStreamHandlerFactory
intf java.net.URLStreamHandlerFactory
Expand Down
71 changes: 35 additions & 36 deletions platform/o.n.bootstrap/src/org/netbeans/ProxyClassLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.BiFunction;
import java.util.logging.Level;
import java.util.logging.Logger;
Expand Down Expand Up @@ -62,7 +64,7 @@ public class ProxyClassLoader extends ClassLoader {
/** All known packages
* @GuardedBy("packages")
*/
private final Map<String, Package> packages = new HashMap<String, Package>();
private final ConcurrentMap<String, Package> packages = new ConcurrentHashMap<>();

/** keeps information about parent classloaders, system classloader, etc.*/
volatile ProxyClassParents parents;
Expand Down Expand Up @@ -107,7 +109,6 @@ public void append(ClassLoader[] nueparents) throws IllegalArgumentException {
if (cl == null) throw new IllegalArgumentException("null parent: " + Arrays.asList(nueparents)); // NOI18N
}

ProxyClassLoader[] resParents = null;
ModuleFactory moduleFactory = Lookup.getDefault().lookup(ModuleFactory.class);
if (moduleFactory != null && moduleFactory.removeBaseClassLoader()) {
// this hack is here to prevent having the application classloader
Expand Down Expand Up @@ -203,7 +204,7 @@ private Class<?> doFindClass(String name) throws ClassNotFoundException {
cls.getClassLoader() + " and " + pcl + " starting from " + this +
"; see http://wiki.netbeans.org/DevFaqModuleCCE";
ClassNotFoundException cnfe = new ClassNotFoundException(message);
if (arbitraryLoadWarnings.add(message)) {
if (ARBITRARY_LOAD_WARNINGS.add(message)) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, null, cnfe);
} else {
Expand Down Expand Up @@ -232,7 +233,6 @@ private Class<?> doFindClass(String name) throws ClassNotFoundException {
}

private String diagnosticCNFEMessage(String base, Set<ProxyClassLoader> del) {
String parentSetS;
int size = parents.size();
// Too big to show in its entirety - overwhelms the log file.
StringBuilder b = new StringBuilder();
Expand All @@ -250,7 +250,7 @@ private String diagnosticCNFEMessage(String base, Set<ProxyClassLoader> del) {
b.append(']');
return b.toString();
}
private static final Set<String> arbitraryLoadWarnings = Collections.synchronizedSet(new HashSet<String>());
private static final Set<String> ARBITRARY_LOAD_WARNINGS = ConcurrentHashMap.newKeySet();

/** May return null */
private synchronized Class<?> selfLoadClass(String pkg, String name) {
Expand All @@ -266,7 +266,7 @@ private synchronized Class<?> selfLoadClass(String pkg, String name) {
}
if (LOG_LOADING && !name.startsWith("java.")) LOGGER.log(Level.FINEST, "{0} loaded {1}",
new Object[] {this, name});
}
}
return cls;
}

Expand Down Expand Up @@ -468,34 +468,35 @@ protected Package getPackage(String name) {
* @return located package, or null
*/
protected Package getPackageFast(String name, boolean recurse) {
synchronized (packages) {
Package pkg = packages.get(name);
if (pkg != null) {
return pkg;
}
if (!recurse) {
return null;
}
String path = name.replace('.', '/');
for (ProxyClassLoader par : this.parents.loaders()) {
if (!shouldDelegateResource(path, par))
continue;
pkg = par.getPackageFast(name, false);
if (pkg != null) break;
}
// pretend the resource ends with "/". This works better with hidden package and
// prefix-based checks.
if (pkg == null && shouldDelegateResource(path + "/", null)) {
// Cannot access either Package.getSystemPackages nor ClassLoader.getPackage
// from here, so do the best we can though it will cause unnecessary
// duplication of the package cache (PCL.packages vs. CL.packages):
pkg = super.getPackage(name);
Package pkg = packages.get(name);
if (pkg != null) {
return pkg;
}
if (!recurse) {
return null;
}
String path = name.replace('.', '/');
for (ProxyClassLoader par : this.parents.loaders()) {
if (!shouldDelegateResource(path, par)) {
continue;
}
pkg = par.getPackageFast(name, false);
if (pkg != null) {
packages.put(name, pkg);
break;
}
return pkg;
}
// pretend the resource ends with "/". This works better with hidden package and
// prefix-based checks.
if (pkg == null && shouldDelegateResource(path + "/", null)) {
// Cannot access either Package.getSystemPackages nor ClassLoader.getPackage
// from here, so do the best we can though it will cause unnecessary
// duplication of the package cache (PCL.packages vs. CL.packages):
pkg = super.getPackage(name);
}
if (pkg != null) {
packages.put(name, pkg);
}
return pkg;
}

/** This is here just for locking serialization purposes.
Expand All @@ -508,12 +509,10 @@ protected Package definePackage(String name, String specTitle,
String specVersion, String specVendor, String implTitle,
String implVersion, String implVendor, URL sealBase )
throws IllegalArgumentException {
synchronized (packages) {
Package pkg = super.definePackage(name, specTitle, specVersion, specVendor, implTitle,
Package pkg = super.definePackage(name, specTitle, specVersion, specVendor, implTitle,
implVersion, implVendor, sealBase);
packages.put(name, pkg);
return pkg;
}
packages.put(name, pkg);
return pkg;
}

/**
Expand Down Expand Up @@ -585,7 +584,7 @@ final ClassLoader firstParent() {
// System Class Loader Packages Support
//

private static Map<String,Boolean> sclPackages = Collections.synchronizedMap(new HashMap<String,Boolean>());
private static ConcurrentMap<String,Boolean> sclPackages = new ConcurrentHashMap<>();
private static Boolean isSystemPackage(String pkg) {
return sclPackages.get(pkg);
}
Expand Down
54 changes: 25 additions & 29 deletions platform/o.n.bootstrap/src/org/netbeans/ProxyClassPackages.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,10 @@
package org.netbeans;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/** Keeps the coverage of various packages by existing ProxyClassLoaders.
*
Expand All @@ -32,47 +31,44 @@
final class ProxyClassPackages {
private ProxyClassPackages() {
}

/** A shared map of all packages known by all classloaders. Also covers META-INF based resources.
* It contains two kinds of keys: dot-separated package names and slash-separated
* META-INF resource names, e.g. {"org.foobar", "/services/org.foobar.Foo"}
*/
private static final Map<String, Set<ProxyClassLoader>> packageCoverage = new HashMap<String, Set<ProxyClassLoader>>();
private static final ConcurrentMap<String, Set<ProxyClassLoader>> PACKAGE_COVERAGE = new ConcurrentHashMap<>();

static synchronized void addCoveredPackages(
ProxyClassLoader loader, Iterable<String> coveredPackages
) {
for (String pkg : coveredPackages) {
Set<ProxyClassLoader> delegates = ProxyClassPackages.packageCoverage.get(pkg);
if (delegates == null) {
delegates = Collections.<ProxyClassLoader>singleton(loader);
ProxyClassPackages.packageCoverage.put(pkg, delegates);
} else if (delegates.size() == 1) {
delegates = new HashSet<ProxyClassLoader>(delegates);
ProxyClassPackages.packageCoverage.put(pkg, delegates);
delegates.add(loader);
} else {
delegates.add(loader);
static void addCoveredPackages( ProxyClassLoader loader, Iterable<String> coveredPackages) {
synchronized(PACKAGE_COVERAGE) {
for (String pkg : coveredPackages) {
Set<ProxyClassLoader> delegates = ProxyClassPackages.PACKAGE_COVERAGE.get(pkg);
if (delegates == null) {
delegates = Collections.<ProxyClassLoader>singleton(loader);
ProxyClassPackages.PACKAGE_COVERAGE.put(pkg, delegates);
} else if (delegates.size() == 1) {
delegates = new HashSet<ProxyClassLoader>(delegates);
ProxyClassPackages.PACKAGE_COVERAGE.put(pkg, delegates);
delegates.add(loader);
} else {
delegates.add(loader);
}
}
}
}

static synchronized void removeCoveredPakcages(
ProxyClassLoader loader
) {
for (Iterator<String> it = ProxyClassPackages.packageCoverage.keySet().iterator(); it.hasNext();) {
String pkg = it.next();
Set<ProxyClassLoader> set = ProxyClassPackages.packageCoverage.get(pkg);
static void removeCoveredPakcages(ProxyClassLoader loader) {
PACKAGE_COVERAGE.values().removeIf( (Set<ProxyClassLoader> set) -> {
if (set.contains(loader) && set.size() == 1) {
it.remove();
return true;
} else {
set.remove(loader);
return false;
}
}
} );
}

static synchronized Set<ProxyClassLoader> findCoveredPkg(String pkg) {
return packageCoverage.get(pkg);
static Set<ProxyClassLoader> findCoveredPkg(String pkg) {
return PACKAGE_COVERAGE.get(pkg);
}

}

0 comments on commit 3f6476b

Please sign in to comment.