Return-Path: Delivered-To: apmail-tomcat-users-archive@www.apache.org Received: (qmail 10829 invoked from network); 25 Jul 2006 14:03:48 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 25 Jul 2006 14:03:48 -0000 Received: (qmail 18110 invoked by uid 500); 25 Jul 2006 14:03:33 -0000 Delivered-To: apmail-tomcat-users-archive@tomcat.apache.org Received: (qmail 18092 invoked by uid 500); 25 Jul 2006 14:03:33 -0000 Mailing-List: contact users-help@tomcat.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: "Tomcat Users List" Delivered-To: mailing list users@tomcat.apache.org Received: (qmail 18080 invoked by uid 99); 25 Jul 2006 14:03:33 -0000 Received: from asf.osuosl.org (HELO asf.osuosl.org) (140.211.166.49) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 25 Jul 2006 07:03:33 -0700 X-ASF-Spam-Status: No, hits=0.5 required=10.0 tests=DNS_FROM_RFC_ABUSE,SPF_HELO_PASS,SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (asf.osuosl.org: domain of NBelov@abisoft.spb.ru designates 81.222.171.140 as permitted sender) Received: from [81.222.171.140] (HELO mail.abisoft.spb.ru) (81.222.171.140) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 25 Jul 2006 07:03:31 -0700 Received: by mail.abisoft.spb.ru (Postfix, from userid 410) id 6FF2EB6441; Tue, 25 Jul 2006 18:00:15 +0400 (MSD) Received: from nbelov (nbelov.abisoft.spb.ru [172.26.10.49]) by mail.abisoft.spb.ru (Postfix) with ESMTP id 72F95B6366 for ; Tue, 25 Jul 2006 18:00:12 +0400 (MSD) From: "Nikita Belov" To: "'Tomcat Users List'" Subject: RE: JSP class loader Date: Tue, 25 Jul 2006 18:03:04 +0400 Organization: ABISoft MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_NextPart_000_01EF_01C6B014.93A6BB50" X-Mailer: Microsoft Office Outlook, Build 11.0.5510 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1807 Thread-Index: Acas4ReWKcF+JK2iT8+MLZxDrMFxfwDB9WCA In-Reply-To: <44C0FF01.3010603@christopherschultz.net> Message-Id: <20060725140012.72F95B6366@mail.abisoft.spb.ru> X-Spam-Checker-Version: SpamAssassin 3.0.2 on mail.abisoft.spb.ru X-Virus-Checked: Checked by ClamAV on apache.org X-Old-Spam-Flag: NO X-Old-Spam-Status: No, score=-5.9 required=6.9 tests=ALL_TRUSTED,BAYES_00 autolearn=ham version=3.0.2 X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N ------=_NextPart_000_01EF_01C6B014.93A6BB50 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Chris, >> I work on application which allows user to deploy/undeploy large >> number of the JSP pages to AppServer (JBoss 4.03sp1 + Tomcat 5.5). >> Standard Tomcat class loader caches classes for all deployed JSP >> internally and never clean its cache. This brings JVM to PermGen >> overflow error after several days of system work. > >Ouch. Are you saying that the sheer number of classes in your system >is overflowing your memory? Yes. >That doesn't seem likely. > >After tomcat compiles your JSP, it loads the resulting class and >executes it like a servlet. I know. >If you have an option enabled, it will detect updated JSPs, re-compile >them, and reload them. It is certainly possible that when this happens, >Tomcat discards the entire ClassLoader and starts fresh. In that case, >if you have 10,000 JSPs, then each time you reload, you'll get 10,000 >more classes loaded into memory. If this happens enough times, you'll >run out of memory since Java does not clean up old, unused classes in >memory. I have made some research. Looks like JVM unloads classes from PermGen, when classloader instance, used for loading these classes, is destroyed by GC. See program attached to the letter. It simply loads classes from specified dir. This program is intended to be monitored by jconsole. >Is this the behavior you are describing? Yes. >If so, then you can't fix the >problem by writing your own JSP compiler and/or ClassLoader. I guess loading each JSP class by separate classloader instance will fix the problem. Classloader will be created when HTTP request recived and no one reference on this classloader instance will be stored during request processing, so it can be destroyed by GC. >Your best bet is not to modify your JSPs and have them re-loaded. > >Is this in a development setting or production? I would say that >having JSP reloading turned on in production is a mistake. I am working on system for business processes processing. Each business process can be deployed and launched by user many times. Business process can contain JSP(JSF) pages, also it can contain Java-scriplets (POJO classes) with business logic. Each scriplet is loaded with separate classloader and therefore successfully unloaded from PermGen when classloader destroyed. All JSP classes are loaded by the one Tomcat classloader and can't be unloaded from memory. This is the problem. Any ideas? -- Nikita ------=_NextPart_000_01EF_01C6B014.93A6BB50 Content-Type: text/java; name="JTest.java" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="JTest.java" import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.util.ArrayList; public class JTest { =09 /** * Load class from specified dir */ private static class SimpleClassLoader extends ClassLoader { private String classPath =3D null; =09 public SimpleClassLoader(String classPath) { this.classPath =3D classPath; } =20 private byte[] loadClassData(File f) throws IOException { FileChannel in =3D new FileInputStream(f).getChannel(); ByteBuffer buf =3D ByteBuffer.allocate((int) in.size()); in.read(buf); in.close(); return buf.array(); } public Class findClass(String name) throws ClassNotFoundException { try { System.out.println("Loading " + name); String classFileName =3D name.replace('.', '/') + ".class"; byte[] buf =3D loadClassData(new File(classPath, classFileName)); return defineClass(name, buf, 0, buf.length); } catch (Exception e) { throw new ClassNotFoundException(name); } } } // Any directory with large number of classes. private final static String CLASS_PATH =3D "C:\\Trash\\cp"; =09 private static ArrayList clArr =3D new ArrayList(); =09 /** * Recursively load classes from CLASS_PATH dir and its subdirs */ static void loadClasses(File dir, String pak) throws Exception { File[] files =3D dir.listFiles(); if (files !=3D null) { for (int i =3D 0; i < files.length; i++) { if (files[i].isDirectory()) { loadClasses(files[i], pak + files[i].getName() + "."); } else { String fname =3D files[i].getName(); fname =3D fname.substring(0, fname.indexOf('.')); SimpleClassLoader classLoader =3D new = SimpleClassLoader(CLASS_PATH); classLoader.loadClass(pak + fname); =09 // uncomment following line to disallow GC finalize=20 // SimpleClassLoader instances and free PermGen=20 //clArr.add(classLoader); =09 Thread.sleep(50); // for better visualization } } } } =20 public static void main(String[] args) throws Exception { System.out.println("Start"); Thread.sleep(10000); // timeout to start jconsole =09 System.out.println("Begin classes loading"); loadClasses(new File(CLASS_PATH), ""); System.out.println("Classes loading completed"); =20 Thread.sleep(60000); // use "Perform GC" in jconsole to try to free = PermGen System.out.println("Finish"); } =20 } ------=_NextPart_000_01EF_01C6B014.93A6BB50 Content-Type: text/plain; charset=us-ascii --------------------------------------------------------------------- To start a new topic, e-mail: users@tomcat.apache.org To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org For additional commands, e-mail: users-help@tomcat.apache.org ------=_NextPart_000_01EF_01C6B014.93A6BB50--