1. glassfish
  2. GLASSFISH-3963

Tag-file classes get loaded for each JSP leading to PermGen space problem


    • Type: Bug Bug
    • Status: Open
    • Priority: Minor Minor
    • Resolution: Unresolved
    • Affects Version/s: 9.1peur1
    • Fix Version/s: not determined
    • Component/s: web_container
    • Labels:
    • Environment:

      Operating System: All
      Platform: All

    • Issuezilla Id:


      Here is a problem described on apache tomcat dev list. GF also suffers from it.

      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 a few thousand
      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

      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

      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".

      Loading each JSP 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), there is no need for a new ClassLoader for each JSP/tag.

      Related apache tomcat bug:

      Steps to reproduce:
      1. Create firstTag.tag as shown below under <anyapp>/WEB-INF/tags:

      <%@ tag import="java.util.Date"
      DateFormat dateFormat =
      Date now = new Date(System.currentTimeMillis());

      2. Create 1.jsp, 2.jsp as shown below under <anyapp> directory.

      <%@ taglib prefix="easy"
      tagdir="/WEB-INF/tags" %>
      In 1.jsp: Today is <easy:firstTag/>

      <%@ taglib prefix="easy"
      tagdir="/WEB-INF/tags" %>
      In 2.jsp: Today is <easy:firstTag/>

      3) Set the JVM option "-XX:+TraceClassLoading -XX:+TraceClassUnloading" in
      domain.xml and access 1.jsp and 2.jsp.

      You will see that the the firstTag_tag class is loaded for each JSP the tag is
      placed on. This is true even when the 'development' is set to 'false' and/or
      'reload-interval' is set to '-1' in default-web.xml.

      Suggested fix for PWC1.2 branch:

      Index: org/apache/jasper/
      RCS file:
      retrieving revision
      diff -u -r1.9.6.4
      — org/apache/jasper/ 27 Mar 2007 17:23:37 -0000
      +++ org/apache/jasper/ 4 Jan 2008 00:45:29 -0000
      @@ -638,11 +638,7 @@

      public ClassLoader getJspLoader() {

      • return new JasperLoader(new URL[] {baseUrl},
        - getClassLoader(),
        - rctxt.getPermissionCollection(),
        - rctxt.getCodeSource(),
        - rctxt.getBytecodes());
        + return rctxt.getJspLoader(baseUrl, getClassLoader());

        public void makeOutputDir() { Index: org/apache/jasper/compiler/ =================================================================== RCS file: /cvs/glassfish/appserv-webtier/src/java/org/apache/jasper/compiler/,v retrieving revision diff -u -r1.7.6.3 --- org/apache/jasper/compiler/ 11 Jan 2007 08:39:04 -0000 +++ org/apache/jasper/compiler/ 4 Jan 2008 00:45:29 -0000 @@ -58,6 +58,7 @@ import org.apache.jasper.runtime.JspFactoryImpl; import; import org.apache.jasper.servlet.JspServletWrapper; +import org.apache.jasper.servlet.JasperLoader; /** * Class for tracking JSP compile time file dependencies when the @@ -193,6 +194,7 @@ private ServletContext context; private Options options; private URLClassLoader parentClassLoader; + private JasperLoader jspLoader; private PermissionCollection permissionCollection; private CodeSource codeSource; private String classpath; @@ -440,6 +442,23 @@ }

        + * Obtain the classloader to use when loading JSP resources. In development
        + * mode, each JSP has a separate classloader to enable easy re-loading of
        + * modified JSPs. If not in development mode, a single loader is used to
        + * reduce perm gen usage when many JSPs all use the same tags.
        + */
        + public URLClassLoader getJspLoader(URL baseUrl, ClassLoader parent) {
        + if (options.getDevelopment() || jspLoader == null) {
        + jspLoader = new JasperLoader(new URL[] {baseUrl}

        + parent,
        + permissionCollection,
        + codeSource,
        + bytecodes);
        + }
        + return jspLoader;
        + }
        + /**

      • Method used to initialize classpath for compiles.
        private void initClassPath() {



          • Assignee:
          • Votes:
            1 Vote for this issue
            3 Start watching this issue


            • Created: