You can always call Runtime.getRuntime().freeMemory().
The other half of the problem, getting the cost of objects, seems more problematic to me.
I think a better solution would be figuring out how to cluster and scale your web services so they can gracefully accept 150% of rated load without denying new connections. Sounds like a sizing exercise would get you a better solution than a code hack.
Runtime.getRuntime().freeMemory() is a way to get free memory for JVM at that moment while runtime. Is it good way (or) not it depends completely on your application.
EDIT: I originally provided this sample (linking to William Brendel's answer on another topic). The creator of that topic (Steve M) wanted to create a multi-platform Java application. Specifically, the user was trying to find a means by which to assess the running machine's resources (disk space, CPU and memory usage).
This is an inline transcript of the answer given in that topic. However, it has been pointed out on this topic that it is not the ideal solution, despite my answer being marked as accepted.
public class Main {
public static void main(String[] args) {
/* Total number of processors or cores available to the JVM */
System.out.println("Available processors (cores): " +
Runtime.getRuntime().availableProcessors());
/* Total amount of free memory available to the JVM */
System.out.println("Free memory (bytes): " +
Runtime.getRuntime().freeMemory());
/* This will return Long.MAX_VALUE if there is no preset limit */
long maxMemory = Runtime.getRuntime().maxMemory();
/* Maximum amount of memory the JVM will attempt to use */
System.out.println("Maximum memory (bytes): " +
(maxMemory == Long.MAX_VALUE ? "no limit" : maxMemory));
/* Total memory currently in use by the JVM */
System.out.println("Total memory (bytes): " +
Runtime.getRuntime().totalMemory());
/* Get a list of all filesystem roots on this system */
File[] roots = File.listRoots();
/* For each filesystem root, print some info */
for (File root : roots) {
System.out.println("File system root: " + root.getAbsolutePath());
System.out.println("Total space (bytes): " + root.getTotalSpace());
System.out.println("Free space (bytes): " + root.getFreeSpace());
System.out.println("Usable space (bytes): " + root.getUsableSpace());
}
}
}
User Christian Fries points out that it is wrong to assume that Runtime.getRuntime().freeMemory() gives you the amount of memory which may be allocated until an out-of-memory error occurs.
From the documentation, the signature return of Runtime.getRuntime().freeMemory() is as such:
Returns: an approximation to the total amount of memory currently available for future allocated objects, measured in bytes.
However, user Christian Fries claims this function may be misinterpreted. He claims that the approximate amount of memory which may be allocated until an out-of-memory error occurs (the free memory) is likely to be given by:
long presumableFreeMemory = Runtime.getRuntime().maxMemory() - allocatedMemory;
With allocatedMemory being given by:
long allocatedMemory =
(Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory());
The key here is a discrepancy between the concept of free memory. One thing is the memory that the operating system provides the Java Virtual Machine. Another is the total amount of bytes comprising the chunks of blocks of memory actually being used by the Java Virtual Machine itself.
Considering that memory given to Java applications is managed in blocks by the Java Virtual Machine, the amount of free memory available to the Java Virtual Machine may not exactly match the memory available for a Java application.
Specifically, Christian Fries denotes the usage of the -mx or -Xmx flags to set the maximum amount of memory available to the Java Virtual Machine. He notes the following function differences:
/* Returns the maximum amount of memory available to
the Java Virtual Machine set by the '-mx' or '-Xmx' flags. */
Runtime.getRuntime().maxMemory();
/* Returns the total memory allocated from the system
(which can at most reach the maximum memory value
returned by the previous function). */
Runtime.getRuntime().totalMemory();
/* Returns the free memory *within* the total memory
returned by the previous function. */
Runtime.getRuntime().freeMemory();
Christian concludes his answer by stating that Runtime.getRuntime().freeMemory() in fact returns what may be called presumable free memory; even if a future memory allocation does not exceed the value returned by that function, if the Java Virtual Machine has not yet received the actual chunk of memory assigned by the host system, a java.lang.OutOfMemoryError may still be produced.
In the end, the proper method to use will have a varying degree of dependence on the specifics of your application.
In addition to the other answer, I would like to note that doing that is not necessarily a good idea, since you might have a cache in your app that uses SoftReferences.
Such a cache would release memory as soon as the JVM reaches its memory limits. Allocating memory, even if there's not enough free memory, would first cause memory to be released by the soft references, and make it available for the allocation.
Each MemoryUsage provides init, used, committed and max values. This might be useful if create a memory monitor thread which polls memory and logs it, providing you with a history of memory usage over time. Sometimes it's helpful to see the memory usage over time leading up to the errors.
If you really want to take this to an extreme, create a heap dump thread. Monitor your memory usage over time and when it exceeds certain thresholds do the following (this works on JBoss 5.0 - your mileage may vary):
// init code
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
HotSpotDiagnosticMXBean diagBean = ManagementFactory.newPlatformMXBeanProxy(server, "com.sun.management:type=HotSpotDiagnostic", HotSpotDiagnosticMXBean.class);
// loop code
// add some code to figure if we have passed some threshold, then
File heapFile = new File(outputDir, "heap-" + curThreshold + ".hprof");
log.info("Dumping heap file " + heapFile.getAbsolutePath());
diagBean.dumpHeap(heapFile.getAbsolutePath(), true);
Later you can review these heap dump files with the eclipse memory analyzer or similar tools to check for memory leaks etc.
Note: All the answers so far, even the accepted one, seem to answer the question by saying that Runtime.getRuntime().freeMemory() gives you the amount of memory which may be allocated until an out-of-memory error occurs. However: this is wrong.
The approximate amount of memory which may be allocated until an out-of-memory error occurs, i.e., the free memory is likely
Runtime runtime = Runtime.getRuntime();
long presumableFreeMemory = runtime.maxMemory() - allocatedMemory;
where
long allocatedMemory = runtime.totalMemory() - runtime.freeMemory();
Explanation:
If you launch the JVM via an -mx parameter (or -Xmx) you specify the maximum amount available to the JVM. Runtime.getRuntime().maxMemory() will give you this amount. From this amount of system memory the JVM will allocate memory in chunks, say for example blocks of 64 mb. At start, the JVM will only allocate such a chunk from the system and not the full amount. Runtime.getRuntime().totalMemory() gives the total memory allocated from the system, while Runtime.getRuntime().freeMemory() gives you the free memory within the total memory allocated.
Hence:
long definitelyFreeMemory = Runtime.getRuntime().freeMemory();
is the free memory already reserved by the JVM, but it is likely just a small amount. And you will likely get presumableFreeMemory. Of course, you may get an out-of-memory exception even if you tried to allocate an amount smaller than presumableFreeMemory. This may happen if the JVM does not get the next memory chunk from the system. However, on most systems this will never happen and the system will rather start swapping - a situation you like to avoid. W.r.t. to the original question: if -mx is set to a reasonable value, then presumableFreeMemory is a good indicator for the free memory.
To get the physical machine total, used and free memory information, we can also get it by using java Runtime.exec() with command argument free -m and then interpreting it as below:
Runtime runtime = Runtime.getRuntime();
BufferedReader br = new BufferedReader(
new InputStreamReader(runtime.exec("free -m").getInputStream()));
String line;
String memLine = "";
int index = 0;
while ((line = br.readLine()) != null) {
if (index == 1) {
memLine = line;
}
index++;
}
// total used free shared buff/cache available
// Mem: 15933 3153 9683 310 3097 12148
// Swap: 3814 0 3814
List<String> memInfoList = Arrays.asList(memLine.split("\\s+"));
int totalSystemMemory = Integer.parseInt(memInfoList.get(1));
int totalSystemUsedMemory = Integer.parseInt(memInfoList.get(2));
int totalSystemFreeMemory = Integer.parseInt(memInfoList.get(3));
System.out.println("Total system memory in mb: " + totalSystemMemory);
System.out.println("Total system used memory in mb: " + totalSystemUsedMemory);
System.out.println("Total system free memory in mb: " + totalSystemFreeMemory);