Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Note about MetaSpae instead of PermGen

...

  • A servlet trying to load a several GBytes file into memory will surely kill the server. These kind of errors must be considered a simple bug in our program.
  • To compensate for the data your servlet tries to load, you increase the heap size so that there is no room to create the stack size for the threads that need to be created. The memory required by each thread will vary by OS but can be as high as 2M by default and in some OS's (like Debian Sarge) is not reducible with the -Xss parameter. Rule of Thumb, use no more than 1G for heap space in a 32-bit web application.
  • Deep recursive algorithms can also lead to Out Of Memory problems. In this case, the only fixes are increasing the thread stack size (-Xss), or refactoring the algorithms to reduce the depth, or the local data size per call.
  • A webapp that uses lots of libraries with many dependencies, or a server maintaining lots of webapps could exhauste the JVM PermGen space. This space is where the VM stores the classes and methods data. In those cases, the fix is to increase this size. The Sun VM has the flag -XX:MaxPermSize that allows to set its size (the default value is 64M)

    Info

    PermGen has been integrated into a new concept called MetaSpace from Java 8 on. The old setting will generate a warning and will be ignored by newer JVMs.


  • Hard references to classes can prevent the garbage collector from reclaiming the memory allocated for them when a ClassLoader is discarded. This will occur on JSP recompilations, and webapps reloads. If these operations are common in a webapp having these kinds of problems, it will be a matter of time, until the PermGen space gets full and an Out Of Memory is thrown.

...

Any threads a web application starts, a web application should stop. ServletContextListener is your friend. Note Tomcat 7 will warn you if you do this and will also provide a (highly dangerous - use at your own risk) option to terminate the threads.

DriverManager

If you load a java.sql.Driver in your own classloader (or servlets), the driver should be removed before undeploying. Each driver is registered in DriverManager which is loaded in system classloader and references the local driver. Note Tomcat will do this for you if you forget.

No Format
                Enumeration<Driver> drivers = DriverManager.getDrivers();
		ArrayList<Driver> driversToUnload=new ArrayList<Driver>();
		while (drivers.hasMoreElements()) {
			Driver driver = drivers.nextElement();
			if (driver.getClass().getClassLoader().equals(getClass().getClassLoader())) {
				driversToUnload.add(driver);
			}
		}
		for (Driver driver : driversToUnload) {
	            DriverManager.deregisterDriver(driver);
                }

ThreadLocal

The lifecycle of a ThreadLocal should match that of a request. There is no guarantee that a thread will ever be used to process a request again so if a ThreadLocal is left on the thread at the end of the request there may be no opportunity for the web application to clean it up. Note Tomcat 7 will do this for you.

ContextClassLoader

There are various parts of the Java API that retain a permanent reference to the context class loader. If this happens to be a web application class loader then a memory leak will occur. Tomcat provides workarounds for these where known but there are undoubtedly others.

...