Real differences between "java -server" and "java -client"?
This is really linked to HotSpot and the default option values (Java HotSpot VM Options) which differ between client and server configuration.
From Chapter 2 of the whitepaper (The Java HotSpot Performance Engine Architecture):
The JDK includes two flavors of the VM -- a client-side offering, and a VM tuned for server applications. These two solutions share the Java HotSpot runtime environment code base, but use different compilers that are suited to the distinctly unique performance characteristics of clients and servers. These differences include the compilation inlining policy and heap defaults.
Although the Server and the Client VMs are similar, the Server VM has been specially tuned to maximize peak operating speed. It is intended for executing long-running server applications, which need the fastest possible operating speed more than a fast start-up time or smaller runtime memory footprint.
The Client VM compiler serves as an upgrade for both the Classic VM and the just-in-time (JIT) compilers used by previous versions of the JDK. The Client VM offers improved run time performance for applications and applets. The Java HotSpot Client VM has been specially tuned to reduce application start-up time and memory footprint, making it particularly well suited for client environments. In general, the client system is better for GUIs.
So the real difference is also on the compiler level:
The Client VM compiler does not try to execute many of the more complex optimizations performed by the compiler in the Server VM, but in exchange, it requires less time to analyze and compile a piece of code. This means the Client VM can start up faster and requires a smaller memory footprint.
The Server VM contains an advanced adaptive compiler that supports many of the same types of optimizations performed by optimizing C++ compilers, as well as some optimizations that cannot be done by traditional compilers, such as aggressive inlining across virtual method invocations. This is a competitive and performance advantage over static compilers. Adaptive optimization technology is very flexible in its approach, and typically outperforms even advanced static analysis and compilation techniques.
Note: The release of jdk6 update 10 (see Update Release Notes:Changes in 1.6.0_10) tried to improve startup time, but for a different reason than the hotspot options, being packaged differently with a much smaller kernel.
G. Demecki points out in the comments that in 64-bit versions of JDK, the -client
option is ignored for many years.
See Windows java
command:
-client
Selects the Java HotSpot Client VM.
A 64-bit capable JDK currently ignores this option and instead uses the Java Hotspot Server VM.
2022: Holger references in the comments the JavaSE6 / Server-Class Machine Detection, adding:
Only on 32 bit Windows systems,
-client
was ever chosen unconditionally.
Other systems checked whether the machine was “server class” which was fulfilled when having at least 2 cores and at least 2GiB of memory.Which explains why almost everything uses
-server
for quite some time now. Even the cheapest computers you can find, are “server class” machines. The Sun/Oracle 64 builds did not even ship with a client JVM.
The most visible immediate difference in older versions of Java would be the memory allocated to a -client
as opposed to a -server
application. For instance, on my Linux system, I get:
$ java -XX:+PrintFlagsFinal -version 2>&1 | grep -i -E 'heapsize|permsize|version'
uintx AdaptivePermSizeWeight = 20 {product}
uintx ErgoHeapSizeLimit = 0 {product}
uintx InitialHeapSize := 66328448 {product}
uintx LargePageHeapSizeThreshold = 134217728 {product}
uintx MaxHeapSize := 1063256064 {product}
uintx MaxPermSize = 67108864 {pd product}
uintx PermSize = 16777216 {pd product}
java version "1.6.0_24"
as it defaults to -server
, but with the -client
option I get:
$ java -client -XX:+PrintFlagsFinal -version 2>&1 | grep -i -E 'heapsize|permsize|version'
uintx AdaptivePermSizeWeight = 20 {product}
uintx ErgoHeapSizeLimit = 0 {product}
uintx InitialHeapSize := 16777216 {product}
uintx LargePageHeapSizeThreshold = 134217728 {product}
uintx MaxHeapSize := 268435456 {product}
uintx MaxPermSize = 67108864 {pd product}
uintx PermSize = 12582912 {pd product}
java version "1.6.0_24"
so with -server
most of the memory limits and initial allocations are much higher for this java
version.
These values can change for different combinations of architecture, operating system and jvm version however. Recent versions of the jvm have removed flags and re-moved many of the distinctions between server and client.
Remember too that you can see all the details of a running jvm
using jvisualvm
. This is useful if you have users who or modules which set JAVA_OPTS
or use scripts which change command line options. This will also let you monitor, in real time, heap and permgen space usage along with lots of other stats.
the -client and -server systems are different binaries. They are essentially two different compilers (JITs) interfacing to the same runtime system. The client system is optimal for applications which need fast startup times or small footprints, the server system is optimal for applications where the overall performance is most important. In general the client system is better suited for interactive applications such as GUIs
We run the following code with both switches:
package com.blogspot.sdoulger;
public class LoopTest {
public LoopTest() {
super();
}
public static void main(String[] args) {
long start = System.currentTimeMillis();
spendTime();
long end = System.currentTimeMillis();
System.out.println("Time spent: "+ (end-start));
LoopTest loopTest = new LoopTest();
}
private static void spendTime() {
for (int i =500000000;i>0;i--) {
}
}
}
Note: The code is been compiled only once! The classes are the same in both runs!
With -client:
java.exe -client -classpath C:\mywork\classes com.blogspot.sdoulger.LoopTest
Time spent: 766
With -server:
java.exe -server -classpath C:\mywork\classes com.blogspot.sdoulger.LoopTest
Time spent: 0
It seems that the more aggressive optimazation of the server system, remove the loop as it understands that it does not perform any action!
Reference