Java VM Options You Should Always Use in Production - Software Engineer Sandbox
Java VM Options You Should Always Use in Production - Software Engineer Sandbox
' Menu
Software Engineer
Sandbox
JAVA PRODUCTION
" 38 COMMENTS
# TWEET
$ LIKE
+ +1
& SUBSCRIBE
This post is a cheatsheet with enumeration of options, which should be always used to
configure Java Virtual Machine for Web-oriented server applications (i.e. Web FrontEnd) in production or production-like environments.
For lazy readers full listing is here (for curious detailed explanation is provided below):
Java < 8
-server
-Xms<heap size>[g|m|k] -Xmx<heap size>[g|m|k]
-XX:PermSize=<perm gen size>[g|m|k] -XX:MaxPermSize=<perm gen size>[g|m|k]
-Xmn<young size>[g|m|k]
-XX:SurvivorRatio=<ratio>
-XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled
-XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=<percen
-XX:+ScavengeBeforeFullGC -XX:+CMSScavengeBeforeRemark
-Dsun.net.inetaddr.ttl=<TTL in seconds>
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=<path to dump>`date`.hprof
-Djava.rmi.server.hostname=<external IP>
-Dcom.sun.management.jmxremote.port=<port>
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
Java >= 8
-server
-Xms<heap size>[g|m|k] -Xmx<heap size>[g|m|k]
-XX:MaxMetaspaceSize=<metaspace size>[g|m|k]
-Xmn<young size>[g|m|k]
-XX:SurvivorRatio=<ratio>
-XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled
-XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=<percen
-XX:+ScavengeBeforeFullGC -XX:+CMSScavengeBeforeRemark
To avoid dynamic heap resizing and lags, which could be caused by this, we explicitely
specify minimal and maximal heap size. Thus Java VM will spend time only once to
commit on all the heap.
-XX:PermSize=<perm gen size>[g|m|k] -XX:MaxPermSize=<perm gen size>[g|m|k]
Logic for permanent generation is the same as for overall heap predefine sizing to
avoid costs of dynamic changes. Not applicable to Java >= 8.
-XX:MaxMetaspaceSize=<metaspace size>[g|m|k]
By default Metaspace in Java VM 8 is not limited, though for the sake of system
stability it makes sense to limit it with some finite value.
-Xmn<young size>[g|m|k]
Ratio which determines size of the survivour space relatively to eden size. Ratio can be
calculated using following formula:
=
2
survivor ratio =
young size
2
survivor size
Make GC Right
-XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled
As response time is critical for server application concurrent collector feets best for
Web applications. Unfortunatelly G1 is still not production ready, thus we have to use
Concurrent Mark-Sweep collector.
-XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=<percent>
By default CMS GC uses set of heuristic rules to trigger garbage collection. This makes
GC less predictable and usually tends to delay collection until old generation is almost
occupied. Initiating it in advance allows to complete collection before old generation
is full and thus avoid Full GC (i.e. stop-the-world pause).
-XX:+UseCMSInitiatingOccupancyOnly
-XX:CMSInitiatingOccupancyFraction
triggered. Basically, it allows to create a buffer in heap, which can be filled with data,
while CMS is working. Thus percent should be back calculated from the speed in which
memory is consumed in old generation during production load. Such percent should
be chosen carefully, if it will be small CMS will work to often, if it will be to big
CMS will be triggered too late and concurrent mode failure may occur. Usually
-XX:CMSInitiatingOccupancyFraction
Instructs garbage collector to collect young generation before doing Full GC or CMS
remark phase and as a result improvde their performance due to absence of need to
check references between young generation and tenured.
Learn more and something fresh.
GC Logging
-XX:+PrintGCDateStamps -verbose:gc -XX:+PrintGCDetails -Xloggc:"<path to log>"
These options make Java to log garbage collector activities into specified file. All
records will be prepended with human readable date and time. Meanwhile you should
avoid using
-XX:+PrintGCTimeStamps
GC log files rotation makes analysis of garbage collection problems easier, also it
guaranties that disk is protected from space overconsumption.
Learn more and a little bit more.
DNS Caching
-Dsun.net.inetaddr.ttl=<TTL in seconds>
Number of seconds during which DNS record will be cached in Java VM. Default
behaviour of Java VM 6 was to cache forever, which does not feet server application
needs, as you would not want to restart server each time, when IP has changed in DNS
record. It has been changed in Java VM 7 to cache for 30 seconds, but only if security
manager is not installed. Depending on version of Java VM and presence of security
manager DNS records still can be cached infinitely.
Commonly recommended option is to disable DNS caching at all, which can be reason
for performance degradation. Requests to DNS are performed in synchorized block
and only one request is performed in any point in time. Thus, if your application is
havily utilizing network it will experience saturation on DNS requests, so TTL value
60
seconds). This mean that system your application is interacting with have to guaranty
that two different IPs will continue to work properly during this 1 minute, otherwise
lower TTL value should be chosen. It should always be reasonable (not equal to
networkaddress.cache.ttl
specified in
) to
If your application would ever fail with out-of-memory in production, you would not
want to wait for another chance to reproduce the problem. These options instruct
Java VM to dump memory into file, when OOM occurred. It can cause considerable
pauses on big heaps during OOM event. However, if Java VM is at OOM already,
collecting as much information about the issue is more important than trying to serve
traffic with completely broken application. We are also making sure the dump would
be created with name unique per application start time (this is requeired because Java
VM will fail to overwrite existing file).
Learn more.
IP address, which would be embedded into RMI stubs sent to clients. Later clients will
use this stubs to communicate with server via RMI. As in modern datacenters machine
often has two IPs (internal and external) you would want explicitly specify which IP to
use, otherwise JVM will make its own choice. Correct value of this property is a
precondition for successfully using JMX.
-Dcom.sun.management.jmxremote.port=<port>
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote
however to make JMX available for remote access specific listen port should be
provided. Later this port can be used to connect using any JMX tool (e.g. VisualVM or
Java Mission Control).
Also to reduce additional troubles with connecting disable standard authentication,
but be sure that only authorized users can connect to environment using firewall. If for
security reasons you still want to control access via standard mechanism learn more.
P.S.
Many options that were previously very useful with updates in Java VM (specifically
release of Java 7) are preconfigured by default:
-XX:+UseCompressedOops
-Dsun.rmi.dgc.server.gcInterval=3600000 and -Dsun.rmi.dgc.client.gcInterval=3600000
-Dcom.sun.management.jmxremote
Previous
Next
# ( )