3

How does class-reloading works in Tomcat when it comes to reloading JSPs (I am talking about the internal architecture)?

I know that each JSP is compiled to a Java class. But how does the classloader (which is unique per web application) reload these generated classes given that a classloader does not allow class unloading and without collecting too much garbage?

Ion Ionascu
  • 552
  • 1
  • 4
  • 15
  • 2
    I would disagree on "without collecting too much garbage", because Tomcat is known for its running out of memory after a few hot re-deploys. – maksimov Jun 07 '12 at 14:49
  • Yes, @maksimov, you are right. Maybe I should also add a question to ask what is Tomcat's strategy for reducing the probability of getting an out of memory error. – Ion Ionascu Jun 07 '12 at 14:58
  • 1
    Some information on [Tomcat](http://tomcat.apache.org/tomcat-5.5-doc/jasper-howto.html). Interesting to know they are using ECJ incremental compiler for their JSP compilation. – maksimov Jun 07 '12 at 15:22
  • 1
    @maksimov Tomcat is not known for running out of memory after a few hot-deploys. Instead, many web applications are poorly written and lots of them run on Tomcat instances. A properly-written web application can be re-deployed hundreds of times without restarting Tomcat and without running out of memory. – Christopher Schultz Jun 07 '12 at 19:09
  • @ChristopherSchultz I won't argue as it might be the case with it running through Eclipse only - in my experience and in others' (Google helps here). I understand it may well be due to different process and method of execution, but still - the issue is there. – maksimov Jun 08 '12 at 08:26
  • [Issue in more detail](http://stackoverflow.com/a/473053/211197) – maksimov Jun 08 '12 at 14:04
  • Tomcat discards its WebappClassLoader when an application is stopped and does not retain references to it. There are a number of application-related behaviors that can cause the WebappClassLoader (and all classes related to it) to remain in memory until the PermGen (in a HotSpot JVM) is exhausted. There are even some API behaviors (and some in each JVM vendor's core Java classes) that can cause this kind of thing to happen. – Christopher Schultz Jun 08 '12 at 20:51
  • You can locate these problems using a procedure like this: http://people.apache.org/~markt/presentations/2010-08-05-Memory-Leaks-JavaOne-60mins.pdf. If you find the problem in an API you use, notify the author and have them fix it. If it's in the JVM, you can use Tomcat's JreMemoryLeakPreventionListener to avoid those kinds of things. If it's in your webapp, when then you just have to go fix it. But don't just go around blaming Tomcat. – Christopher Schultz Jun 08 '12 at 20:53
  • I think Tomcat must discard the instance of WebappClassLoader when the application is stopped as this is required by Java EE specifications which require each web app (and enterprise app) to use its own classloader. – Ion Ionascu Jun 08 '12 at 21:08

3 Answers3

2

A JasperLoader instance is the classloader loads jsp generated servlets.

The jsp compiler "throw away" (set to null) the old JasperLoader instance when it generates a newer servlet class file.

Quote from the comments in JspServletWrapper.setServletLastModifiedTime:

Really need to unload the old class but can't do that. Do the next best thing which is throw away the JspLoader so a new loader will be created which will load the new class.

See also where this method is called after compiling.

acala
  • 332
  • 3
  • 11
0

Read the code if you want an education.

Start here: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/jasper/servlet/JspServlet.java?view=markup

Christopher Schultz
  • 20,221
  • 9
  • 60
  • 77
  • I've already checked the code. But, what I do not understand is: In Java, each class-loader has a list of loaded classes (see the private property classes in ClassLoader). The method addClass is the only one that adds a class to this property and it is invoked by the JVM. This way, each Class object has at least on reference to it and without reflection, a custom classloader cannot remove this reference. From what I know, the idea in Java is to force the GC to unload a class only after it unloads the classloader that loaded it in the first place. – Ion Ionascu Jun 08 '12 at 11:41
  • (continued) I've checked how Tomcat loads classes I can't find a reference to the property classes from ClassLoader. So, my understanding is that a class is actually never unloaded once it has been loaded. So, in the end, this should cause a memory related error. And I am curious what Tomcat does not to get here. – Ion Ionascu Jun 08 '12 at 11:41
0

The standard Java class loader never unloads a class. Tomcat has its own class loaders, which can replace an old instance of a class with a new instance, and then orphans the old instance, making it available to the garbage collector in the usual manner.

Somewhere along the line I read that if a class is not used for some specified period of time, Tomcat will unload it. But I can't find any reference for that at the moment.

Jay
  • 26,876
  • 10
  • 61
  • 112