Over a million developers have joined DZone.

Tuning Your Java VM

DZone's Guide to

Tuning Your Java VM

Free Resource

Download Microservices for Java Developers: A hands-on introduction to frameworks and containers. Brought to you in partnership with Red Hat.

Every java application needs some tuning to meet your requirements.  Java VM has a lot of command line options, the most used of which are :

-Xms<n>[g|m|k]  -> The initial and minimum size of the Java heap
-Xmx<n>[g|m|k]  -> The maximum size of the Java heap

where the  Java Heap size is  the total size of the young generation space and old generation space. (we won't enter into detail here, see doc)

Because you know your server processor's type and memory size, most of the time you will put big values for those options even if there is no need to. Well I have 8GB of memory, so what's the big deal if I set an Xms of 4GB?  Anyway, the values are chosen just because we have used them on other projects of the same caliber and no OutOfMemory was raised. But in the real world it is good to know why you have to set the heap size to some value.

Some lesser-known options are about permanent generation space.This area is only used by the HotSpot VM itself to hold metadata, such as class data structures, interned strings, and so on:

-XX:PermSize=<n>[g|m|k]        -> The initial and minimum size of the permanent generation space.
-XX:MaxPermSize=<n>[g|m|k] -> The maximum size of the permanent generation space

If you use a lot of third party libraries , your perm space may become full and an OutOfMemory regarding permgen space will be given. So you will have to increase MaxPermSize , and because for Java 6 a default value is 64M, a new value of 128M will suffice.

 The general ideea to tune your VM is that when your application was used from some time, meaning the memory size is big enough, to do a full GC to get some statistics. You know your application process pid from java status process tool (jps) or from any another OS command (like ps in linux). You can generate a full GC using java command jmap:

jmap -histo:live <pid>

If we want to see some GC info in our application stdout (or log)  we need to start the application with some command line options :

-Xloggc:<filename>          -> to capture GC data in a file
-XX:+PrintGCDateStamps  -> to print the date time stamp when a GC is done

This will result in some output like :

2012-01-11T15:09:01.483+0200: [GC [PSYoungGen: 250408K->7194K(247872K)] 279260K->38759K(335296K), 0.0187385 secs] [Times: user=0.11 sys=0.00, real=0.02 secs]

Here we can see young generation and total footprint of memory before and after GC. 

There are some GC algorithms which can be used by a Java VM. The following command line options allow to use a specific GC algorithm:

-XX:+UseSerialGC -> single threaded, young generation, and old generation garbage collector (should be used only for small Java heap sizes such as -Xmx256m or smaller)
-XX:+UseParallelGC -> only the young generation space utilizes a multithreaded (parallel) garbage collector.The old generation space uses a single-threaded  garbage collector.
-XX:+UseParallelOldGC -> both young and old generations use multithread garbage collector.
-XX:+UseParNewGC -> enables a multithreaded, young generation garbage collector
-XX:+UseConcMarkSweepGC -> enables the VM’s mostly concurrent garbage collector. It also auto-enables -XX:+UseParNewGC (use if If you are not able to meet your application’s worst case latency requirements due to full garbage collection duration being too long)
-XX:+UseG1GC -> garbage first collector (default in java 7, can be also used in latest releases of java 6)

Practically by default, in Java 6 ParallelGC is used, and in Java 7 G1GC. Changing this algorithm must not be done in almost all cases.

When a jmap -histo:live command is issued, the following result will be seen:

[Full GC [PSYoungGen: 28393K->0K(321088K)] [ParOldGen: 101070K->107957K(204096K)] 129464K->107957K(525184K) [PSPermGen: 75396K->74999K(110208K)], 0.6012680 secs] [Times: user=1.68 sys=0.00, real=0.60 secs] 

Here we can see young generation, old generation and permanent generation memory before and after GC.  To know your application java heap size and permanent generation size you can use some general guidelines :

1) The initial and maximum Java heap size command line options, -Xms and -Xmx, should be set to a value between three and four times larger than the live data size of the old generation space (for  previous output xms must be between 3*107957K ~ 323M and 4*107957K ~ 431M)

2) The initial and maximum permanent generation size, -XX:PermSize and -XX:MaxPermSize, should be 1.2x to 1.5x larger than the live data size of the permanent generation space (for previous output permSize must be between 1.2*74999K ~ 90M and 1.5*74999K  ~ 112M)

You must have in mind only one thing:

The more data you collect, the better the estimate for a Java heap size starting point.

Download Modern Java EE Design Patterns: Building Scalable Architecture for Sustainable Enterprise Development.  Brought to you in partnership with Red Hat


Opinions expressed by DZone contributors are their own.


Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.


{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}