Lines 112-148
Link Here
|
112 |
} |
112 |
} |
113 |
} |
113 |
} |
114 |
|
114 |
|
115 |
/** |
115 |
protected static char[] namescratch = new char[115]; |
116 |
* Loads the class with the specified name. The implementation of |
116 |
//needs to be big enough to accomodate |
117 |
* this method searches for classes in the following order:<p> |
117 |
//org.netbeans.modules.properties.syntax.PropertiesSettingsInitializer$PropertiesTokenColoringInitializer.class |
118 |
* <ol> |
118 |
protected static char[] pkgscratch = new char[90]; |
119 |
* <li> Calls {@link #findLoadedClass(String)} to check if the class has |
119 |
//These arrays are sized > longest neede name for NetBeans - |
120 |
* already been loaded. |
120 |
|
121 |
* <li> Checks the caches whether another class from the same package |
121 |
//org.netbeans.modules.projects.CurrentProjectNode$Explorer$MiniStatusBarStateListener.class |
122 |
* was already loaded and uses the same classloader |
122 |
private static final char[] clazzext = new char[] {'.','c','l','a','s','s'}; |
123 |
* <li> Tries to find the class using parent loaders in their order. |
123 |
protected synchronized final Class loadClass(String name, boolean resolve) |
124 |
* <li> Calls the {@link #simpleFindClass(String,String)} method to find |
|
|
125 |
* the class using this class loader. |
126 |
* </ol> |
127 |
* |
128 |
* @param name the name of the class |
129 |
* @param resolve if <code>true</code> then resolve the class |
130 |
* @return the resulting <code>Class</code> object |
131 |
* @exception ClassNotFoundException if the class could not be found |
132 |
*/ |
133 |
protected synchronized final Class loadClass(String name, boolean resolve) |
134 |
throws ClassNotFoundException { |
124 |
throws ClassNotFoundException { |
135 |
zombieCheck(name); |
125 |
zombieCheck(name); |
136 |
String filename = name.replace('.', '/').concat(".class"); // NOI18N |
126 |
/* The following code is an heavy optimization of |
137 |
int idx = filename.lastIndexOf('/'); // NOI18N |
127 |
String filename = name.replace('.', '/').concat(".class"); // NOI18N |
138 |
if (idx == -1) throw new ClassNotFoundException("Will not load classes from default package"); // NOI18N |
128 |
int idx = filename.lastIndexOf('/'); // NOI18N |
139 |
String pkg = filename.substring(0, idx + 1); // "org/netbeans/modules/foo/" |
129 |
to improve performance and reduce memory allocation. |
140 |
Class c = smartLoadClass(name, filename, pkg); |
130 |
*/ |
|
|
131 |
int nlen = name.length(); |
132 |
//create an array with room for .class |
133 |
int end = nlen +6; |
134 |
//copy the constant char array here |
135 |
//copy the name into the beginning of the array |
136 |
try { |
137 |
name.getChars(0, nlen, namescratch, 0); |
138 |
} catch (ArrayIndexOutOfBoundsException ae1) { |
139 |
namescratch = new char[nlen + 20]; |
140 |
name.getChars(0, nlen, namescratch, 0); |
141 |
} |
142 |
//quickly scan backwards and find the last occurance of '.' & |
143 |
//save the result |
144 |
int idx = nlen-1; |
145 |
for (;(idx >= 0) && (namescratch[idx] != '.'); idx--) { |
146 |
//empty impl |
147 |
} |
148 |
if (idx < 0) throw new ClassNotFoundException("Will not load classes from default package - " + name); // NOI18N |
149 |
//since we know about it already, set the final . to / now |
150 |
namescratch[idx] = '/'; |
151 |
// idx++; |
152 |
|
153 |
try { |
154 |
//iterate forward up to package name boundary, skipping |
155 |
//the one we already set and the preceding character (if that |
156 |
//is / or . we have an illegal package name and it will be |
157 |
//caught later, so doesn't matter). Overflowing doesn't matter, we |
158 |
//will only copy up to the value of the end field, and any |
159 |
//inadvertent modifications will be overwritten by '.class'. |
160 |
for (int j=0; j < idx; j+=5) { |
161 |
namescratch[j] = namescratch[j] == '.' ? '/' : namescratch[j]; |
162 |
namescratch[j+1] = namescratch[j+1] == '.' ? '/' : namescratch[j+1]; |
163 |
namescratch[j+2] = namescratch[j+2] == '.' ? '/' : namescratch[j+2]; |
164 |
namescratch[j+3] = namescratch[j+3] == '.' ? '/' : namescratch[j+3]; |
165 |
namescratch[j+4] = namescratch[j+4] == '.' ? '/' : namescratch[j+4]; |
166 |
} |
167 |
} catch (ArrayIndexOutOfBoundsException e) { |
168 |
//on the rare occasion that it won't fit, reallocate and do it again |
169 |
char[] old = namescratch; |
170 |
namescratch = new char[old.length + 20]; |
171 |
System.arraycopy (old, 0, namescratch, 0, old.length); |
172 |
//do it the slow way, won't happen often if at all |
173 |
for (int j1=0; j1 < idx; j1++) { |
174 |
if (namescratch[j1] == '.') namescratch[j1]='/'; |
175 |
} |
176 |
} |
177 |
|
178 |
//now copy in the .class extension |
179 |
try { |
180 |
System.arraycopy(clazzext, 0, namescratch, nlen, 6); |
181 |
} catch (ArrayIndexOutOfBoundsException ae) { |
182 |
//on the off chance a name is too long, grow the array. |
183 |
//Shouldn't happen often if at all |
184 |
char[] oldscratch = namescratch; |
185 |
namescratch = new char[end+10]; |
186 |
System.arraycopy (oldscratch, 0, namescratch, 0, oldscratch.length); |
187 |
System.arraycopy(clazzext, 0, namescratch, nlen, 6); |
188 |
} |
189 |
//allocate the strings |
190 |
String pkg = new String (namescratch,0,idx+1); // "org/netbeans/modules/foo/" |
191 |
String fullname = new String (namescratch,0,end); // "org/netbeans/modules/foo/MyClass.class" |
192 |
//end of string optimization |
193 |
Class c = smartLoadClass(name, fullname, pkg); |
141 |
if(c == null) throw new ClassNotFoundException(name); |
194 |
if(c == null) throw new ClassNotFoundException(name); |
142 |
if (resolve) resolveClass(c); |
195 |
if (resolve) resolveClass(c); |
143 |
return c; |
196 |
return c; |
144 |
} |
197 |
} |
145 |
|
|
|
146 |
/** This ClassLoader can't load anything itself. Subclasses |
198 |
/** This ClassLoader can't load anything itself. Subclasses |
147 |
* may override this method to do some class loading themselves. The |
199 |
* may override this method to do some class loading themselves. The |
148 |
* implementation should not throw any exception, just return |
200 |
* implementation should not throw any exception, just return |
Lines 295-301
Link Here
|
295 |
return super.findResources(name); |
347 |
return super.findResources(name); |
296 |
} |
348 |
} |
297 |
|
349 |
|
298 |
|
|
|
299 |
/** |
350 |
/** |
300 |
* Returns a Package that has been defined by this class loader or any |
351 |
* Returns a Package that has been defined by this class loader or any |
301 |
* of its parents. |
352 |
* of its parents. |
Lines 305-319
Link Here
|
305 |
*/ |
356 |
*/ |
306 |
protected Package getPackage(String name) { |
357 |
protected Package getPackage(String name) { |
307 |
zombieCheck(name); |
358 |
zombieCheck(name); |
308 |
|
359 |
Package pkg=null; |
|
|
360 |
synchronized (packages) { |
361 |
pkg=(Package) packages.get(name); |
362 |
if (pkg != null) return pkg; |
363 |
} |
364 |
//below is the original code for string handling; |
365 |
//the code in the synchronized block following |
366 |
//accomplishes the same thing, but is optimized to |
367 |
//reduce String array copies and is about 40% faster |
368 |
/* |
309 |
int idx = name.lastIndexOf('.'); |
369 |
int idx = name.lastIndexOf('.'); |
310 |
if (idx == -1) return null; |
370 |
if (idx == -1) return null; |
311 |
String spkg = name.substring(0, idx + 1).replace('.', '/'); |
371 |
String spkg = name.substring(0, idx + 1).replace('.', '/'); |
312 |
|
372 |
*/ |
313 |
synchronized (packages) { |
373 |
String spkg; |
314 |
Package pkg = (Package)packages.get(name); |
374 |
int nlen = name.length(); |
315 |
if (pkg != null) return pkg; |
375 |
//is this synchronization necessary? Probably. Works |
316 |
|
376 |
//without it, but that's on a uniprocessor machine. If sure |
|
|
377 |
//it is a non-issue, remove. |
378 |
synchronized (pkgscratch) { |
379 |
try { |
380 |
//load the name into the scratch array |
381 |
name.getChars(0, nlen-1, pkgscratch, 0); |
382 |
} catch (ArrayIndexOutOfBoundsException ae) { |
383 |
//if the array is too small, grow it and try again |
384 |
pkgscratch = new char[nlen+20]; |
385 |
name.getChars(0, nlen-1, pkgscratch, 0); |
386 |
} |
387 |
//start at the end of the array and iterate back until |
388 |
// a '.' is found. |
389 |
int idx=nlen-1; |
390 |
for (; (idx >= 0) && (pkgscratch[idx] != '.'); idx--) { |
391 |
//empty impl-we just want the value of idx |
392 |
} |
393 |
|
394 |
//now iterate the array as far as necessary, replacing |
395 |
//'.' with '/' - we'll set the last char (known) explicitly below |
396 |
try { |
397 |
for (int i=0; i <= idx-5; i+=4) { |
398 |
if (pkgscratch[i] == '.') pkgscratch[i] = '/'; |
399 |
if (pkgscratch[i+1] == '.') pkgscratch[i+1] = '/'; |
400 |
if (pkgscratch[i+2] == '.') pkgscratch[i+2] = '/'; |
401 |
if (pkgscratch[i+3] == '.') pkgscratch[i+3] = '/'; |
402 |
} |
403 |
} catch (ArrayIndexOutOfBoundsException ae2) { |
404 |
//Faint possibility of overflowing |
405 |
//if we need to grow the array, we've got one honkin' big package name |
406 |
char[] oldscratch = pkgscratch; |
407 |
pkgscratch=new char[pkgscratch.length + 20]; |
408 |
System.arraycopy (oldscratch, 0 , pkgscratch, 0, oldscratch.length); |
409 |
for (int n = 0; n < idx; n++) { |
410 |
if (pkgscratch[n] == '.') pkgscratch[n] = '/'; |
411 |
} |
412 |
} |
413 |
//if we're not in the default package, explicitly set the |
414 |
//final trailing slash |
415 |
if (idx >=0) pkgscratch[idx] = '/'; |
416 |
//create the result string |
417 |
spkg = idx == -1 ? "" : new String (pkgscratch, 0, idx+1); |
418 |
} |
419 |
//end of optimized string loading |
420 |
synchronized (packages) { |
317 |
for (int i = 0; i < parents.length; i++) { |
421 |
for (int i = 0; i < parents.length; i++) { |
318 |
ClassLoader par = parents[i]; |
422 |
ClassLoader par = parents[i]; |
319 |
if (par instanceof ProxyClassLoader && shouldDelegateResource(spkg, par)) { |
423 |
if (par instanceof ProxyClassLoader && shouldDelegateResource(spkg, par)) { |