Hi Because i like to play Java detective, i have made this simple test with T 5.1
- Put enough permgen space to let jetty run and my index page work - Simply touch and reload the index page Index page is made of five @Property and five @Persist After 12 touch, i reach the Permgen out of memory exception Using 'jstat -class' i observed that the number of kb of classes loaded follows a linear expansion after each touch. Don't you think this is a possible memory leak ? I can understand that the number of classes explodes due to the usage of anonymous inner classes but they should be garbage collected when the page instance get released. 2010/4/29 Howard Lewis Ship <[email protected]> > Calls to TransformField.getAccess() or TransformMethod.addAdvice() > (and many others) will often create one or more new classes behinds > the scenes. ComponentClassTransformWorkers make use of such methods. > > > > On Thu, Apr 29, 2010 at 10:33 AM, Christophe Cordenier > <[email protected]> wrote: > > After going into Tapestry core and ioc code i have seen this comment. I > > thought a fresh view on the problem should help, but it's clear that the > > Tapestry community knows its subject deeply. > > > > It keeps on impressing me !! > > It's not like its a-priori knowlege; people hit obscure bugs, often do > the research and provide a patch. I think most of the detective work > on this one was provided by a user. The code base gains experience. > > I've found that web apps are easy up to a point, then you cross a line > and things become much more complicated. Tapestry exists to push that > "line" way, way out ... but it means there's a lot of code and > machinery employed on simple things so that everything continues to > work once you pass the complexity threshold. > > Often that complexity represents various cross-cutting concerns. > > For example, I was just working on a logout link. The trick is, some > pages allow anonymous access, and some don't. Once logged out, the > code has to determine whether to stay on the current page or go to a > new page. > > In an action/view framework, you would have to probably provide a new > parameter to the "component" that renders the logout link, and > manually configure it with where to go after logging out. That's > because a view does not have insight into the action that triggered it > (partially because a view can potentially have a one-to-many > relationship with actions). Thus, the developer has to take on this > bit of complexity ... made more complex in the case where the URL must > incorporate additional data. In Tapestry, that would be a page > activation context, but in a traditional app it could be anything > (extra path or query parameters). > > The point is, my code ends up looking like: > > Object onActionFromLogout() { > authenticationService.logout(); > > Component page = resources.getPage(); > > boolean canAccessCurrentPageAnonymously = page.getClass() > .isAnnotationPresent(AnonymousAccess.class); > > return canAccessCurrentPageAnonymously ? page : > Landing.class; > } > > And Tapestry handles the rest; it has already handled the logic about > encoding into the URL that triggers this method that identity of the > page and the activation context for that page. > > > > > /** > > * This is, of course, a bit of a problem. We don't have an avenue for > > ensuring that this ThreadLocal is destroyed > > * at the end of the request, and that means a thread can hold a > > reference to the class and the class loader which > > * loaded it. This may cause redeployment problems (leaked classes and > > class loaders). Apparently JDK 1.6 provides > > * the APIs to check to see if the current thread has a read lock. So, > > we tend to remove the TL, rather than set its > > * value to false. > > */ > > private static class ThreadBoolean extends ThreadLocal<Boolean> > > { > > @Override > > protected Boolean initialValue() > > { > > return false; > > } > > } > > > > 2010/4/29 Christophe Cordenier <[email protected]> > > > >> Thanks for clarification. > >> > >> But If i have well understood, a permgen out of memory indicates that we > >> have too many classes loaded by the classloader. > >> > >> After going through the different Workers, I don't see where Tapestry > >> creates more classes than before. At most there is two/three advisors > per > >> Worker. > >> > >> I must miss something ? > >> > >> 2010/4/29 Howard Lewis Ship <[email protected]> > >> > >>> When coding (not meta-coding) Java, using static inner classes rather > >>> > >>> than instance inner classes (including anonymous inner classes) is > >>> more efficient, as the inner class instance does not need to hold a > >>> reference to the enclosing object. That's probably what PMD was > >>> getting on about; an inner class can be a memory leak of the enclosing > >>> object if the enclosing object is not needed anymore. > >>> > >>> On Thu, Apr 29, 2010 at 8:07 AM, Christophe Cordenier > >>> <[email protected]> wrote: > >>> > Hi > >>> > > >>> > 2010/4/29 Thiago H. de Paula Figueiredo <[email protected]> > >>> > > >>> >> On Thu, 29 Apr 2010 11:18:55 -0300, Christophe Cordenier < > >>> >> [email protected]> wrote: > >>> >> > >>> >> Is it not possible to use static inner class with constructors > instead > >>> of > >>> >>> using anonymous inner classes ? > >>> >>> Won't this solve a part of the problem ? > >>> >>> > >>> >> > >>> >> I don't think so, as the problem is not how the classes are created, > >>> but > >>> >> the number of them. > >>> >> > >>> >> > >>> > Yes i have well understood this, it's just that i was remembering a > rule > >>> > (PMD or Findbug) that told me to turn some of my inner classes to > static > >>> for > >>> > the one who do not access to the enclosing class, maybe it's just to > >>> have a > >>> > clean coding style. > >>> > > >>> > Also i don't know exactly how the JVM handles anonymous classes, > every > >>> new > >>> > ComponentMethodAdvice() { ... } ? > >>> > >>> This is Tapestry; to add advice to component method it splits the > >>> method into two and creates a new implementation of the > >>> ComponentMethodInvocation interface that is used to track parameter > >>> values, return values, and thrown exceptions, along with the stack of > >>> method advice. > >>> > >>> > > >>> > > >>> >> -- > >>> >> Thiago H. de Paula Figueiredo > >>> >> Independent Java, Apache Tapestry 5 and Hibernate consultant, > >>> developer, > >>> >> and instructor > >>> >> Owner, Ars Machina Tecnologia da Informação Ltda. > >>> >> http://www.arsmachina.com.br > >>> >> > >>> >> > >>> >> > --------------------------------------------------------------------- > >>> >> To unsubscribe, e-mail: [email protected] > >>> >> For additional commands, e-mail: [email protected] > >>> >> > >>> >> > >>> > > >>> > > >>> > -- > >>> > Regards, > >>> > Christophe Cordenier. > >>> > > >>> > Developer of wooki @wookicentral.com > >>> > > >>> > >>> > >>> > >>> -- > >>> Howard M. Lewis Ship > >>> > >>> Creator of Apache Tapestry > >>> > >>> The source for Tapestry training, mentoring and support. Contact me to > >>> learn how I can get you up and productive in Tapestry fast! > >>> > >>> (971) 678-5210 > >>> http://howardlewisship.com > >>> > >>> --------------------------------------------------------------------- > >>> To unsubscribe, e-mail: [email protected] > >>> For additional commands, e-mail: [email protected] > >>> > >>> > >> > >> > >> -- > >> Regards, > >> Christophe Cordenier. > >> > >> Developer of wooki @wookicentral.com > >> > > > > > > > > -- > > Regards, > > Christophe Cordenier. > > > > Developer of wooki @wookicentral.com > > > > > > -- > Howard M. Lewis Ship > > Creator of Apache Tapestry > > The source for Tapestry training, mentoring and support. Contact me to > learn how I can get you up and productive in Tapestry fast! > > (971) 678-5210 > http://howardlewisship.com > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [email protected] > For additional commands, e-mail: [email protected] > > -- Regards, Christophe Cordenier. Developer of wooki @wookicentral.com
