The amazing adventures of Doug Hughes

This blog post is drawn from a presentation I gave recently to the Maryland CFUG. It is in some ways slightly simplistic so I will apologize to those for whom this information is “old-hat”. However there are many ColdFusion users who are not aware that since ColdFusion MX, the JVM is indeed The Heart Of The Matter for both ColdFusion and JRun. In this post I am attempting to explain where all the pieces fit, how they work together and how to tune and troubleshoot.

What Is The JVM?

Sun Microsystems created Java as a high-level programming language which should run on as many operating systems and hardware variations as possible. The goal of “write once run anywhere” meant that a predictable encapsulated operating system, no matter what the underlying hardware and software, was required. The Java Virtual Machine (JVM or JRE) is a multi-threaded environment abstracting the actual computer operating system from the application code.

Main JVM Suppliers

These are the main suppliers of Java Virtual Machines, there are others.

  • Sun Hotspot JVM
  • IBM JVM
  • BEA JRockit
  • MAC OSRuntime for OSX
  • Oracle JVM aka JServer – OJVM
  • Microsoft JVM

ColdFusion And The JVM

Since ColdFusion MX 6.0-6.1, CF has been a Java Application which needs what is known as a Servlet Container to run on. The most popular Servlet Container for ColdFusion is JRun. In the Enterprise edition of ColdFusion, the actual Servlet Container to be used can be selected during the install. In non-Enterprise installs JRun is automatically used. The main point being that there is always a Servlet Container.

Java J2EE – Java EE Servlet Containers

This is a list of suppliers of Java servlet containers which are certified as being J2EE compliant. Tomcat is not shown because I don’t believe it is fully certified as such by Sun. However, Apache Geronimo will be the first open-source certified J2EE/JavaEE servlet container.

  • Geronimo from Apache
  • JBoss from Red Hat
  • JRun from Adobe
  • Oracle OC4J
  • Sun Java System Application Server (Sun One).
  • WebLogic Server from BEA
  • WebSphere Server from IBM

Where everything sits-fits

This is a simple diagram showing where the Operating System, JVM, Servlet Container and Java Application Server sit in relativity.

ColdFusion and the JVM

When Allaire ported ColdFusion to run on Java (previously the core was C++) they realized there were already many copies of ColdFusion in use and needed to engineer some backward compatibility into the newly released version, CFMX 6.0 code-named “Neo”. If we refer to the diagram above we can see that ColdFusion (the yellow rectangle in case it is hard to read the text) runs inside the Java Servlet Container (often JRun).

By ColdFusion MX 6.1 (code named Red Sky) CF was a fully compliant J2EE application server which involves items such as a particular directory-file structures. However Allaire-Macromedia wanted to make sure that existing users of CF could upgrade easily and relatively painlessly. They also wanted to market ColdFusion to the Java community who were used to a particular directory structure. As added benefit for Adobe-Macromedia, this presented a marketing opportunity to have two versions of CFMX; a Standard-Server version and an Enterprise version.

The Standard-Server version would follow the existing CF install where there could only be one instance of ColdFusion on a physical server. The Enterprise version would follow the J2EE standard where multiple application server instances are common and normal.

One very important point to note here is that whether ColdFusion is installed as a Standard-Server version or as an Enterprise version, the JVM is still at the heart of all.

This need to support existing CF users led to the creation of a convoluted directory structure for the Standard-Server version, I will attempt to describe that below. This is a typical directory structure for a Windows install of CFMX 7 Standard-Server version. Note that I have highlighted the “runtime” directory. That directory actually contains JRun and this is visually confusing as in actual fact, ColdFusion is running inside JRun, not the other way around as it appears in this directory structure. In this install there can only be one ColdFusion server instance on a single physical server.

Once again this is a typical Windows install, this time for the Enterprise version and shows ColdFusion (which is inside the “servers” directory) as actually logically where it is inside the JRun4 directory structure. In this install, multiple versions of ColdFusion are possible on a single physical server.

Again, one very important point to note here is that whether ColdFusion is installed as a Standard-Server version or as an Enterprise version, the JVM is still at the heart of all.

Garbage Collection

The JVM has a fairly efficient memory management paradigm which is seen better that the typical Windows methodology. Sun JVM’s use a generational garbage collector with two young generations and an old generation. New objects are always allocated in the young generation part of the heap. Every time the young generation is full a minor garbage collection takes place. Minor garbage collections don’t take very long. Objects which survived some minor collections, because they are still referenced from the application, are promoted to the older generation.

Usually the older generation is full at some point too, and needs to be cleaned. This leads to a major garbage collection or Full Garbage (Full GC) collection that removes garbage from both the old and the younger generations. Full GC’s are “stop-the-world” events and need to occur only when absolutely necessary. I emphasize here the part in italics in the paragraph above “because they are still referenced from the application“.

In an efficiently written CF-Java web application objects created in memory should be cycled and collected (that memory allocation released) whilst the object is in the “new” part of the overall memory space. Web applications by nature have short object lifecycles because of the request-response nature of web applications. As a very general rule the more objects that end up in the “old” memory space the more often Full GC’s are likely to occur.

Garbage Collectors

There are three main Garbage Collector algorithms available to ColdFusion – JRun applications; here they are.

  • XX:+UseParallelGC Use parallel garbage collection, this is typically the default collector for ColdFusion installations. This collector is also referred to as the throughput collector. It uses a parallel version of the young generation collector. The old (tenured) generation is still cleaned with the default collector. Note This option can not be used in conjunction with -XX:+UseConcMarkSweepGC.
  • XX:+UseConcMarkSweepGC Use concurrent garbage collection. This collector is also referred to as the concurrent low pause collector. It collects garbage in the old (tenured) generation concurrently to executing the application. Note that this option can not be used in conjunction with -XX:+UseParallelGC. Instead you may combine it with -XX:+UseParNewGC
  • XX:+UseParNewGC Instructs the VM to use a parallel collector for the young generation. This option can be used in conjunction with -XX:+UseConcMarkSweepGC. As a note I have found that using the ConcMarkSweepGC along with ParNewGC can cause longer Full GC’s, I tend to use ParNewGC on its own. To change the garbage collector one of the above arguments is added to the jvm.config file.

Full Garbage Collections (Full GC’s) – Try To Minimize

One of the first methods I always want to employ when troubleshooting is to ascertain how many Full GC’s are taking place. To do so I add these arguments to the jvm.config file, which is located in one of these directories depending on the installation:

  • Enterprise – {drive-volume}jrun4bin
  • Standard/Server – {drive-volume}CFusionMX7runtimebin

I add these five arguments to the jvm.config file, it is important to remove these arguments when verbose garbage collection output is no longer needed.

-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC -verbose:gc -Xloggc:yourname.log*

*This will send Garbage collection output to the {std}-out.log and will create a log of all GC activity with whatever name you gave yourname in either. This output log will go to one of the following locations.

  • Enterprise – {drive-volume}jrun4bin
  • Standard/Server – {drive-volume}CFusionMX7runtimebin

Full GC’s are “stop-the-world” events and need to occur only when absolutely necessary.

Verbose Garbage Collection Log Example

Here is an example of the Verbose Garbage Collection log output:

par new generation   total 97088K, used 0K [0x10010000, 0x171d0000, 0x171d0000)
eden space 77696K,   0% used [0x10010000, 0x10010000, 0x14bf0000)
from space 19392K,   0% used [0x14bf0000, 0x14bf0000, 0x15ee0000)
to   space 19392K,   0% used [0x15ee0000, 0x15ee0000, 0x171d0000)
<span style="color: red;">tenured generation   total 932096K, used 11109K</span> [0x171d0000, 0x50010000, 0x50010000)
the space 932096K,   1% used [0x171d0000, 0x17ca95b8, 0x17ca9600, 0x50010000)
compacting perm gen  total 26624K, used 26606K [0x50010000, 0x51a10000, 0x58010000)
the space 26624K,  99% used [0x50010000, 0x51a0b8a0, 0x51a0ba00, 0x51a10000)
} , 0.1523967 secs]
<span style="color: red;">3691.704: [Full GC</span>  {Heap before GC invocations=8:
Heap

This Full GC was almost certainly unnecessary because at the time it ran only 1109k out of 932096k of the tenured (old) generation had been used. I also note the timestamp (3691.704) of every Full GC in the log. If I see a regular pattern it almost always means something is calling a Full GC perhaps using System.gc()

Methods To Safely Minimize Full GC’s

One pattern I have seen over and over with ColdFusion is that Full GC’s are very often occurring at regular 60 second intervals. Although I have never been able to pin this down fully, I suspect it is due to a Java process called RMI(Remote Method Invocation). So then what do we do to control these unnecessary “stop-the-world” Full G’s? There are two alternatives:

  1. Disable Full GC’s using the -XX:+DisableExplicitGC jvm.config argument. I am not totally happy doing this and in many cases it will not work
  2. Run Full GC’s at longer regular intervals. Applying these arguments instead of -XX:+DisableExplicitGC will cause Full GC’s every 10 minutes (600,000 ms).
Dsun.rmi.dgc.client.gcInterval=600000
Dsun.rmi.dgc.server.gcInterval=600000

Using Metrics Logging In Troubleshooting The JVM

I have found that enabling metrics looking is invaluable in troubleshooting ColdFusion and JRun application issues. Metrics logging will show the status of the CF-JRun instance at pre-selected time intervals in terms of number of threads in use and available memory. In order to enable metrics logging we need to edit the jrun.xml file, here:

  • Enterprise install {drive-volume}JRun4servers{servername}SERVER-INF
  • Server-Standard install {drive-volume}CFusionMX7runtimeservers{servername}SERVER-INF

Here are the settings I usually use by making these changes in the jrun.xml file. Firstly uncomment the service class…

Then set “metricsEnabled” to true, we will leave other settings to default…

Lastly I like to split the logs out to make reading them easier by this change…

Conclusion

I have found that the only way to really determine the correct garbage collector to use for your applications and what the correct arguments are to pass to the JVM, via the jvm.config file, to effectively manage garbage collections is to first determine how many Full GC’s are occurring and control that if there are too many. Then load-test the application whilst tuning the arguments passed to the JVM, via the jvm.config file.

Comments on: "The Heart Of The Matter – The JVM" (10)

  1. Hi Mike, thanks for the post. I thought that there was a big difference between servlet containers (aka servlet engines) and J2EE application servers. If I’m not mistaken, Tomcat is a servlet engine and Geronimo is a J2EE application server. The biggest difference, amongst other things, the support for EJB (which should be present in a Sun certified J2EE application server). I also thought that Tomcat is in fact the reference implementation for servlet engines (as suggested by Sun). I always thought CF needed a JE22 application server to run and that just a servlet engine wasn’t enough. Meaning CF won’t run on Tomcat but it will run on Geronimo. I could be wrong…

    Cheers,
    Luke

    Like

  2. Mike Brunt said:

    @Luke, thanks for your comment, you raise a good point here because there are different levels of functionality between products such as WebSphere and Tomcat for instance. But I am being highly non -technical and non-specific. I will do a bit more research and see what I can do to broaden my comments here.

    There is an article here about using CFMX 6.1 and possibly 7 with Tomcat.
    http://www.performancehosting.net/cfmx-tomcat.htm

    Like

  3. Mike Brunt said:

    @Luke, one more point I should have mentioned, when you create new instances of CF in the Enterprise install of course, you can select either an EAR (Enterprise Archive) or WAR (Web Archive) base for the instance. If there is a need to interact with EJB’s you should chose to create an EAR deployment. As a matter of course I always create an EAR.

    Like

  4. Richard said:

    Just a note on this. We’ve been developing CF7 applications for clients and deploying them (packaged as WARs) on Tomcat 5 for 18 months now. Although Tomcat isn’t officially supported according to Adobe we don’t have any problems as long as you increase the default JVM memory

    The advantage we find is that Tomcat is so simple, especially for clients who do not have enterprise J2EE capabilities already. In fact we haven’t found too many clients who have a well developed J2EE infrastructure.

    The applications are generally low-use management information systems. so although they are functionally rich they do not experience high load. They are also self contained, apart from some interfacing with local authentication schemes. For more complex requirements, Tomcat may not be the solution, but for us it works a treat.

    Like

  5. Mike Brunt said:

    @Richard that sounds great and it’s interesting because I am a member of the Open BlueDragon steering committee and Tomcat is well supported there. You are right, the benefits of J2EE are not yet widely used nor understood in the CF community. Adobe does not publish much at about server side issues. Thanks for the comment by the way.

    Like

  6. Richard said:

    @Mike – I too am delighted with the OBD initiative. One of my gripes has been that each of our applications requires an enterprise CF license (or some sort of OEM agreement) which prices certain business models out of the market. Vince has rightly said that New Atlanta offer very competitive OEM rates, but OBD is free which opens up a whole lot more.

    Out of interest I dropped our applications into an OBD Tomcat installation and they ran fine (except for CFDOCUMENT, of course)

    I didn’t do extensive testing but it looks promising. Will certainly be looking at developing applications with an eye on the Tomcat/OBD deployment route.

    Couple of questions. OBD doesn’t seem to run code that has been compiled with the cfcompile utility. This would need to looked at I guess if you are distributing applications.

    Like

  7. J.T. Wenting said:

    As to the difference between a JEE application server and a servlet container:
    A JEE application server provides a superset of the functionality of a servlet container.
    In other words, it does everything a servlet container does, and adds other services to fill out the complete JEE platform.
    Additional services include (among others) an EJB container and JMS messaging stack.
    Also some services (like database connection pooling, JNDI naming service, etc.) that are optional for servlet containers are required for a full JEE server.

    As to JVM providers, you can remove Microsoft from that list.
    They stopped providing their JVM back in 2006 (I think it was) and now officially endorse Sun’s reference implementation.

    Tomcat will never be a certified JEE application server because it only implements the servlet/JSP container and associated services (JNDI, Database connection pooling).
    It has however for a long time been the reference implementation for the servlet stack, a position it has now lost to GlassFish which btw is the first and so far only open source and certified JEE application server (being the reference implementation for the platform).

    Like

  8. Mike Brunt said:

    @JT thank you very much for providing very valuable information for this blog piece and I will clarify the Microsoft JVM position.

    Like

  9. Great article very helpful. I know most of these items however its nice to have all of it specified by one place for reference.

    Like

  10. At this time it seems like Drupal is the preferred blogging platform available right now. (from what I’ve read) Is that what you’re using on your blog?

    Like

Comments are closed.

Tag Cloud

%d bloggers like this: