One issue I have come across is the usage of String concatenation. As far as I've understood, those are never removed from memory.
It is only Strings that are intern()ed that are hard to get rid of - servlet apps constantly build temporary Strings that are disposed like any other object.
Threads that are created but never properly terminated can indeed eventually crash a system but most apps dont create extra Threads.
The servlet container should be able to serialize large session objects out to disk when needed and delete them when the session is invalidated - it is object kept in collections NOT managed by the container that can build up.
Use arrays instead of ArrayList - what a bizarre idea - use either as appropriate, just be sure to discard when finished.
Pass minimum data! Good point - be especially careful with the objects that the container manages such as request and response objects - keeping references to these beyond a single request/response cycle is very very dangerous.
Bill