OutOfMemory can happen in two scenarios:
1. You have leakage in your code
2. The JVM garbage collector paused
To solve the problem, do a stress testing on your application to find out how long it will take for the JVM to capture the OutOfMemory excpetion. Then change the JVM generational collector(for garbage collection) to the other three models provided by your Sun JVM. Tune some of the parameters, see if you can still get this exception. If you still get it, then you need to do some memory profiling. The commercial tools are all too generic, it is not easy to find out the leakage. A simple method is instantiate a WeakHashmap object, and add all you application related java collection objects to this weak hashmap, add a timer task to print out memory footprint(the objects and each object size in the hashmap), analyze the result, you should be able to find the leakage. If there is no leakage in the collection objects, add other application initiated objects to the hashmap for analysis.
If you have less than 50 aggressive threads in your application, chances are you have leakage in your code.