Skip to content

Commit 8957bc9

Browse files
committed
LDEV-5903 fix PageSourcePool leak when PhysicalClassLoader flushes
1 parent 5821d91 commit 8957bc9

3 files changed

Lines changed: 29 additions & 13 deletions

File tree

core/src/main/java/lucee/commons/lang/PhysicalClassLoader.java

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@
2424
import java.lang.instrument.UnmodifiableClassException;
2525
import java.net.URL;
2626
import java.net.URLClassLoader;
27+
import java.util.Collections;
2728
import java.util.List;
2829
import java.util.Map;
30+
import java.util.Set;
2931
import java.util.concurrent.ConcurrentHashMap;
3032

3133
import lucee.commons.digest.HashUtil;
@@ -80,19 +82,25 @@ public static void resetLastFlushPagesCleared() {
8082
private Map<String, Integer> allLoadedClasses = new ConcurrentHashMap<>(); // this includes all renames
8183
private Map<String, String> unavaiClasses = new ConcurrentHashMap<>();
8284

83-
private PageSourcePool pageSourcePool;
85+
private final Set<PageSourcePool> pageSourcePools = Collections.newSetFromMap(new ConcurrentHashMap<>());
86+
87+
public void registerPageSourcePool( PageSourcePool pool ) {
88+
if ( pool != null ) {
89+
pageSourcePools.add( pool );
90+
}
91+
}
8492

8593
private boolean rpc;
8694

8795
private String birthplace;
8896

8997
public final String id;
9098

91-
PhysicalClassLoader(Config c, List<Resource> resources, Resource directory, ClassLoader parentClassLoader, ClassLoader addionalClassLoader, PageSourcePool pageSourcePool,
99+
PhysicalClassLoader(Config c, List<Resource> resources, Resource directory, ClassLoader parentClassLoader, ClassLoader addionalClassLoader,
92100
boolean rpc) throws IOException {
93101

94102
this(c, PhysicalClassLoaderFactory.doURLs(resources), resources, directory,
95-
parentClassLoader == null ? (parentClassLoader = SystemUtil.getCombinedClassLoader()) : parentClassLoader, addionalClassLoader, pageSourcePool, rpc);
103+
parentClassLoader == null ? (parentClassLoader = SystemUtil.getCombinedClassLoader()) : parentClassLoader, addionalClassLoader, rpc);
96104

97105
// check directory
98106
if (!directory.exists()) directory.mkdirs();
@@ -101,13 +109,12 @@ public static void resetLastFlushPagesCleared() {
101109
}
102110

103111
private PhysicalClassLoader(Config c, URL[] urls, List<Resource> resources, Resource directory, ClassLoader parentClassLoader, ClassLoader addionalClassLoader,
104-
PageSourcePool pageSourcePool, boolean rpc) {
112+
boolean rpc) {
105113
super(urls, parentClassLoader == null ? (parentClassLoader = SystemUtil.getCombinedClassLoader()) : parentClassLoader);
106114
this.resources = resources;
107115
config = (ConfigPro) c;
108116
this.addionalClassLoader = addionalClassLoader;
109117
this.birthplace = ExceptionUtil.getStacktrace(new Throwable(), false);
110-
this.pageSourcePool = pageSourcePool;
111118

112119
this.directory = directory;
113120
this.rpc = rpc;
@@ -123,10 +130,15 @@ private PhysicalClassLoader(Config c, URL[] urls, List<Resource> resources, Reso
123130
}
124131

125132
public static PhysicalClassLoader flush(PhysicalClassLoader existing, Config config) {
126-
int pagesCleared = existing.pageSourcePool != null ? existing.pageSourcePool.clearPages(existing) : 0;
133+
int pagesCleared = 0;
134+
for (PageSourcePool pool : existing.pageSourcePools) {
135+
pagesCleared += pool.clearPages(existing);
136+
}
127137
lastFlushPagesCleared = pagesCleared;
128138
PhysicalClassLoader clone = new PhysicalClassLoader(config, existing.getURLs(), existing.resources, existing.directory, existing.getParent(), existing.addionalClassLoader,
129-
null, existing.rpc);
139+
existing.rpc);
140+
// copy registered pools to the new classloader
141+
clone.pageSourcePools.addAll(existing.pageSourcePools);
130142
DynamicInvoker instance = DynamicInvoker.getExistingInstance();
131143
int count = 0;
132144
if (instance != null) count += instance.remove(existing);
@@ -454,7 +466,11 @@ private void clear() {
454466
}
455467

456468
private void clear(boolean clearPagePool) {
457-
if (clearPagePool && pageSourcePool != null) pageSourcePool.clearPages(this);
469+
if (clearPagePool) {
470+
for (PageSourcePool pool : pageSourcePools) {
471+
pool.clearPages(this);
472+
}
473+
}
458474
this.loadedClasses.clear();
459475
this.allLoadedClasses.clear();
460476
this.unavaiClasses.clear();

core/src/main/java/lucee/commons/lang/PhysicalClassLoaderFactory.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public static PhysicalClassLoader getPhysicalClassLoader(Config c, Resource dire
5454
PhysicalClassLoader existing = classLoaders.get(key);
5555
if (existing != null) PhysicalClassLoader.flush(existing, c);
5656
}
57-
classLoaders.put(key, rpccl = new PhysicalClassLoader(c, new ArrayList<Resource>(), directory, SystemUtil.getCombinedClassLoader(), null, null, false));
57+
classLoaders.put(key, rpccl = new PhysicalClassLoader(c, new ArrayList<Resource>(), directory, SystemUtil.getCombinedClassLoader(), null, false));
5858
return rpccl;
5959
}
6060
}
@@ -93,8 +93,7 @@ public static PhysicalClassLoader getRPCClassLoader(Config c, JavaSettings js, b
9393
resources = toSortedList(((JavaSettingsImpl) js).getAllResources());
9494
}
9595
Resource dir = storeResourceMeta(c, key, js, resources);
96-
// (Config config, String key, JavaSettings js, Collection<Resource> _resources)
97-
classLoaders.put(key, rpccl = new PhysicalClassLoader(c, resources, dir, parent != null ? parent : SystemUtil.getCombinedClassLoader(), null, null, true));
96+
classLoaders.put(key, rpccl = new PhysicalClassLoader(c, resources, dir, parent != null ? parent : SystemUtil.getCombinedClassLoader(), null, true));
9897
return rpccl;
9998
}
10099
}
@@ -122,8 +121,7 @@ public static PhysicalClassLoader getRPCClassLoader(Config c, BundleClassLoader
122121
}
123122
Resource dir = c.getClassDirectory().getRealResource("RPC/" + key);
124123
if (!dir.exists()) ResourceUtil.createDirectoryEL(dir, true);
125-
// (Config config, String key, JavaSettings js, Collection<Resource> _resources)
126-
classLoaders.put(key, rpccl = new PhysicalClassLoader(c, new ArrayList<Resource>(), dir, SystemUtil.getCombinedClassLoader(), bcl, null, true));
124+
classLoaders.put(key, rpccl = new PhysicalClassLoader(c, new ArrayList<Resource>(), dir, SystemUtil.getCombinedClassLoader(), bcl, true));
127125
return rpccl;
128126
}
129127
}

core/src/main/java/lucee/runtime/MappingImpl.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ public Class<?> loadClass(String className) {
266266

267267
private Class<?> loadClass(String className, byte[] code) throws IOException, ClassNotFoundException {
268268
PhysicalClassLoader pcl = PhysicalClassLoaderFactory.getPhysicalClassLoader(config, getClassRootDirectory(), false);
269+
pcl.registerPageSourcePool( pageSourcePool );
269270
/*
270271
* PhysicalClassLoaderReference pclr = loaders.get(className); PhysicalClassLoader pcl = pclr ==
271272
* null ? null : pclr.get(); if (pcl == null || code != null) {// || pcl.getSize(true) > 3 if (pcl
@@ -280,6 +281,7 @@ private Class<?> loadClass(String className, byte[] code) throws IOException, Cl
280281
}
281282
catch (UnmodifiableClassException e) {
282283
pcl = PhysicalClassLoaderFactory.getPhysicalClassLoader(config, getClassRootDirectory(), true);
284+
pcl.registerPageSourcePool( pageSourcePool );
283285
try {
284286
return pcl.loadClass(className, code);
285287
}

0 commit comments

Comments
 (0)