Developing and Deploying Java SE-Based Applications in Solaris
January 21 - January 25, 2008
Experts: David Dice, Alan Bateman, and Valerie Peng
In this Ask the Experts session, Sun engineers Dave Dice, Alan Bateman, and Valerie Peng answered a variety of questions about developing and deploying Java SE applications in Solaris.
Serena H.: I have a web application that services a lot of SSL/TLS connections. Can JSSE
make use of the hardware assisted acceleration on T1 and T2 machines?
Valerie Peng: The answer is yes. Java applications can take advantage of the performance boost provided by the
built-in hardware acceleration without any code or configuration changes. Just run the apps as usual and it should work just
like that. What happens underneath is that JSSE goes through Java Cryptography Architecture (JCA) to locate the
cryptographic provider(s) that it needs. On Solaris 10, the SunPKCS#11 provider is pre-configured to be the most
preferred cryptographic provider of JCA, and when used, it accesses the native PKCS#11 tokens such as hardware
cryptographic accelerators to complete the requested cryptographic operations.
Marek Fus: When running my application under Solaris 9.0 OS I experience huge memory occupation after
a few hours. Applications start with memory usage about 300MB but after 12-16 hrs jconsole shows the Current heap size
and Committed memory ~2GB. The problem is not observable when the same application is run under MS Windows. Why is memory
occupation so big under Solaris?
Alan Bateman: There are a number of possibilities here. It would be great to know which JDK and what command line
arguments are used here. It would also be useful to know if the application fails with OutOfMemoryError when the Java heap
grows to 2GB.
One possibility is that the Solaris machine is a "server-class" machine. Since J2SE 5.0, the compiler, collector,
and heap settings are configured at start up based on the type of machine. A server-class machine (defined as >= 2 CPUs
and >= 2GB memory) has its maximum heap size set to 1/4 of the physical memory or 1GB (whichever is smaller). This tuning
(or ergonomics as it is called) isn't implemented on Windows so it is possible you are running with the client VM and
a 64MB heap on Windows. See Garbage
Collector Ergonomics for more information about this topic.
Your question did mention 2GB but perhaps you meant 1GB. If it is 2GB then it may not be ergonomics related but it would
still be interesting to see if you have -mx or other heap sizing arguments on the command line.
The other possibility is of course a memory leak. Does the application eventually fail with OutOfMemoryError? If so then
either it needs a larger maximum heap or you have a leak. The option is useful
for such cases. This option (which has no performance penalty unless OOME is thrown) causes the HotSpot VM to generate
a heap dump when OOME is thrown. The resulting heap dump can be analyzed by a number of different tools. The heap dump
can be transported to other machines for analysis if you don't have any analyzers installed locally. One such tool is
jhat that ships in JDK6. That tool can be used to analyze heap dumps from 1.4.2, 5.0, or 6.0. Another useful
utility is jmap in JDK6. jmap -histo <pid> provides a summary of objects in the heap as
a class-wise histogram. That is often very useful to get a quick picture on the objects that are consuming the memory.
If you look at the man page for this utility you will see that you can have it do a full GC before the histogram is
printed so that you only get a summary of the "live" objects in the heap.
Erik Pearson: We tend to run 32-bit JVMs on sparcv9 hardware out of habit. Without getting into
application specifics, should we start examining the 64-bit JVM by default? What criteria should be used to select the JVM?
Dave Dice: On SPARC you're better off with a 32-bit JVM unless the process running the JVM requires
a virtual address space greater than 4GB. The major consumers of virtual address space are the Java heap itself
and Java thread stacks. Either one can push you from using a 32-bit JVM to a 64-bit JVM. Processor data caches are
a fixed size regardless of whether you're running 32-bit or 64-bit code, so a 32-bit JVM is somewhat preferable for
performance, as pointers (object references) are 32-bits, allowing the cache to contain more objects and their fields
in 32-bit mode.
Bharath Ravi Kumar: Is there an accurate way of finding out the exact memory footprint of a Java SE
application on Solaris? I found the need to carry out this measurement a year ago and had a lot of difficulty
interpreting/correlating the data from pmap and jmap -heap. It took a lot of help from Java SE engineers Steve Bohne
and Dave Dice before I could reasonably estimate the overall footprint of my Java application. The calculation gets
more complex with a global Java SE instance shared across Solaris Zones.
This is a topic that requires more explanation (in the form of a blog or other documentation)
and probably an enhancement to an existing diagnostic tool to plot the memory map (in terms
of various generations) that is more consistent with the operating systems's overall view of
the application's memory.
Dave Dice: Thanks for the question. I'll contact Steve Bohne
to see if he might augment his blog
content on that topic, which at the moment is largely Windows-specific. Measuring memory footprint on most
modern operating systems -- even for simple "C"applications, let alone a JVM -- is a challenge as
interpreting the output from the tools requires too much understanding of the memory management subsystems,
at least for my taste. Process- level memory metrics, while useful, don't easily compose or tally up to form
a consistent view of aggregate system use. Taking a step back, we typically want to use tools such as pmap,
etc., as a guide for capacity planning or perhaps to diagnose performance issues. For the most part, we want to predict
how many or which processes we can add to our system before it'll (a) start to swap, or (b) encounter complete memory
exhaustion. (Equivalently, we might ask how much memory we might want to add to support a given workload). Ideally,
we'd use the tools and do the math. Instead, however, I'd suggest a slightly cruder but more direct approach: add processes
incrementally; warm up each new application as needed; measure system memory pressure with vmstat and
swap -s. This will tell you how close the system is to swapping. Once you've captured a few data
points you can extrapolate safely.
For inspection of memory use within a JVM I recommend jconsole or jmap.