Launching a Java Virtual Machine can be as easy as running java -classpath myapp.jar Main
or even shorter java -jar myapp.jar
if your using the Main-Class
attribute in META-INF/MANIFEST.MF
. This command will launch a JVM with default settings.
To see which options that are available and their default values on our system execute:
java -XX:+PrintFlagsFinal -version
uintx AdaptiveSizeDecrementScaleFactor = 4 {product} uintx AdaptiveSizeMajorGCDecayTimeScale = 10 {product} uintx AdaptiveSizePausePolicy = 0 {product} ... bool UseCompressedOops := true {lp64_product} ... bool UseXmmRegToRegMoveAll = true {ARCH product} bool VMThreadHintNoPreempt = false {product} intx VMThreadPriority = -1 {product} intx VMThreadStackSize = 1024 {pd product} intx ValueMapInitialSize = 11 {C1 product} intx ValueMapMaxLoopSize = 8 {C1 product} intx ValueSearchLimit = 1000 {C2 product} bool VerifyMergedCPBytecodes = true {product} ...
(If these options aren’t enough there’s more if you add a couple of switches:
java -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+PrintFlagsFinal -version
).
Most of these options can safely be left with their default values but there are a few options that should be tuned when running in production.
Basic memory setting
The minimum settings needed for any Java application are probably to specify initial and maximum Java heap size:
-Xms<size>
set initial Java heap size-Xmx<size>
set maximum Java heap size
If your are using Java 7 or earlier there’s a chance that you’ll run into “OutOfMemoryError: PermGen space” and need to increase the perm gen size with
-XX:MaxPermSize=<size>
, the default size is 64M for server VMs but many applications need more than 64M permgen space.
If the JVM runs out of heap memory which it cannot reclaim during GC it will throw an “java.lang.OutOfMemoryError: Java heap space”. To analyze what occupies the memory add
-XX:+HeapDumpOnOutOfMemoryError
– this will Dump heap to file in the current working directory when java.lang.OutOfMemoryError occurs. The -XX:HeapDumpPath=<path>
flag can be used to specify another location.
Garbage Collection
There are a number of garbage collection strategies to chose from and they won’t be covered here. Java Garbage Collection Distilled is a good overview.
Regardless of which collector is being used it’s a good a idea to enable logging of GC activities to GC activity to see how well the GC performs over time. Simply adding the flag -verbose:gc
enables basic gc acticty logging to STDOUT but it’s a better idea to instead use -Xloggc:<pathtofile>
> which logs GC events to a file.
Also make sure to add -XX:+PrintGCDateStamps
which print event date stamps and -XX:+PrintGCDetails
to get more gc events details.
By default the gc logfile keeps growing but the JVM also has built in support for rotating the file using the -XX:+UseGCLogFileRotation
, the -XX:GCLogFileSize=8K
and the -XX:NumberOfGCLogFiles=1
options.
Finally you might want to explicitly disable manual GC with -XX:+DisableExplicitGC
, this making sure that calls to System.gc()
turns into a no-op and leaves all gc execution in the control of the garbage collector.
Final example
java -Xms10g -Xmx10g -XX:MaxPermSize=256m -XX:+HeapDumpOnOutOfMemoryError -XX:+DisableExplicitGC -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:/var/log/myapp/gc.log -XX:+UseGCLogFileRotation -XX:GCLogFileSize=10M -XX:NumberOfGCLogFiles=20 -jar myapp.jar
This example launches a VM and allocated 10 GB memory and 256MB for permgen (Java7). The option to dump the heap on out of memory is turned on, the application is set to use the G1 (garbage first) collector and garbage collect activities are logged to the file /var/log/myapp/gc.log
with log file rotation turned on.
Good blog, well, I traslated you blog into Chinese in my blog.