Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit dd7b1cc

Browse files
Fixing class loader bug of incorrectly assigning class to class loader in which class is already marked as loaded.
Supporting reloading multiple classes in one class loader Adding status monitor and releasing unused class loaders
1 parent 10eca7b commit dd7b1cc

File tree

1 file changed

+163
-17
lines changed

1 file changed

+163
-17
lines changed

sources/net.sf.j2s.ajax/ajaxrpc/net/sf/j2s/ajax/SimpleClassLoader.java

Lines changed: 163 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@
1515
import java.io.File;
1616
import java.io.FileInputStream;
1717
import java.io.IOException;
18+
import java.util.ArrayList;
1819
import java.util.HashMap;
1920
import java.util.HashSet;
2021
import java.util.Iterator;
22+
import java.util.List;
2123
import java.util.Map;
2224
import java.util.Set;
2325

@@ -33,6 +35,7 @@
3335
public class SimpleClassLoader extends ClassLoader {
3436

3537
private String classpath;
38+
private String tag;
3639

3740
private Set<String> targetClasses;
3841
private Map<String, Class<?>> loadedClasses;
@@ -42,12 +45,17 @@ public class SimpleClassLoader extends ClassLoader {
4245
private static ClassLoader defaultLoader = SimpleClassLoader.class.getClassLoader();
4346
private static Map<String, SimpleClassLoader> allLoaders = new HashMap<String, SimpleClassLoader>();
4447

45-
public SimpleClassLoader(ClassLoader parent, String path) {
48+
public SimpleClassLoader(ClassLoader parent, String path, String tag) {
4649
super(parent);
4750
targetClasses = new HashSet<String>();
4851
loadedClasses = new HashMap<String, Class<?>>();
4952
loadingMutex = new Object();
5053
classpath = path;
54+
this.tag = tag;
55+
}
56+
57+
protected boolean isSystemClass(String clazzName) {
58+
return clazzName.startsWith("java.") || clazzName.startsWith("javax.");
5159
}
5260

5361
@Override
@@ -61,19 +69,27 @@ public Class<?> loadClass(String clazzName) throws ClassNotFoundException {
6169
synchronized (loadingMutex) {
6270
clazz = loadedClasses.get(clazzName);
6371
if (clazz == null) {
72+
// The following two lines are IO sensitive
6473
byte[] bytes = loadClassData(clazzName);
6574
clazz = defineClass(clazzName, bytes, 0, bytes.length);
66-
synchronized (loadedClasses) {
67-
loadedClasses.put(clazzName, clazz);
68-
}
75+
loadedClasses.put(clazzName, clazz);
6976
}
7077
}
7178
return clazz;
7279
} catch (Throwable e) {
7380
//e.printStackTrace();
7481
}
7582
}
76-
return getParent().loadClass(clazzName);
83+
Class<?> clazz = getParent().loadClass(clazzName);
84+
if (isSystemClass(clazzName)) {
85+
return clazz;
86+
} // else add to loaded classes map
87+
synchronized (loadingMutex) {
88+
if (!loadedClasses.containsKey(clazzName)) {
89+
loadedClasses.put(clazzName, clazz);
90+
}
91+
}
92+
return clazz;
7793
}
7894

7995
/*
@@ -136,30 +152,160 @@ public static Object loadSimpleInstance(String clazzName) {
136152
* @param classpath for the given class
137153
*/
138154
public static void reloadSimpleClass(String clazzName, String path) {
155+
reloadSimpleClasses(new String[] { clazzName }, path, null);
156+
}
157+
158+
/**
159+
* Try to reload given classes.
160+
*
161+
* Class should contains default constructor.
162+
*
163+
* @param clazzNames
164+
* @param classpath for the given class
165+
* @param tag, with specified tag
166+
*/
167+
public static void reloadSimpleClasses(String[] clazzNames, String path, String tag) {
139168
hasClassReloaded = true;
140169
SimpleClassLoader loader = null;
170+
Set<SimpleClassLoader> checkedLoaders = new HashSet<SimpleClassLoader>();
141171
synchronized (allLoaders) {
142172
for (Iterator<SimpleClassLoader> itr = allLoaders.values().iterator();
143173
itr.hasNext();) {
144174
loader = (SimpleClassLoader) itr.next();
145-
if (!loader.loadedClasses.containsKey(clazzName)
146-
&& ((loader.classpath == null && path == null) || loader.classpath.equals(path))) {
147-
// Class loader does not know class specified by clazzName variable
148-
break;
175+
if (checkedLoaders.contains(loader)) {
176+
loader = null;
177+
continue;
178+
}
179+
checkedLoaders.add(loader);
180+
if ((tag == null // for tag is null, use any existed loader
181+
|| (loader.tag != null && loader.tag.equals(tag)))
182+
&& ((loader.classpath == null && path == null)
183+
|| (loader.classpath != null && loader.classpath.equals(path)))) {
184+
boolean loaded = false;
185+
for (int i = 0; i < clazzNames.length; i++) {
186+
String name = clazzNames[i];
187+
if (name != null && name.length() > 0
188+
&& loader.loadedClasses.containsKey(name)) {
189+
loaded = true;
190+
break;
191+
}
192+
}
193+
if (!loaded) {
194+
// Class loader does not know class specified by clazzName variable
195+
break;
196+
}
149197
}
150198
loader = null;
151199
}
200+
boolean creatingMore = false;
201+
if (loader == null) {
202+
loader = new SimpleClassLoader(defaultLoader, path, tag);
203+
creatingMore = true;
204+
}
205+
for (int i = 0; i < clazzNames.length; i++) {
206+
String name = clazzNames[i];
207+
if (name != null && name.length() > 0) {
208+
loader.targetClasses.add(name);
209+
}
210+
}
211+
if (creatingMore) { // keep it in all loaders
212+
allLoaders.put("." + (checkedLoaders.size() + 1), loader);
213+
}
214+
for (int i = 0; i < clazzNames.length; i++) {
215+
String name = clazzNames[i];
216+
if (name != null && name.length() > 0) {
217+
allLoaders.put(name, loader);
218+
}
219+
}
152220
}
153-
if (loader == null) {
154-
loader = new SimpleClassLoader(defaultLoader, path);
155-
}
156-
synchronized (loader.targetClasses) {
157-
loader.targetClasses.add(clazzName);
221+
for (int i = 0; i < clazzNames.length; i++) {
222+
String name = clazzNames[i];
223+
if (name != null && name.length() > 0) {
224+
SimpleSerializable.removeCachedClassFields(name);
225+
}
158226
}
227+
}
228+
229+
public static void releaseUnusedClassLoaders() {
230+
List<String> removingKeys = new ArrayList<String>();
231+
synchronized (allLoaders) {
232+
for (Iterator<String> itr = allLoaders.keySet().iterator(); itr.hasNext();) {
233+
String key = (String) itr.next();
234+
if (key.startsWith(".")) {
235+
removingKeys.add(key);
236+
}
237+
}
238+
for (Iterator<String> itr = removingKeys.iterator(); itr.hasNext();) {
239+
String key = (String) itr.next();
240+
allLoaders.remove(key);
241+
}
242+
}
243+
}
244+
245+
public static String allLoaderStatuses() {
246+
StringBuffer buffer = new StringBuffer();
247+
Set<SimpleClassLoader> checkedLoaders = new HashSet<SimpleClassLoader>();
159248
synchronized (allLoaders) {
160-
allLoaders.put(clazzName, loader);
249+
int count = 0;
250+
for (Iterator<SimpleClassLoader> itr = allLoaders.values().iterator();
251+
itr.hasNext();) {
252+
SimpleClassLoader loader = (SimpleClassLoader) itr.next();
253+
if (checkedLoaders.contains(loader)) {
254+
continue;
255+
}
256+
checkedLoaders.add(loader);
257+
count++;
258+
buffer.append("Classloader ");
259+
buffer.append(count);
260+
buffer.append(" ");
261+
buffer.append(loader.toString());
262+
buffer.append("\r\n");
263+
buffer.append("classpath : ");
264+
buffer.append(loader.classpath);
265+
buffer.append("\r\n");
266+
if (loader.tag != null) {
267+
buffer.append("tag : ");
268+
buffer.append(loader.tag);
269+
buffer.append("\r\n");
270+
}
271+
buffer.append("active classes : ");
272+
for (Iterator<String> iter = loader.loadedClasses.keySet().iterator(); iter
273+
.hasNext();) {
274+
String clazz = (String) iter.next();
275+
SimpleClassLoader clazzLoader = allLoaders.get(clazz);
276+
if (clazzLoader == loader) {
277+
buffer.append(clazz);
278+
buffer.append(", ");
279+
}
280+
}
281+
buffer.append("\r\n");
282+
buffer.append("inactive classes : ");
283+
for (Iterator<String> iter = loader.loadedClasses.keySet().iterator(); iter
284+
.hasNext();) {
285+
String clazz = (String) iter.next();
286+
SimpleClassLoader clazzLoader = allLoaders.get(clazz);
287+
if (clazzLoader != null && clazzLoader != loader) {
288+
buffer.append(clazz);
289+
buffer.append(", ");
290+
}
291+
}
292+
buffer.append("\r\n");
293+
buffer.append("other classes : ");
294+
for (Iterator<String> iter = loader.loadedClasses.keySet().iterator(); iter
295+
.hasNext();) {
296+
String clazz = (String) iter.next();
297+
SimpleClassLoader clazzLoader = allLoaders.get(clazz);
298+
if (clazzLoader == null) {
299+
buffer.append(clazz);
300+
buffer.append(", ");
301+
}
302+
}
303+
buffer.append("\r\n\r\n");
304+
} // end of for values
305+
buffer.append("Total classloaders : ");
306+
buffer.append(count);
161307
}
162-
SimpleSerializable.removeCachedClassFields(clazzName);
308+
return buffer.toString();
163309
}
164-
310+
165311
}

0 commit comments

Comments
 (0)