Есть ли реальная практическая разница между "java -server" и "java -client"?
Все, что я могу найти на сайте Sun, - расплывчатые
"-server starts slower but should run faster".
Какие настоящие отличия? (В настоящее время используется JDK 1.6.0_07.)




Я не заметил никакой разницы во времени запуска между двумя версиями, но с помощью «-сервера» (сервер Solaris, все использовали SunRays для запуска приложения) удалось добиться минимального улучшения производительности приложения. Это было меньше 1,5.
Дэн, у вас есть ссылка на это? Я хотел бы продолжить расследование.
Запуск Sunflow с серверной виртуальной машиной НАМНОГО быстрее, чем с клиентской. sunflow.sourceforge.net
IIRC серверная виртуальная машина выполняет больше оптимизаций точки доступа при запуске, поэтому она работает быстрее, но запускается немного дольше и использует больше памяти. Клиентская виртуальная машина откладывает большую часть оптимизации, чтобы ускорить запуск.
Отредактируйте, чтобы добавить: Вот некоторая информация от Sun, это не очень конкретно, но даст вам некоторые идеи.
IIRC, он включает в себя стратегии сборки мусора. Теоретически клиент и сервер будут отличаться короткоживущими объектами, что важно для современных алгоритмов сборки мусора.
Вот ссылка в серверном режиме. Увы, в них не упоминается клиентский режим.
Вот очень подробная ссылка на GC вообще; это более базовая статья. Не уверен, что адрес -сервер или -клиент, но это относящийся к делу материал.
В No Fluff Just Stuff Кен Сайп и Гленн Ванденбург отлично обсуждают подобные темы.
Это действительно связано с HotSpot и значения опционов по умолчанию (Параметры виртуальной машины Java HotSpot), которые различаются в зависимости от конфигурации клиента и сервера.
Из Глава 2 технического документа (Архитектура Java HotSpot Performance Engine):
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.
Итак, реальная разница также на уровне компилятора:
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.
Примечание: выпуск jdk6 обновление 10 (см. Примечания к выпуску обновления: изменения в 1.6.0_10) попытался улучшить время запуска, но по другой причине, чем параметры точки доступа, поскольку они были упакованы по-другому с гораздо меньшим ядром.
Г. Демеки указывает в комментариях, что в 64-битных версиях JDK параметр -client игнорируется в течение многих лет.
См. Команда Windows java:
-client
Selects the Java HotSpot Client VM.
A 64-bit capable JDK currently ignores this option and instead uses the Java Hotspot Server VM.
jdk6 update 10 и более поздние версии имеют фоновый процесс, сохраняющий библиотеки времени выполнения в памяти, что позволяет намного быстрее запускать новые процессы, чем загружать их все по запросу.
Думал, что клиентская vm также агрессивно встраивается, да ладно.
Думаю, этот ответ должен будет обновлен. Потому что в 64-битных версиях JDK параметр -client игнорируется в течение многих лет.
@ G.Demecki Конечно: есть ли у вас ссылка, подтверждающая, что эта опция устарела или игнорируется?
Конечно. Вот некоторая документация для Java 7 для Windows. И на удивление похожую информацию можно найти также в Java 6 документация.
@ G.Demecki Отлично! Я соответствующим образом отредактировал ответ.
@VonC Какой из них лучше для запуска Java-игры, такой как Minecraft
@SuiciDoga сейчас (2016) достаточно простой java (без сервера): minecraft.net/en/download/server. Но думаю, -server может помочь: lemire.me/blog/2016/04/02/…
@VonC это то же самое для клиента Майнкрафт? По умолчанию OpenJDK выбрал сервер, потому что он говорит, что у меня есть оборудование серверного уровня (но у меня просто ноутбук с AMD A8, а не сервер).
@SuiciDoga Этого я не знаю. Вы можете задать новый вопрос другим экспертам, чтобы высказать свое мнение.
Также в выходных данных запуска java для меня он говорит: -server для выбора "серверной" виртуальной машины. По умолчанию виртуальная машина является сервером, потому что вы работаете на машине серверного класса.
@rogerdpack Да, виртуальная машина по умолчанию - сервер. Мне нужно проверить только Oracle JDK 8. Интересно, изменился ли дисплей с более свежим OpenJDK (10, 12, ...)
Одно отличие, которое я только что заметил, заключается в том, что в «клиентском» режиме кажется, что JVM фактически возвращает некоторую неиспользованную память операционной системе, тогда как в «серверном» режиме, как только JVM захватывает память, она не передает ее. назад. Так оно и есть в Solaris с Java6 (используя prstat -Z для просмотра объема памяти, выделенной процессу).
Наиболее заметным непосредственным различием в старых версиях Java будет память, выделенная для -client, а не для приложения -server. Например, в моей системе Linux я получаю:
$ 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"
поскольку по умолчанию используется -server, но с опцией -client я получаю:
$ 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"
поэтому с -server большинство ограничений памяти и начальных выделений намного выше для этой версии java.
Однако эти значения могут изменяться для различных комбинаций архитектуры, операционной системы и версии jvm. В последних версиях jvm убраны флаги и убраны многие различия между сервером и клиентом.
Помните также, что вы можете увидеть все детали работающего jvm с помощью jvisualvm. Это полезно, если у вас есть пользователи или модули, которые устанавливают JAVA_OPTS, или используют сценарии, изменяющие параметры командной строки. Это также позволит вам в реальном времени отслеживать использование пространства куча и пермген вместе с множеством другой статистики.
Он дает мне те же числа в режимах -server и -client для версии java "1.7.0_79" в CentOS 7 [Java (TM) SE Runtime Environment (build 1.7.0_79-b15) Java HotSpot ™ (TM) 64-разрядная серверная виртуальная машина ]
Вот почему я дал ответ. Дело не в ценностях, а в том, чтобы позволить кому угодно в любое время найти ответ для своей конкретной версии jvm.
В интерактивной документации Oracle содержится некоторая информация по Java SE 7.
На странице java - средство запуска Java-приложений для Windows параметр -client игнорируется в 64-битном JDK:
Select the Java HotSpot Client VM. A 64-bit capable jdk currently ignores this option and instead uses the Java HotSpot Server VM.
Однако (чтобы было интересно) в -server говорится:
Select the Java HotSpot Server VM. On a 64-bit capable jdk only the Java HotSpot Server VM is supported so the -server option is implicit. This is subject to change in a future release.
На странице Обнаружение машин серверного класса представлена информация о том, какая виртуальная машина выбрана ОС и архитектурой.
Я не знаю, насколько это применимо к JDK 6.
Спасибо, мне было интересно, почему я не увидел client / jvm.dll на JDK7
В прошлый раз, когда я взглянул на это (и, по общему признанию, это было некоторое время назад), самая большая разница, которую я заметил, была в сборке мусора.
IIRC:
Если вы можете сравнить две виртуальные машины Java, один клиент и один сервер с помощью инструмента jvisualvm, вы должны увидеть разницу в частоте и эффекте сборки мусора, а также в количестве поколений.
У меня была пара скриншотов, которые действительно хорошо показали разницу, но я не могу воспроизвести, поскольку у меня есть 64-битная JVM, которая реализует только виртуальную машину сервера. (И я не могу беспокоиться о том, чтобы загрузить 32-битную версию и попробовать ее в моей системе.)
Похоже, что это уже не так, попробовав запустить какой-то код в Windows как с серверными, так и с клиентскими виртуальными машинами, я, похоже, получил одну и ту же модель генерации для обоих ...
При выполнении миграции с версии 1.4 на версию 1.7 ("1.7.0_55"). То, что мы здесь наблюдали, заключается в том, что нет таких различий в значениях по умолчанию, присвоенных параметрам heapsize | permsize | ThreadStackSize в режиме клиента и сервера.
Кстати, (http://www.oracle.com/technetwork/java/ergo5-140223.html). Это фрагмент, взятый из ссылки выше.
initial heap size of 1/64 of physical memory up to 1Gbyte
maximum heap size of ¼ of physical memory up to 1Gbyte
ThreadStackSize выше в версии 1.7, хотя на форуме Open JDK есть обсуждения, в которых указано, что размер кадра несколько выше в версии 1.7. Считается, что реальную разницу можно будет измерить во время выполнения на основе вашего поведения вашего приложения.
системы -client и -server - это разные двоичные файлы. По сути, это два разных компилятора (JIT), взаимодействующих с одной и той же системой времени выполнения. Клиентская система оптимальна для приложений, которым требуется быстрое время запуска или небольшая занимаемая площадь, серверная система оптимальна для приложений, где общая производительность наиболее важна. В целом клиентская система лучше подходит для интерактивных приложений, таких как графические интерфейсы.
Мы запускаем следующий код с обоими переключателями:
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--) {
}
}
}
Примечание: Код компилируется только один раз! Классы одинаковые в обоих прогонах!
С -клиентом:
java.exe -client -classpath C: \ mywork \ classes com.blogspot.sdoulger.LoopTest
Проведено времени: 766
С -сервером:
java.exe -server -classpath C: \ mywork \ classes com.blogspot.sdoulger.LoopTest
Затраченное время: 0
Похоже, что при более агрессивной оптимизации серверной системы удаляем цикл, так как он понимает, что он не выполняет никаких действий!
От Goetz - Параллелизм Java на практике:
- Debugging tip: For server applications, be sure to always specify the
-serverJVM command line switch when invoking the JVM, even for development and testing. The server JVM performs more optimization than the client JVM, such as hoisting variables out of a loop that are not modified in the loop; code that might appear to work in the development environment (client JVM) can break in the deployment environment (server JVM). For example, had we “forgotten” to declare the variable asleep as volatile in Listing 3.4, the server JVM could hoist the test out of the loop (turning it into an infinite loop), but the client JVM would not. An infinite loop that shows up in development is far less costly than one that only shows up in production.Listing 3.4. Counting sheep.
volatile boolean asleep; ... while (!asleep) countSomeSheep();
Мой акцент. YMMV
Зависит от того, что делает ваша программа. Для некоторых приложений, интенсивно использующих процессор, которые делают одно и то же неоднократно, я заметил улучшения огромный (до 10x) с -server.