I am developing a web app that runs on a Tomcat server but the server keeps getting killed because of memory usage, and I have no idea what is wrong.
The server itself is rather small, it only has 600 MB RAM, the heap is limited to 128 MB but checking with VisualVM while in test suggests that it barely crosses 75 MB on the heap so the limit should not be an issue. This leaves me confused because it suggests to me that it is the VM itself that uses too much memory which I have never seen or heard of and has a hard time believing. Watching the server with "top" while running showed a physical memory usage of almost 60%, that is 360 MB RAM.
The old server shows similar signs. It has 1.5 GB RAM and while idle "top" shows a physical memory use of 91.2%. It does not get killed but has to be rebooted daily to avoid problems as ending the java process is the only way to get it to release the unused resources.
The issue cannot be reproduced in test, but that might be because the test machine runs Tomcat on a different platform (Windows, while both servers run Linux) and has significantly more RAM (12 GB) so the relative usage is smaller.
Last time I checked, an unloaded JVM ate somewhat over 100MB. Tomcat really needs at least 256MB. If you have a GUI desktop, kiss off another 128MB or so. Other support apps such as Apache HTTP take their own bites. And if the machine runs a web browser or GUI email client, either of them alone can eat more RAM than Tomcat.
For practical purposes, I really recommend 1GB RAM for a Tomcat server machine. 600MB was a tight fit even in 1998.
It does sound like maybe there's a problem with a webapp. Since the JVM has pre-set memory constraints, I'd kind of wonder if you're not interacting with a native class that does memory grabbing of its own and doesn't give it back.
An IDE is no substitute for an Intelligent Developer.
The server is question is a pure and dedicated server so no GUI of any kind and nothing is installed except the things Tomcat need. The apps saves to a database but even that runs on another server.
The 60% memory usage is for the java process run by the tomcat user so it is the server and nothing else, and even if has allocated all 128 MB of heap it still leaves 232 MB to the JVM and other data for the java process.
The app does not use native code in the form of methods declared native, but it does use instances of classes implementing the interfaces in java.sql and those are known to cause problems if used incorrectly. But I have been over code several times and that does look like clean use of those classes, also a problem involving those classes would show up in the heap as they are Java objects.