Determine process id
First we determine the process id(s) of the running Tomcat instance(s).
We can grep the running process list for ‘catalina.home’:
pgrep -f 'catalina.home'
This might yield more than one pid.
Or we can search by port (8080 is the default, adjust if necessary). The following commands will likely require root privileges:
lsof -t -i :8080
Alternatively, for example if lsof is not installed:
Or yet another way, using netstat (or its “ss” replacement):
netstat -nlp | grep 8080
ss -nlp | grep 8080
For the process id(s) determined above, we look at process details:
ps -o pid,uid,cmd -p [pidlist] | cat
For each specified pid, this shows the uid (system user) and the full command line of the process.
Typically the command line will contain something like “-Dcatalina.home=[path]” and that path is the catalina.home system property of the Java process.
Alternatively – with Java 7 and later – we can use the JDK command “jcmd” to query the JVM process for its system properties:
sudo -u [uid] jcmd [pid] VM.system_properties \ | grep '^catalina.home' \ | cut -f2 -d'='
Now we can finally determine which Tomcat version is installed under the catalina.home path:
[catalina.home]/bin/catalina.sh version \ | grep '^Server number:'
Note: Please replace
[catalina.home] with the path you determined above.
The final output should be something like this:
Server number: 126.96.36.199
An old wisdom says that Software can be optimized for latency, throughput or footprint. The same is true for the JVM and its Garbage Collector(s).
Roughly speaking, the classic GC implementations each optimize for one aspect: Serial GC optimizes footprint, Parallel GC optimizes throughput and Concurrent Mark and Sweep (CMS) optimizes for response times and minimal GC induced latency.
But since JDK7u4, we officially have the “Garbage First” (G1) GC. It is still new enough to not even have its own Wikipedia article, but there are good introductory tutorials, articles and tuning guides.
In several ways, G1 is a step up from the conventional GC approaches: It uses non-contiguous heap regions instead of contiguous young and old generations and does most of its reclamation through copying of the live data, thus achieving compaction.
It is based on the principle of collecting the most garbage first and designed with scalability in mind, without compromising throughput.
The benefits of G1 have lead to a proposal and lively debate about Defaulting to G1 Garbage Collector in Java 9.
In conclusion, you can either take the easy path and use the default JVM settings or take some time to learn about modern GC choices and tuning options.
And if you get it all right you might be rewarded with your Java based services performing better than ever before … :)