Another speed optimization in ReflectiveEnvironment#isPackage()
authorJan Vrany <jan.vrany@fit.cvut.cz>
Fri, 25 Jul 2014 09:23:02 +0100
changeset 3177 79cde29be713
parent 3176 243dcc6b3220
child 3181 19acb606dd69
Another speed optimization in ReflectiveEnvironment#isPackage() Defer .jar scanning at laters possible moment.
tools/java/src/stx/libjava/tools/environment/ReflectiveEnvironment.java
--- 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;
 	}