Quick & Dirty ColdFusion JVM Memory Monitor

Posted by Dan on Dec 13, 2007 @ 9:27 AM

Yesterday, I posted on how to use JConsole to monitor ColdFusion's JVM. Today I wanted to give you a quirk and dirty script you can run on ColdFusion 8 which will give you a lot of the same memory information—but wrapped up into a CF script. The script is based on some code from Steve Brownlee's useful post on accessing ColdFusion internals using Java.

The key benefit to this method is there's nothing to install—just copy the code on a server and run it. Obviously, this only works if the server is responding and is not going to be as thorough as using JConsole. I have found this script handy to just give you a quick overview of the system state.

I've only tested the code in CF8, but it doesn't utilize any special ColdFusion classes—it utilizes the core Java classes. This code should work on any ColdFusion installation using Java 5 (v1.5) or higher.

<html>
<head>
    <title>
        JVM Monitor -
        <cfoutput>
            #server.coldfusion.ProductName#
            - #server.coldfusion.ProductLevel#
            v#server.coldfusion.ProductVersion#
        </cfoutput>
    </title>
</head>
<body>
<script type="text/javascript">document.write("<h1>" + document.title + "</h1>");</script>
<cfscript>
/**
* Pass in a value in bytes, and this function converts it to a human-readable format of bytes, KB, MB, or GB.
* Updated from Nat Papovich's version.
* 01/2002 - Optional Units added by Sierra Bufe (sierra@brighterfusion.com)
*
* @param size     Size to convert.
* @param unit     Unit to return results in. Valid options are bytes,KB,MB,GB.
* @return Returns a string.
* @author Paul Mone (sierra@brighterfusion.compaul@ninthlink.com)
* @version 2.1, January 7, 2002
*/

function byteConvert(num) {
    var result = 0;
    var unit = "";
    // Set unit variables for convenience
    var bytes = 1;
    var kb = 1024;
    var mb = 1048576;
    var gb = 1073741824;
    // Check for non-numeric or negative num argument
    if (not isNumeric(num) OR num LT 0)
        return "Invalid size argument";
    // Check to see if unit was passed in, and if it is valid
    if ((ArrayLen(Arguments) GT 1)
        AND ("bytes,KB,MB,GB" contains Arguments[2]))
    {
        unit = Arguments[2];
    // If not, set unit depending on the size of num
    } else {
         if     (num lt kb) {    unit ="bytes";
        } else if (num lt mb) {    unit ="KB";
        } else if (num lt gb) {    unit ="MB";
        } else                {    unit ="GB";
        }
    }
    // Find the result by dividing num by the number represented by the unit
    result = num / Evaluate(unit);
    // Format the result
    if (result lt 10)
    {
        result = NumberFormat(Round(result * 100) / 100,"0.00");
    } else if (result lt 100) {
        result = NumberFormat(Round(result * 10) / 10,"90.0");
    } else {
        result = Round(result);
    }
    // Concatenate result and unit together for the return value
    return (result & " " & unit);
}
function formatMB(num){
    return byteConvert(num, "MB");
}
// Create Java object instances needed for creating memory charts
runtime = createobject("java", "java.lang.Runtime");
mgmtFactory = createobject("java", "java.lang.management.ManagementFactory");
pools = mgmtFactory.getMemoryPoolMXBeans();
heap = mgmtFactory.getMemoryMXBean();
jvm = structNew();
jvm["JVM - Used Memory"] = formatMB(runtime.getRuntime().maxMemory()-runtime.getRuntime().freeMemory());
jvm["JVM - Max Memory"] = formatMB(runtime.getRuntime().maxMemory());
jvm["JVM - Free Memory"] = formatMB(runtime.getRuntime().freeMemory());
jvm["JVM - Total Memory"] = formatMB(runtime.getRuntime().totalMemory());
jvm["Heap Memory Usage - Max"] = formatMB(heap.getHeapMemoryUsage().getMax());
jvm["Heap Memory Usage - Used"] = formatMB(heap.getHeapMemoryUsage().getUsed());
jvm["Heap Memory Usage - Committed"] = formatMB(heap.getHeapMemoryUsage().getCommitted());
jvm["Heap Memory Usage - Initial"] = formatMB(heap.getHeapMemoryUsage().getInit());
jvm["Non-Heap Memory Usage - Max"] = formatMB(heap.getNonHeapMemoryUsage().getMax());
jvm["Non-Heap Memory Usage - Used"] = formatMB(heap.getNonHeapMemoryUsage().getUsed());
jvm["Non-Heap Memory Usage - Committed"] = formatMB(heap.getNonHeapMemoryUsage().getCommitted());
jvm["Non-Heap Memory Usage - Initial"] = formatMB(heap.getNonHeapMemoryUsage().getInit());
for( i=1; i lte arrayLen(pools); i=i+1 ) jvm["Memory Pool - #pools[i].getName()# - Used"] = formatMB(pools[i].getUsage().getUsed());
</cfscript>
<cfdump var="#jvm#" label="JVM Memory Monitor" />
</body>
</html>

Categories: HTML/ColdFusion, Java

7 Comments

  • Nice Work...should come in handy. For all of the benefits of Java-based CF (and there are MANY), all of this memory tuning hassle kind of makes my pine for the pre-Java days. You could throw some NASTY code at CF 4.5/5 and it would just keep humming along.
  • Hi Dan,
    Hope you can help. I ran the memory script you wrote to monitor JVM memory (very nice!) and it says
      Heap Memory Usage - Max: 63.6 MB,
      Heap Memory Usage - Initial: 0.00 MB

    yet I have set the JVM Heapsize to 1024MB (-Xms1024m -Xmx1024m )
    Why is my Heap size not reaching 1024Mb

    Our Server (CF8) keeps crashing (java.lang.OutOfMemoryError) and i'm trying to debug it.
    Any help much appreciated.
    Thanks,
    Mathew
  • @Mathew:

    The "Heap Memory Usage - Initial" should definitely read 1024 (or close to it.) Are you sure the JVM settings you set are actually being used? Also, did you actually restart the CF services after making the changes?

    What's does your full "java.args" line look like in your jvm.config file?

    It's possible you have contradictory settings.

    Also, what version of CF are you using?
  • This is great nice and simple!!!
  • Your tool is great. I have began using it on all of my sites. I have a weird issue that continues to show its face. I get random 500 errors. I have read tons of posts with no clear answer. I am currently using your tool to determine if I have a GC/heap problem. Any thoughts?
  • I just checked and this code appears to be working correctly with ColdFusion 10 Developer v10.0.0.281485.
  • Dan,

    Very nice work! but I am getting the same issue "Heap Memory Usage - Initial: 0.00 MB" I have CF 9.0.1 on wndows 2003 box

Add Comment

Leave this field empty