15
15
import java .io .File ;
16
16
import java .io .FileInputStream ;
17
17
import java .io .IOException ;
18
+ import java .util .ArrayList ;
18
19
import java .util .HashMap ;
19
20
import java .util .HashSet ;
20
21
import java .util .Iterator ;
22
+ import java .util .List ;
21
23
import java .util .Map ;
22
24
import java .util .Set ;
23
25
33
35
public class SimpleClassLoader extends ClassLoader {
34
36
35
37
private String classpath ;
38
+ private String tag ;
36
39
37
40
private Set <String > targetClasses ;
38
41
private Map <String , Class <?>> loadedClasses ;
@@ -42,12 +45,17 @@ public class SimpleClassLoader extends ClassLoader {
42
45
private static ClassLoader defaultLoader = SimpleClassLoader .class .getClassLoader ();
43
46
private static Map <String , SimpleClassLoader > allLoaders = new HashMap <String , SimpleClassLoader >();
44
47
45
- public SimpleClassLoader (ClassLoader parent , String path ) {
48
+ public SimpleClassLoader (ClassLoader parent , String path , String tag ) {
46
49
super (parent );
47
50
targetClasses = new HashSet <String >();
48
51
loadedClasses = new HashMap <String , Class <?>>();
49
52
loadingMutex = new Object ();
50
53
classpath = path ;
54
+ this .tag = tag ;
55
+ }
56
+
57
+ protected boolean isSystemClass (String clazzName ) {
58
+ return clazzName .startsWith ("java." ) || clazzName .startsWith ("javax." );
51
59
}
52
60
53
61
@ Override
@@ -61,19 +69,27 @@ public Class<?> loadClass(String clazzName) throws ClassNotFoundException {
61
69
synchronized (loadingMutex ) {
62
70
clazz = loadedClasses .get (clazzName );
63
71
if (clazz == null ) {
72
+ // The following two lines are IO sensitive
64
73
byte [] bytes = loadClassData (clazzName );
65
74
clazz = defineClass (clazzName , bytes , 0 , bytes .length );
66
- synchronized (loadedClasses ) {
67
- loadedClasses .put (clazzName , clazz );
68
- }
75
+ loadedClasses .put (clazzName , clazz );
69
76
}
70
77
}
71
78
return clazz ;
72
79
} catch (Throwable e ) {
73
80
//e.printStackTrace();
74
81
}
75
82
}
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 ;
77
93
}
78
94
79
95
/*
@@ -136,30 +152,160 @@ public static Object loadSimpleInstance(String clazzName) {
136
152
* @param classpath for the given class
137
153
*/
138
154
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 ) {
139
168
hasClassReloaded = true ;
140
169
SimpleClassLoader loader = null ;
170
+ Set <SimpleClassLoader > checkedLoaders = new HashSet <SimpleClassLoader >();
141
171
synchronized (allLoaders ) {
142
172
for (Iterator <SimpleClassLoader > itr = allLoaders .values ().iterator ();
143
173
itr .hasNext ();) {
144
174
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
+ }
149
197
}
150
198
loader = null ;
151
199
}
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
+ }
152
220
}
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
+ }
158
226
}
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 >();
159
248
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 );
161
307
}
162
- SimpleSerializable . removeCachedClassFields ( clazzName );
308
+ return buffer . toString ( );
163
309
}
164
-
310
+
165
311
}
0 commit comments