OpenJDK default options to always use the server VM
Assuming you have both the client and server VM installed, you just need to change the order of the lines in jvm.cfg to make -server first. You can find jvm.cfg like this:
find $(dirname $(dirname $(readlink -f $(which java)))) -name jvm.cfg
On my machine, it’s /usr/lib/jvm/java-6-openjdk-amd64/jre/lib/amd64/jvm.cfg .
The default Java VM is set in your jvm.cfg file. On Windows this is in your Java folder in C:\Program Files , on Linux the path may vary.
On my Ubuntu 12.04 amd64 system with Oracle Java JDK7 installed via the Webupd8 ppa, the file is in /usr/lib/jvm/java-7-oracle/jre/lib/amd64 . For the default OpenJDK 6, the file is in /usr/lib/jvm/java-6-openjdk-amd64/jre/lib/amd64/jvm.cfg . Note that you need the JDK and not just the JRE installed.
Edit the jvm.cfg that corresponds to your current default Java version ( sudo nano /usr/lib/jvm/java-7-oracle/jre/lib/amd64/jvm.cfg ). Switch -server KNOWN to -server IGNORE and -client IGNORE to -client KNOWN .
This will make the -client flag «known» to the java executable, and make it ignore the -server flag , thus making it the default.
The original file (client vm as default):
# Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. # ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. # # List of JVMs that can be used as an option to java, javac, etc. # Order is important -- first in this list is the default JVM. # NOTE that this both this file and its format are UNSUPPORTED and # WILL GO AWAY in a future release. # # You may also select a JVM in an arbitrary location with the # "-XXaltjvm=" option, but that too is unsupported # and may not be available in a future release. # -server KNOWN -client IGNORE -hotspot ERROR -classic WARN -native ERROR -green ERROR
Modified file (server vm as default):
# Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. # ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. # # List of JVMs that can be used as an option to java, javac, etc. # Order is important -- first in this list is the default JVM. # NOTE that this both this file and its format are UNSUPPORTED and # WILL GO AWAY in a future release. # # You may also select a JVM in an arbitrary location with the # "-XXaltjvm=" option, but that too is unsupported # and may not be available in a future release. # #-server KNOWN -server IGNORE #-client IGNORE -client KNOWN -hotspot ERROR -classic WARN -native ERROR -green ERROR
Now test to see if the change worked:
$ java -version java version "1.7.0_07" Java(TM) SE Runtime Environment (build 1.7.0_07-b10) Java HotSpot(TM) 64-Bit Server VM (build 23.3-b01, mixed mode)
Java Insider
Let’s talk about java enterprise server applications. I always want to know what are the best or default JVM settings for a server application to start with in production? I read a lot on the web and tried several things myself and wanted to share what I found out:
Use “-server”: All 64-bit JVMs use the server VM as default. This setting generally optimizes the JVM for long running server applications instead of startup time. The JVM will collect more data about the Java byte code during program execution and generate the most efficient machine code via JIT.
The “-Xmx/-Xms” settings specify the maximum and minimum values for the JVM heap memory. For servers, both params should have the same value to avoid heap resizing during runtime.
Depending on your application, you will have to try out how much memory will be best suited for your application.
Java 8 has no “Permanent Generation” (PermGen) anymore but requires additional “Metaspace” memory instead. This memory is used, in addition to the heap memory we specified before, for storing class meta data information.
The default size will be unlimited – I tend to limit MaxMetaspaceSize with a somewhat high value. Just in case something goes wrong with the application, the JVM will not hog all the memory of the server.
Note: Let your application run for a couple of days to get a feeling for how much Metaspace Size it uses normally. Upon next restart of the application set the limit to e.g. double the value.
-XX:+CMSClassUnloadingEnabled
Additionally, you might want to allow the JVM to unload classes which are held in memory but no code is pointing to them any more. If your application generates lots of dynamic classes, this is what you want.
This option makes the JVM use the ConcurrentMarkSweepGC – It can do much work in parallel to program execution but in some circumstances a “full GC” with a “STW pause” might still occur. I’ve read many articles and came to the conclusion that this GC is still the best one for server workloads.
-XX:+CMSParallelRemarkEnabled
The option CMSParallelRemarkEnabled means the remarking is done in parallel to program execution – which is what you want if your server has many cores (and most servers do).
-XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=
Normally the GC will use heuristics to know when it’s time to clear memory. GC might kick in too late with default settings (causing full-Gcs).
Some sources say it might be a good idea to disable heuristics altogether and just use generation occupancy to start a CMS collection cycle. Setting values around 70% worked fine for all of my applications and use cases.
The first option tells the GC to first free memory by clearing out the “young generation” or fairly new objects before doing a full GC.
-XX:+CMSScavengeBeforeRemark
CMSScavengeBeforeRemark does attempt a minor collection before the CMS remark phase – thus keeping the remark pause afterwards short.
-XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses
The option “-XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses” is especially important if your application uses RMI (remote method invocation). The usage of RMI will cause the JVM to do a FULL-GC EVERY HOUR! This might be a very bad idea for large heap sizes because the FULL-GC pause might take up to several seconds. It would be better to do a concurrent GC and try to unload unused classes to free up more memory – which is exactly what the second option does.
-XX:+PrintGCDateStamps -verbose:gc -XX:+PrintGCDetails -Xloggc:""
These options shown here will write out all GC related information to a specified log file. You can see how well your GC configuration works by looking into it.
I personally prefer to use the “Visual GC” plug in for the “Visual VM” tool to monitor the general JVM and GC behavior.
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath='date'.hprof
When your JVM runs out of memory, you will want to know why. Since the OOM error might be hard to reproduce and you want to get your production server up and running again – you should specify a path for a heap dump. When things have settled down, you can analyze the dump afterwards.
-Djava.rmi.server.hostname= -Dcom.sun.management.jmxremote.port=
These options will help you to specify an IP and port for JMX – you will need those ports open to connect remotely to a JVM running on a server for tools like VisualVM. You can gain deep insights over CPU and memory usage, gc behaviour, class loading, thread count and usage of your application this way.
Lastly, I would like to recommend to you the VisualVM tool which is bundled with the Java 8 JDK. You can use it to gain more insights about your specific application behaviour on the JVM – like cpu and memory usage, thread utilisation and much more.
VisualVM can be extended with a plug in called “Visual GC”. It will briefly show you VERY detailed information about the usage of the young and old generation object spaces. You can easily spot problems with garbage collection simply by analyzing these graphs during application runtime.
Changing JVM in Java
I only recently discovered the different JVM’s on the wiki page and thought I’d start tinkering. Its been difficult to find documentation on how to configure Java on Ubuntu though. Lets say I wanted to change the JRE or JDK that I’m using, I could crack open a terminal and say
sudo update-alternatives --config java
And then pick from one of the installed versions. If I’m understanding JVM’s right (which I may very well be not), You can configure the openJDK to use alternative JVM’s (Eg JAMVM) and run it as such
2 questions, 1: Do i have the concept of a JVM right? As in, is this possible? 2: If so how do i configure the JVM and switch the default to a JVM of my choosing?
2 Answers 2
Feel free to use this as a reference to tinkering with Java at runtime.
Choosing your JRE
sudo update-alternatives --config java
This will give something like the following output.
Selection Path Priority Status ------------------------------------------------------------ 0 /usr/lib/jvm/java-6-openjdk/jre/bin/java 1061 auto mode * 1 /usr/lib/jvm/java-6-openjdk/jre/bin/java 1061 manual mode 2 /usr/lib/jvm/java-6-sun/jre/bin/java 63 manual mode 3 /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java 1051 manual mode
You can then select which Java runtime you want through the number selection.
Choosing your JVM
Sun/Oracle have two JVM choices, -server and -client. If you select the OpenJDK as your Java runtime environment you have additional options.
When you type java into the terminal with no other parameters, the help lists several optional VMs. I’m not sure which ones come with OpenJDK but 3 popular ones are JamVM, Zero and Cacao
java -jamvm 'your other parameters here' java -cacao 'your other parameters here' java -zero 'your other parameters here' java -server 'your other parameters here
The -server VM is normally the default. You can also specify -client but in 64-bit IcedTea6 it appears to run the same version as -server. There are most likely others but I find the default option to be the most responsive.
Setting your Memory
Finally, how to set the memory of Java (just because)
java -Xmx1024m -Xms128m 'your other parameters here'
This limits the memory allowed for the Java program to a maximum of 1024 MB, and sets its initial memory size to 128 MB. This is a great way of defining minimum system requirements. The Java 6 man page for the java command describes these options and others.
That’s all. If anyone has additional Java tweaks for Ubuntu then leave them in the comments and I’ll add them.