Hello Tomcat (Jasper) developers, in our project we have a serious memory problem (perm gen space) related to JSP tag files: The class generated from the tag file gets loaded for every JSP the tag is placed on. So if you put such a tag on i.e. 8000 JPSs, the tag class will seriously pollute the perm gen space. The problem gets even worse, if you have a great number of tags used nearly on every singe page. (You can trace class loading by starting the VM with the options "-XX:+TraceClassLoading -XX:+TraceClassUnloading" and see what I mean).
I traced down the problem in the Jasper sources and found out that even though the container is configured not to re-load JSPs, a new instance of a JspCompilationContext is used for every JSP. This JspCompilationContext holds a reference to a JasperLoader (which is null in the beginning and a new instance is created by the JspCompilationContext on demand). Thus a new JasperLoader (=a new ClassLoader) is used for every JSP. As tagfiles of tags placed on this JSP get loaded via the same ClassLoader as the JSP, the class of the same tag placed on different JSPs gets loaded via different ClassLoaders. There is no problem with Java-coded tags, as those get loaded by the parent class loader and the JasperLoaders delegate to it's parent if the class-name does not start with "org.apache.jsp". I perfectly understand that loading each JSPs via a different ClassLoader is necessary if you want to be able to reload the JSP-class, but if the reloading-feature is turned off (development=false), I don't see the need for a new ClassLoader for each JSP/tag. It's the first time I took a look into the Tomcat sources and surely I've missed an important point, so please excuse my silly question: But wouldn't it be possible to re-use the ClassLoader if reloading is turned off? I attached a simple (dirty hack) patch to illustrate what I mean. (I don't think a static map is really a good idea here, but it a first shot to show you what I mean) I've already filed a bugreport for this some days ago: http://issues.apache.org/bugzilla/show_bug.cgi?id=43878 christoph
Index: java/org/apache/jasper/JspCompilationContext.java =================================================================== --- java/org/apache/jasper/JspCompilationContext.java (Revision 602816) +++ java/org/apache/jasper/JspCompilationContext.java (Arbeitskopie) @@ -25,6 +25,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import javax.servlet.ServletContext; import javax.servlet.jsp.tagext.TagInfo; @@ -91,6 +92,9 @@ protected boolean protoTypeMode; protected TagInfo tagInfo; protected URL tagFileJarUrl; + + protected static Map<String, URLClassLoader> contextName2jspLoader = + new ConcurrentHashMap<String, URLClassLoader>(); // jspURI _must_ be relative to the context public JspCompilationContext(String jspUri, @@ -176,11 +180,22 @@ public ClassLoader getJspLoader() { if( jspLoader == null ) { - jspLoader = new JasperLoader - (new URL[] {baseUrl}, - getClassLoader(), - rctxt.getPermissionCollection(), - rctxt.getCodeSource()); + + jspLoader = contextName2jspLoader.get(context.getServletContextName()); + + if (jspLoader == null) { + jspLoader = new JasperLoader + (new URL[] {baseUrl}, + getClassLoader(), + rctxt.getPermissionCollection(), + rctxt.getCodeSource()); + if (!this.options.getDevelopment()) { + contextName2jspLoader.put(context.getServletContextName(), jspLoader); + } + } + + + } return jspLoader; }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]