tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From r...@apache.org
Subject cvs commit: jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/loader WebappClassLoader.java WebappLoader.java
Date Sun, 15 Jun 2003 07:22:16 GMT
remm        2003/06/15 00:22:16

  Modified:    catalina/src/share/org/apache/catalina/loader
                        WebappClassLoader.java WebappLoader.java
  Log:
  - Add a machanism to release JAR objects periodically.
  - This should decrease classloading performance because of a big sync block
    during JAR access, but lookup of previously loaded class will behave the same as before.
  - Add a workaround for JAR locking with XML processing and getResource.
    If the resource was loaded from a JAR, it will be extracted as needed to the
    work directory.
  
  Revision  Changes    Path
  1.17      +163 -59   jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/loader/WebappClassLoader.java
  
  Index: WebappClassLoader.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/loader/WebappClassLoader.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- WebappClassLoader.java	12 Jun 2003 22:02:12 -0000	1.16
  +++ WebappClassLoader.java	15 Jun 2003 07:22:16 -0000	1.17
  @@ -61,6 +61,7 @@
   package org.apache.catalina.loader;
   
   import java.io.File;
  +import java.io.FileOutputStream;
   import java.io.FilePermission;
   import java.io.InputStream;
   import java.io.ByteArrayInputStream;
  @@ -285,6 +286,12 @@
   
   
       /**
  +     * Last time a JAR was accessed.
  +     */
  +    protected long lastJarAccessed = 0L;
  +
  +
  +    /**
        * The list of local repositories, in the order they should be searched
        * for locally loaded classes or resources.
        */
  @@ -348,6 +355,12 @@
   
   
       /**
  +     * Path where resources loaded from JARs will be extracted.
  +     */
  +    private File loaderDir = null;
  +
  +
  +    /**
        * The PermissionCollection for each CodeSource for a web
        * application context.
        */
  @@ -534,6 +547,14 @@
       }
   
   
  +    /**
  +     * Change the work directory.
  +     */
  +    public void setWorkDir(File workDir) {
  +        this.loaderDir = new File(workDir, "loader");
  +    }
  +
  +
       // ------------------------------------------------------- Reloader Methods
   
   
  @@ -977,15 +998,18 @@
           }
   
           // Looking at the JAR files
  -        for (i = 0; i < jarFilesLength; i++) {
  -            JarEntry jarEntry = jarFiles[i].getJarEntry(name);
  -            if (jarEntry != null) {
  -                try {
  -                    String jarFakeUrl = getURI(jarRealFiles[i]).toString();
  -                    jarFakeUrl = "jar:" + jarFakeUrl + "!/" + name;
  -                    result.addElement(new URL(jarFakeUrl));
  -                } catch (MalformedURLException e) {
  -                    // Ignore
  +        synchronized (jarFiles) {
  +            openJARs();
  +            for (i = 0; i < jarFilesLength; i++) {
  +                JarEntry jarEntry = jarFiles[i].getJarEntry(name);
  +                if (jarEntry != null) {
  +                    try {
  +                        String jarFakeUrl = getURI(jarRealFiles[i]).toString();
  +                        jarFakeUrl = "jar:" + jarFakeUrl + "!/" + name;
  +                        result.addElement(new URL(jarFakeUrl));
  +                    } catch (MalformedURLException e) {
  +                        // Ignore
  +                    }
                   }
               }
           }
  @@ -1052,6 +1076,33 @@
           // (2) Search local repositories
           url = findResource(name);
           if (url != null) {
  +            // Locating the repository for special handling in the case 
  +            // of a JAR
  +            ResourceEntry entry = (ResourceEntry) resourceEntries.get(name);
  +            FileOutputStream os = null;
  +            try {
  +                String repository = entry.codeBase.toString();
  +                if (repository.endsWith(".jar")) {
  +                    // Copy binary content to the work directory if not present
  +                    File resourceFile = new File(loaderDir, name);
  +                    if (entry.lastModified > resourceFile.lastModified()) {
  +                        resourceFile.getParentFile().mkdirs();
  +                        os = new FileOutputStream(resourceFile);
  +                        os.write(entry.binaryContent);
  +                    }
  +                    url = resourceFile.toURL();
  +                }
  +            } catch (Exception e) {
  +                // Ignore
  +                e.printStackTrace();
  +            } finally {
  +                if (os != null) {
  +                    try {
  +                        os.close();
  +                    } catch (IOException ex) {
  +                    }
  +                }
  +            }
               if (log.isDebugEnabled())
                   log.debug("  --> Returning '" + url.toString() + "'");
               return (url);
  @@ -1454,7 +1505,9 @@
           length = jarFiles.length;
           for (int i = 0; i < length; i++) {
               try {
  -                jarFiles[i].close();
  +                if (jarFiles[i] != null) {
  +                    jarFiles[i].close();
  +                }
               } catch (IOException e) {
                   // Ignore
               }
  @@ -1479,10 +1532,54 @@
       }
   
   
  +    /**
  +     * Used to periodically signal to the classloader to release 
  +     * JAR resources.
  +     */
  +    public void closeJARs(boolean force) {
  +        if (jarFiles.length > 0) {
  +            try {
  +                synchronized (jarFiles) {
  +                    if (force || (System.currentTimeMillis() 
  +                                  > (lastJarAccessed + 90000))) {
  +                        for (int i = 0; i < jarFiles.length; i++) {
  +                            if (jarFiles[i] != null) {
  +                                jarFiles[i].close();
  +                                jarFiles[i] = null;
  +                            }
  +                        }
  +                    }
  +                }
  +            } catch (IOException e) {
  +                log("Failed to close JAR", e);
  +            }
  +        }
  +    }
  +
  +
       // ------------------------------------------------------ Protected Methods
   
   
       /**
  +     * Used to periodically signal to the classloader to release JAR resources.
  +     */
  +    protected void openJARs() {
  +        if (started && (jarFiles.length > 0)) {
  +            lastJarAccessed = System.currentTimeMillis();
  +            if (jarFiles[0] == null) {
  +                try {
  +                    for (int i = 0; i < jarFiles.length; i++) {
  +                        jarFiles[i] = new JarFile(jarRealFiles[i]);
  +                    }
  +                } catch (IOException e) {
  +                    log("Failed to open JAR", e);
  +                }
  +            }
  +        }
  +    }
  +
  +
  +    /**
        * Find specified class in local repositories.
        *
        * @return the loaded class, or null if the class isn't found
  @@ -1692,67 +1789,74 @@
   
           JarEntry jarEntry = null;
   
  -        for (i = 0; (entry == null) && (i < jarFilesLength); i++) {
  +        synchronized (jarFiles) {
   
  -            jarEntry = jarFiles[i].getJarEntry(path);
  +            openJARs();
  +            for (i = 0; (entry == null) && (i < jarFilesLength); i++) {
   
  -            if (jarEntry != null) {
  +                jarEntry = jarFiles[i].getJarEntry(path);
   
  -                entry = new ResourceEntry();
  -                try {
  -                    entry.codeBase = getURL(jarRealFiles[i]);
  -                    String jarFakeUrl = getURI(jarRealFiles[i]).toString();
  -                    jarFakeUrl = "jar:" + jarFakeUrl + "!/" + path;
  -                    entry.source = new URL(jarFakeUrl);
  -                } catch (MalformedURLException e) {
  -                    return null;
  -                }
  -                contentLength = (int) jarEntry.getSize();
  -                try {
  -                    entry.manifest = jarFiles[i].getManifest();
  -                    binaryStream = jarFiles[i].getInputStream(jarEntry);
  -                } catch (IOException e) {
  -                    return null;
  +                if (jarEntry != null) {
  +
  +                    entry = new ResourceEntry();
  +                    try {
  +                        entry.codeBase = getURL(jarRealFiles[i]);
  +                        String jarFakeUrl = getURI(jarRealFiles[i]).toString();
  +                        jarFakeUrl = "jar:" + jarFakeUrl + "!/" + path;
  +                        entry.source = new URL(jarFakeUrl);
  +                        entry.lastModified = jarRealFiles[i].lastModified();
  +                    } catch (MalformedURLException e) {
  +                        return null;
  +                    }
  +                    contentLength = (int) jarEntry.getSize();
  +                    try {
  +                        entry.manifest = jarFiles[i].getManifest();
  +                        binaryStream = jarFiles[i].getInputStream(jarEntry);
  +                    } catch (IOException e) {
  +                        return null;
  +                    }
                   }
  -            }
   
  -        }
  +            }
   
  -        if (entry == null) {
  -            synchronized (notFoundResources) {
  -                notFoundResources.put(name, name);
  +            if (entry == null) {
  +                synchronized (notFoundResources) {
  +                    notFoundResources.put(name, name);
  +                }
  +                return null;
               }
  -            return null;
  -        }
   
  -        if (binaryStream != null) {
  +            if (binaryStream != null) {
   
  -            byte[] binaryContent = new byte[contentLength];
  +                byte[] binaryContent = new byte[contentLength];
   
  -            try {
  -                int pos = 0;
  -                while (true) {
  -                    int n = binaryStream.read(binaryContent, pos,
  -                                              binaryContent.length - pos);
  -                    if (n <= 0)
  -                        break;
  -                    pos += n;
  +                try {
  +                    int pos = 0;
  +
  +                    while (true) {
  +                        int n = binaryStream.read(binaryContent, pos,
  +                                                  binaryContent.length - pos);
  +                        if (n <= 0)
  +                            break;
  +                        pos += n;
  +                    }
  +                    binaryStream.close();
  +                } catch (IOException e) {
  +                    e.printStackTrace();
  +                    return null;
  +                } catch (Exception e) {
  +                    e.printStackTrace();
  +                    return null;
                   }
  -                binaryStream.close();
  -            } catch (IOException e) {
  -                e.printStackTrace();
  -                return null;
  -            } catch (Exception e) {
  -                e.printStackTrace();
  -                return null;
  -            }
   
  -            entry.binaryContent = binaryContent;
  +                entry.binaryContent = binaryContent;
  +
  +                // The certificates are only available after the JarEntry 
  +                // associated input stream has been fully read
  +                if (jarEntry != null) {
  +                    entry.certificates = jarEntry.getCertificates();
  +                }
   
  -            // The certificates are only available after the JarEntry 
  -            // associated input stream has been fully read
  -            if (jarEntry != null) {
  -                entry.certificates = jarEntry.getCertificates();
               }
   
           }
  
  
  
  1.17      +16 -3     jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/loader/WebappLoader.java
  
  Index: WebappLoader.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/loader/WebappLoader.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- WebappLoader.java	22 May 2003 23:04:48 -0000	1.16
  +++ WebappLoader.java	15 Jun 2003 07:22:16 -0000	1.17
  @@ -530,15 +530,18 @@
           return sb.toString();
       }
   
  -    /** Classpath, as set in org.apache.catalina.jsp_classpath context
  +
  +    /** 
  +     * Classpath, as set in org.apache.catalina.jsp_classpath context
        * property
        *
  -     * @return
  +     * @return The classpath
        */
       public String getClasspath() {
           return classpath;
       }
   
  +
       /**
        * Has the internal repository associated with this Loader been modified,
        * such that the loaded classes should be reloaded?
  @@ -551,6 +554,14 @@
   
   
       /**
  +     * Used to periodically signal to the classloader to release JAR resources.
  +     */
  +    public void closeJARs(boolean force) {
  +        classLoader.closeJARs(force);
  +    }
  +
  +
  +    /**
        * Remove a property change listener from this component.
        *
        * @param listener The listener to remove
  @@ -969,6 +980,8 @@
   
           if( log.isDebugEnabled()) 
               log.debug(sm.getString("webappLoader.deploy", workDir.getAbsolutePath()));
  +
  +        classLoader.setWorkDir(workDir);
   
           DirContext resources = container.getResources();
   
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-dev-help@jakarta.apache.org


Mime
View raw message