I have a couple of questions. My end goal is to try to find out more about our web app's memory usage without having to use an expensive profiler. We would like to have an idea of how much memory an average session uses. Is our best option to just repeatedly call as we open up more sessions to get an idea? The problem with that approach is that it is sometimes difficult to tell whether the increase in memory was because of an individual session or additional objects as well...
We run on Tomcat, and our script for installing Tomcat as a service has the options -server -Xmx1536m -Xms1536m. This is on a machine that has 3MB of memory, and I understand that the last two refer to the initial and max heap size and that the JVM can't go much higher than either 1.5MB or 2MB or something like that. I'm not entirely clear on whether we would always want to jumpstart the initial heap size to the max heap size. Anyway, I have heard that sometimes multiple Tomcats are run on a server, and I'm assuming that there's one VM per Tomcat, so I'm wondering if this is done to reduce the heap size for each one to give better performance on each. It seems like it'd be ideal to run one Tomcat with a huge VM heap size per machine to reduce complexity, but if we need to change this, then we'll have to learn this stuff!
Initial Heap Size is the amount of memory consumed on start JVM and maximum heap is the obviously the maximum memory which can JVM allocate. If the maximum will be to low than you will get OutOfMemoryError.
I think that without a profiler you will be blind about memory consumption.
I also used freeMemory method, but it is very coarse for any performance tuning. You will need to know how often is GC running, because this is very expensive for CPU. There are many issues in GC tuning.
Some profilers are available for trial period, try them.
Read up on Java Platform Performance. It has some invaluable info about calculating and measuring memory. However, without a profiler, as David said, you are flying blind. As for a profiler being "expensive", your time is expensive and your application failing would be expensive as well. Fixing performance problems is very tricky (first rule of optimization: dont do it!). Your first step should be to define the problem. If you are experiencing slow performance, memory is probably not the issue because -Xms allocates all that memory on startup. Just chasing the memory allocation in this case will not reveal anything useful about the behavior of your code. A profiler, however, will let you track object allocation and code bottlenecks, which will give you something useful to work with.