Another speed optimization in ReflectiveEnvironment#isPackage()
Defer .jar scanning at laters possible moment.
--- a/tools/java/src/stx/libjava/tools/environment/ReflectiveEnvironment.java Fri Jul 25 01:52:23 2014 +0100
+++ b/tools/java/src/stx/libjava/tools/environment/ReflectiveEnvironment.java Fri Jul 25 09:23:02 2014 +0100
@@ -12,7 +12,6 @@
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;
-import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
@@ -187,24 +186,32 @@
*/
@SuppressWarnings("unchecked")
public boolean isPackage(String packageName, ClassLoader loader) {
+ // Primordial class loader, consult boot class path.
if (loader == null) {
return isPackage(packageName, sun.misc.Launcher.getBootstrapClassPath().getURLs());
}
+ // Ask parent class loader...
+ if (isPackage(packageName, loader.getParent())) {
+ return true;
+ }
+ // Check loaded classes...
if (FIELD_ClassLoader_Classes != null) {
int packageNameLen = packageName.length();
Vector<Class<?>> classes;
try {
classes = (Vector<Class<?>>)FIELD_ClassLoader_Classes.get(loader);
- Iterator<Class<?>> i = classes.iterator();
- while (i.hasNext()) {
- String className = i.next().getName();
- int classNameLen = className.length();
- if ((classNameLen > packageNameLen) &&
- (className.charAt(packageNameLen) == '.') &&
- (className.startsWith(packageName))) {
- return true;
- }
- }
+ if (classes.size() > 0) {
+ Iterator<Class<?>> i = classes.iterator();
+ while (i.hasNext()) {
+ String className = i.next().getName();
+ int classNameLen = className.length();
+ if ((classNameLen > packageNameLen) &&
+ (className.charAt(packageNameLen) == '.') &&
+ (className.startsWith(packageName))) {
+ return true;
+ }
+ }
+ }
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
}
@@ -216,7 +223,7 @@
return true;
}
}
- return isPackage(packageName, loader.getParent());
+ return false;
}
/**
@@ -233,58 +240,73 @@
} else {
packagePathNative = packageName.replace('.', File.separatorChar);
}
- for (int i = 0; i < classpath.length; i++) {
- URL url = classpath[i];
- if (url.getProtocol().equals("file")) {
- File file = new File(url.getPath());
- if (file.isDirectory()) {
- if ((new File(file, packagePathNative)).isDirectory()) {
- return true;
- }
- } else {
- ZipFile zip = null;
- try {
- try {
- zip = new ZipFile(file);
- if (DEBUG_isPackage) {
- System.err.println("checking jar: " + file.getName());
- }
- /* try to short-circuit: look for .class file assuming
- * packageName is actually class name. If found, return
- * false (it is a class, not a package)
- */
- if (zip.getEntry(packagePathSlashed + ".class") != null) {
- return true;
- }
- Enumeration<? extends ZipEntry> entries = zip.entries();
- while (entries.hasMoreElements()) {
- String entryName = entries.nextElement().getName();
- int entryNameLen = entryName.length();
- if (DEBUG_isPackage) {
- System.err.println("checking jar entry: " + entryName);
- }
-
- if ((entryNameLen > packageNameLen) &&
- (entryName.charAt(packageNameLen) == '/') &&
- (entryName.startsWith(packagePathSlashed))) {
- return true;
- }
- }
- if (DEBUG_isPackage) {
- System.err.println();
- System.err.println();
- }
- } finally {
- if (zip != null) {
- zip.close();
- }
- }
- } catch (ZipException e) {
- } catch (IOException e) {
- }
- }
- }
+ ZipFile[] zips = new ZipFile[classpath.length];
+
+ try {
+ // Pass 1 - quick check for directories and zip files
+ for (int i = 0; i < classpath.length; i++) {
+ URL url = classpath[i];
+ if (url.getProtocol().equals("file")) {
+ File file = new File(url.getPath());
+ if (file.isDirectory()) {
+ if ((new File(file, packagePathNative)).isDirectory()) {
+ return true;
+ }
+ } else {
+ ZipFile zip = null;
+ try {
+
+ zip = new ZipFile(file);
+ if (DEBUG_isPackage) System.err.println("checking jar: " + file.getName());
+ /*
+ * try to short-circuit: look for .class file assuming
+ * packageName is actually class name. If found, return
+ * false (it is a class, not a package)
+ */
+ if (zip.getEntry(packagePathSlashed + ".class") != null) {
+ return false;
+ } else {
+ zips[i] = zip;
+ }
+ } catch (ZipException e) {
+ } catch (IOException e) {
+ }
+ }
+ }
+ }
+
+ // Pass 2 - full scan of zip files
+ for (int i = 0; i < zips.length; i++) {
+ ZipFile zip = zips[i];
+ if (zip != null) {
+ Enumeration<? extends ZipEntry> entries = zip.entries();
+ while (entries.hasMoreElements()) {
+ String entryName = entries.nextElement().getName();
+ int entryNameLen = entryName.length();
+ if (DEBUG_isPackage) {
+ System.err.println("checking jar entry: " + entryName);
+ }
+
+ if ((entryNameLen > packageNameLen) &&
+ (entryName.charAt(packageNameLen) == '/') &&
+ (entryName.startsWith(packagePathSlashed))) {
+ return true;
+ }
+ }
+ }
+ }
+ } finally {
+ for (int i = 0; i < zips.length; i++) {
+ ZipFile zip = zips[i];
+ if (zip != null) {
+ try {
+ zip.close();
+ } catch (IOException e) {
+ }
+ }
+ }
}
+
return false;
}