Максимальный размер кучи Java 32-разрядной JVM в 64-разрядной ОС

Вопрос не в максимальном размере кучи на 32-битной ОС, учитывая, что 32-разрядные ОС имеют максимальный адресный размер памяти 4 ГБ и что максимальный размер кучи JVM зависит от того, насколько непрерывна свободная память может быть зарезервирован.

Мне больше интересно узнать максимальный (как теоретический, так и практически достижимый) размер кучи для 32-разрядной JVM, работающей в 64-разрядной ОС. В основном, я смотрю на ответы, похожие на цифры в соответствующем вопросе на SO.

Что касается использования 32-разрядной JVM вместо 64-разрядной, причина не техническая, а скорее административная/бюрократическая - возможно, слишком поздно установить 64-разрядную JVM в производственной среде.

Ответ 1

32-разрядные JVM, которые ожидают иметь один большой кусок памяти и использовать необработанные указатели, не могут использовать более 4 Гб (поскольку это 32-разрядный предел, который также применяется к указателям). Это включает в себя Sun и - я уверен, - также внедрения IBM. Я не знаю, если, например, JRockit или другие имеют большой вариант памяти со своими 32-разрядными реализациями.

Если вы планируете использовать этот предел, вам следует подумать о начале параллельной проверки подлинности 64-разрядной JVM для вашей производственной среды, чтобы у вас была такая готовность, когда 32-разрядная среда распадается. В противном случае вам придется делать эту работу под давлением, что никогда не бывает приятным.


Изменить 2014-05-15: Часто задаваемые вопросы по Oracle:

Максимальный теоретический предел кучи для 32-разрядной JVM равен 4G. Из-за различных дополнительных ограничений, таких как доступный обмен, использование адресного пространства ядра, фрагментация памяти и накладные расходы VM, на практике предел может быть значительно ниже. В большинстве современных 32-битных систем Windows максимальный размер кучи будет варьироваться от 1,4 ГГц до 1,6 ГГц. В 32-битных ядрах Solaris адресное пространство ограничено 2G. В 64-битных операционных системах с 32-разрядной виртуальной машиной максимальный размер кучи может быть выше, приближаясь к 4G во многих системах Solaris.

(http://www.oracle.com/technetwork/java/hotspotfaq-138619.html#gc_heap_32bit)

Ответ 2

Вы можете задать Java Runtime:

public class MaxMemory {
    public static void main(String[] args) {
        Runtime rt = Runtime.getRuntime();
        long totalMem = rt.totalMemory();
        long maxMem = rt.maxMemory();
        long freeMem = rt.freeMemory();
        double megs = 1048576.0;

        System.out.println ("Total Memory: " + totalMem + " (" + (totalMem/megs) + " MiB)");
        System.out.println ("Max Memory:   " + maxMem + " (" + (maxMem/megs) + " MiB)");
        System.out.println ("Free Memory:  " + freeMem + " (" + (freeMem/megs) + " MiB)");
    }
}

Это сообщит о "максимальной памяти", основанной на распределении кучи по умолчанию. Таким образом, вам все равно придется играть с -Xmx (на HotSpot). Я обнаружил, что, работая на 64-битной Windows 7 Enterprise, моя 32-битная JSM HotSpot может выделять до 1577MiB:

[C:scratch]> java -Xmx1600M MaxMemory
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.
[C:scratch]> java -Xmx1590M MaxMemory
Total Memory: 2031616 (1.9375 MiB)
Max Memory:   1654456320 (1577.8125 MiB)
Free Memory:  1840872 (1.75559234619 MiB)
[C:scratch]>

В то время как с 64-битной JVM на той же ОС, конечно, она намного выше (около 3TiB)

[C:scratch]> java -Xmx3560G MaxMemory
Error occurred during initialization of VM
Could not reserve enough space for object heap
[C:scratch]> java -Xmx3550G MaxMemory
Total Memory: 94240768 (89.875 MiB)
Max Memory:   3388252028928 (3184151.84297 MiB)
Free Memory:  93747752 (89.4048233032 MiB)
[C:scratch]>

Как уже упоминалось, это зависит от ОС.

  • Для 32-разрядной версии Windows: она будет < 2GB (внутренняя книга Windows говорит 2GB для пользовательских процессов)
  • Для 32-разрядного BSD/Linux: < 3GB (из книги дьявола)
  • Для 32-разрядного MacOS X: < 4GB (из внутренняя книга Mac OS X)
  • Не уверен в 32-разрядной Solaris, попробуйте приведенный выше код и сообщите нам.

Для 64-битной ОС хоста, если JVM 32-разрядная, она все равно будет зависеть, скорее всего, как показано выше.

- ОБНОВЛЕНИЕ 20110905. Я просто хотел указать на некоторые другие наблюдения/подробности:

  • Аппаратное обеспечение, на котором я работал, было 64-битным с установленной 6 ГБ оперативной памяти. Операционная система была Windows 7 Enterprise, 64-разрядная
  • Фактическое количество Runtime.MaxMemory, которое может быть выделено, также зависит от рабочего набора операционной системы. Я когда-то запускал это, пока я также запускал VirtualBox и обнаружил, что не смог успешно запустить JVM HotSpot с помощью -Xmx1590M и должен был уменьшиться. Это также означает, что вы можете получить больше 1590M в зависимости от вашего рабочего размера в то время (хотя я все еще поддерживаю, что он будет находиться под 2GiB для 32-битных из-за дизайна Windows).

Ответ 3

Вы не укажете, какую ОС.

В Windows (для моего приложения - давно работающего приложения для управления рисками) мы заметили, что мы можем идти не дальше 1280 МБ на Windows 32bit. Я сомневаюсь, что запуск 32-битной JVM под 64 бит будет иметь какое-то значение.

Мы портировали приложение в Linux, и мы работаем на 32-битной JVM на 64-битном аппаратном обеспечении и имеем 2,2 ГБ виртуальную машину, которая работает довольно легко.

Самая большая проблема, с которой вы можете столкнуться, - GC в зависимости от того, для чего вы используете память.

Ответ 4

Из 4.1.2 Размер кучи:

"Для 32-разрядной модели процесса максимальный размер виртуального адреса процесс обычно составляет 4 ГБ, хотя некоторые операционные системы ограничивают это 2 ГБ или 3 ГБ. Максимальный размер кучи обычно составляет -Xmx3800m (1600 м) для 2 ГБ), хотя фактическое ограничение зависит от приложения. Для 64-битных моделей процессов максимальный размер по существу неограничен.

Нашел здесь довольно хороший ответ: максимальная память Java в Windows XP.

Ответ 5

Недавно у нас был некоторый опыт. Недавно мы портировали Solaris (x86-64 Version 5.10) на Linux (RedHat x86-64) и поняли, что у нас меньше памяти для 32-разрядного JVM-процесса в Linux, чем Solaris.

Для Solaris это почти доходит до 4 ГБ (http://www.oracle.com/technetwork/java/hotspotfaq-138619.html#gc_heap_32bit).

Мы запустили наше приложение с -Xms2560m -Xmx2560m -XX: MaxPermSize = 512m -XX: PermSize = 512m без проблем в Solaris в течение последних нескольких лет. Пытался переместить его в Linux, и у нас были проблемы с случайными ошибками памяти при запуске. Мы могли бы заставить его последовательно запускать на -Xms2300 -Xmx2300. Затем нам сообщили об этом при поддержке.

32-разрядный процесс в Linux имеет максимальное адресное адресное пространство 3gb (3072mb), тогда как на Solaris полный 4gb (4096mb).

Ответ 6

Ограничения 32-разрядной JVM на 64-разрядной ОС будут точно такими же, как ограничения 32-разрядной JVM на 32-разрядной ОС. В конце концов, 32-разрядная JVM будет запущена на 32-битной виртуальной машине (в смысле виртуализации), поэтому она не будет знать, что она работает на 64-битной ОС/машине.

Единственным преимуществом для запуска 32-разрядной JVM в 64-разрядной ОС по сравнению с 32-разрядной ОС является то, что у вас может быть больше физической памяти, и поэтому она будет чаще встречаться с подкачкой/страницей. Однако это преимущество действительно реализовано только тогда, когда у вас есть несколько процессов.

Ответ 7

Что касается использования 32-разрядной JVM вместо 64-разрядной, причина не техническая, а скорее административная/бюрократическая...

Когда я работал в BEA, мы обнаружили, что среднее приложение на самом деле выполнялось медленнее в 64-разрядной JVM, а затем оно выполнялось при работе в 32-разрядной JVM. В некоторых случаях производительность достигала 25% медленнее. Таким образом, если вашему приложению не нужна вся эта дополнительная память, вам лучше настроить более 32-разрядные серверы.

Насколько я помню, три наиболее распространенных технических обоснования для использования 64-битного персонала, на котором столкнулись сотрудники службы технической поддержки BEA, были:

  • Приложение манипулировало несколькими массивными изображениями,
  • Приложение делало массивный хруст числа,
  • У приложения была утечка памяти, клиент был премьер на правительственный контракт, и они не хотели тратить время и расходы на отслеживание утечки памяти. (Использование массивной памяти куча увеличит MTBF, и премьер будет получать деньги)

.

Ответ 8

JVM JROCKIT, в настоящее время принадлежащий Oracle, поддерживает несмежное использование кучи, что позволяет 32-битной JVM получить доступ к более чем 3,8 ГБ памяти, когда JVM работает на 64-битной ОС Windows. (2,8 ГБ при работе на 32-битной ОС).

http://blogs.oracle.com/jrockit/entry/how_to_get_almost_3_gb_heap_on_windows

JVM можно свободно загрузить (требуется регистрация) в

http://www.oracle.com/technetwork/middleware/jrockit/downloads/index.html

Ответ 9

Вот несколько тестов в 64-разрядной версии Solaris и Linux

Solaris 10 - машина SPARC - T5220 с 32 ГБ оперативной памяти (и около 9 ГБ бесплатно)

$ java -XX:PermSize=128M -XX:MaxPermSize=256M -Xms512m -Xmx3750m MaxMemory
Error occurred during initialization of VM
Could not reserve space for ObjectStartArray
$ java -XX:PermSize=128M -XX:MaxPermSize=256M -Xms512m -Xmx3700m MaxMemory
Total Memory: 518520832 (494.5 MiB)
Max Memory:   3451912192 (3292.0 MiB)
Free Memory:  515815488 (491.91998291015625 MiB)
Current PID is: 28274
Waiting for user to press Enter to finish ...

$ java -version
java version "1.6.0_30"
Java(TM) SE Runtime Environment (build 1.6.0_30-b12)
Java HotSpot(TM) Server VM (build 20.5-b03, mixed mode)

$ which java
/usr/bin/java
$ file /usr/bin/java
/usr/bin/java: ELF 32-bit MSB executable SPARC Version 1, dynamically linked, not stripped, no debugging information available

$ prstat -p 28274
   PID USERNAME  SIZE   RSS STATE  PRI NICE      TIME  CPU PROCESS/NLWP
28274 user1     670M   32M sleep   59    0   0:00:00 0.0% java/35

BTW: По-видимому, Java не выделяет много фактической памяти при запуске. Похоже, что для запуска всего около 100 МБ (я начал 10)

Solaris 10 - x86 - VMWare VM с 8 ГБ оперативной памяти (около 3 ГБ бесплатно *)

Свободная ОЗУ 3 ГБ на самом деле не так. Существует большой кусок ОЗУ, который использует кеш-память ZFS, но у меня нет корневого доступа, чтобы проверить, насколько точно

$ java -XX:PermSize=128M -XX:MaxPermSize=256M -Xms512m -Xmx3650m MaxMemory
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.

$ java -XX:PermSize=128M -XX:MaxPermSize=256M -Xms512m -Xmx3600m MaxMemory
Total Memory: 516423680 (492.5 MiB)
Max Memory:   3355443200 (3200.0 MiB)
Free Memory:  513718336 (489.91998291015625 MiB)
Current PID is: 26841
Waiting for user to press Enter to finish ...

$ java -version
java version "1.6.0_41"
Java(TM) SE Runtime Environment (build 1.6.0_41-b02)
Java HotSpot(TM) Server VM (build 20.14-b01, mixed mode)

$ which java
/usr/bin/java

$ file /usr/bin/java
/usr/bin/java:  ELF 32-bit LSB executable 80386 Version 1 [FPU], dynamically linked, not stripped, no debugging information available

$ prstat -p 26841
   PID USERNAME  SIZE   RSS STATE  PRI NICE      TIME  CPU PROCESS/NLWP
26841 user1     665M   22M sleep   59    0   0:00:00 0.0% java/12

RedHat 5.5 - x86 - VMWare VM с 4 ГБ оперативной памяти (около 3,8 ГБ - 200 МБ в буферах и 3,1 ГБ в кешках, около 3 ГБ бесплатно)

$ alias java='$HOME/jre/jre1.6.0_34/bin/java'

$ java -XX:PermSize=128M -XX:MaxPermSize=256M -Xms512m -Xmx3500m MaxMemory
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.

$ java -XX:PermSize=128M -XX:MaxPermSize=256M -Xms512m -Xmx3450m MaxMemory
Total Memory: 514523136 (490.6875 MiB)
Max Memory:   3215654912 (3066.6875 MiB)
Free Memory:  511838768 (488.1274871826172 MiB)
Current PID is: 21879
Waiting for user to press Enter to finish ...

$ java -version
java version "1.6.0_34"
Java(TM) SE Runtime Environment (build 1.6.0_34-b04)
Java HotSpot(TM) Server VM (build 20.9-b04, mixed mode)

$ file $HOME/jre/jre1.6.0_34/bin/java
/home/user1/jre/jre1.6.0_34/bin/java: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), for GNU/Linux 2.2.5, not stripped

$ cat /proc/21879/status | grep ^Vm
VmPeak:  3882796 kB
VmSize:  3882796 kB
VmLck:         0 kB
VmHWM:     12520 kB
VmRSS:     12520 kB
VmData:  3867424 kB
VmStk:        88 kB
VmExe:        40 kB
VmLib:     14804 kB
VmPTE:        96 kB

Тот же самый аппарат с использованием JRE 7

$ alias java='$HOME/jre/jre1.7.0_21/bin/java'

$ java -XX:PermSize=128M -XX:MaxPermSize=256M -Xms512m -Xmx3500m MaxMemory
Error occurred during initialization of VM
Could not reserve enough space for object heap
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.

$ java -XX:PermSize=128M -XX:MaxPermSize=256M -Xms512m -Xmx3450m MaxMemory
Total Memory: 514523136 (490.6875 MiB)
Max Memory:   3215654912 (3066.6875 MiB)
Free Memory:  511838672 (488.1273956298828 MiB)
Current PID is: 23026
Waiting for user to press Enter to finish ...

$ java -version
java version "1.7.0_21"
Java(TM) SE Runtime Environment (build 1.7.0_21-b11)
Java HotSpot(TM) Server VM (build 23.21-b01, mixed mode)

$ file $HOME/jre/jre1.7.0_21/bin/java
/home/user1/jre/jre1.7.0_21/bin/java: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped

$ cat /proc/23026/status | grep ^Vm
VmPeak:  4040288 kB
VmSize:  4040288 kB
VmLck:         0 kB
VmHWM:     13468 kB
VmRSS:     13468 kB
VmData:  4024800 kB
VmStk:        88 kB
VmExe:         4 kB
VmLib:     10044 kB
VmPTE:       112 kB

Ответ 10

Должно быть намного лучше

Для 32-разрядной JVM, запущенной на 64-битном хосте, я полагаю, что оставшееся после кучи будет тем, что безразличное виртуальное пространство доступно после JVM, у него есть библиотеки DLL, а любая совместимая с 32-разрядной совместимостью с OS 32 были загружены. Как дикая догадка, я думаю, что 3GB должно быть возможно, но насколько это лучше, зависит от того, насколько хорошо вы работаете на 32-битной площадке.

Кроме того, даже если вы могли бы создать гигантскую кучу 3 ГБ, вы, возможно, не захотите, так как это приведет к тому, что паузы GC станут потенциально неприятными. Некоторые люди просто запускают больше JVM, чтобы использовать дополнительную память, а не одну гигантскую. Я думаю, они настраивают JVM прямо сейчас, чтобы работать лучше с гигантскими кучами.

Немного сложно узнать, насколько лучше вы можете это сделать. Я думаю, что ваша 32-битная ситуация может быть легко определена экспериментом. Конечно, трудно предсказать абстрактно, так как в нем много факторов, особенно потому, что виртуальное пространство, доступное на 32-битных хостах, довольно ограничено. Куча должна существовать в смежной виртуальной памяти, поэтому фрагментация адресного пространства для dll и внутреннее использование адресного пространства ядром ОС определит диапазон возможных распределений.

ОС будет использовать некоторое адресное пространство для отображения HW-устройств и собственные динамические распределения. Хотя эта память не отображается в адресное пространство процесса Java, ядро ​​ОС не может одновременно обращаться к нему и к вашему адресному пространству, поэтому оно ограничивает размер любого виртуального пространства программы.

Загрузка DLL зависит от реализации и выпуска JVM. Загрузка ядра ОС зависит от огромного количества вещей, выпуска, HW, сколько вещей он отобразил до сих пор с момента последней перезагрузки, кто знает...

В заключение

Бьюсь об заклад, вы получаете 1-2 ГБ в 32-битной стране и около 3 в 64-битных, поэтому общее улучшение примерно 2x.

Ответ 11

В Solaris предел составлял около 3,5 ГБ, поскольку Solaris 2.5. (около 10 лет назад)

Ответ 12

У меня были те же проблемы с JVM, что и приложение Inventor для Android Blocks Editor. Он устанавливает кучу на максимальном уровне 925 м. Этого недостаточно, но я не мог установить его более чем на 1200 м, в зависимости от различных случайных факторов на моей машине.

Я загрузил Nightly, бета-версию 64-битного браузера из Firefox, а также версию JAVA 7 с 64-разрядной версией.

Я еще не нашел свой новый предел кучи, но я только что открыл JVM с размером кучи 5900 м. Нет проблем!

Я запускаю Win 7 64-бит Ultimate на машине с 24-гигабайтной оперативной памятью.

Ответ 13

Я попытался установить размер кучи до 2200M на 32-битной Linux-машине, и JVM работал нормально. JVM не запускался, когда я установил его на 2300M.

Ответ 15

еще одна точка для 32-битной JVM для горячих точек: - урожайность кучи = 4 Gig - Java Heap - PermGen;

Это может оказаться особенно сложным для 32-битной JVM, поскольку Java-куча и родная куча находятся в гонке. чем больше ваша куча Java, тем меньше местная куча. Попытка настроить большую кучу для 32-разрядной виртуальной машины например, 2,5 ГБ + увеличивает риск создания собственного OutOfMemoryError в зависимости от вашего приложения (ов) количество потоков и т.д.

Ответ 16

Теоретический 4gb, но на практике (для IBM JVM):

Win 2k8 64, IBM Websphere Application Server 8.5.5 32bit

C:\IBM\WebSphere\AppServer\bin>managesdk.bat -listAvailable -verbose CWSDK1003I: Доступные SDK: CWSDK1005I: Имя SDK: 1.6_32 - com.ibm.websphere.sdk.version.1.6_32=1.6 - com.ibm.websphere.sdk.bits.1.6_32=32 - com.ibm.websphere.sdk.location.1.6_32=${WAS_INSTALL_ROOT}/java - com.ibm.websphere.sdk.platform.1.6_32=windows - com.ibm.websphere.sdk.architecture.1.6_32=x86_32 - com.ibm.websphere.sdk.nativeLibPath.1.6_32=${WAS_INSTALL_ROOT}/lib/native/win /x86_32/ CWSDK1001I: Задача managesdk выполнена успешно. C:\IBM\WebSphere\AppServer\java\bin>java -Xmx2036 MaxMemory JVMJ9GC017E -Xmx слишком мала, должна быть не меньше 1 M байт JVMJ9VM015W Ошибка инициализации для библиотеки j9gc26(2): Не удалось инициализи ровать Could not create the Java virtual machine. C:\IBM\WebSphere\AppServer\java\bin>java -Xmx2047M MaxMemory Total Memory: 4194304 (4.0 MiB) Max Memory: 2146435072 (2047.0 MiB) Free Memory: 3064536 (2.9225692749023438 MiB) C:\IBM\WebSphere\AppServer\java\bin>java -Xmx2048M MaxMemory JVMJ9VM015W Ошибка инициализации для библиотеки j9gc26(2): Не удалось создать эк земпляр кучи; запрошено 2G Could not create the Java virtual machine.

RHEL 6.4 64, IBM Websphere Application Server 8.5.5 32bit

[bin]./java -Xmx3791M MaxMemory Total Memory: 4194304 (4.0 MiB) Max Memory: 3975151616 (3791.0 MiB) Free Memory: 3232992 (3.083221435546875 MiB) [[email protected] bin]# ./java -Xmx3793M MaxMemory Total Memory: 4194304 (4.0 MiB) Max Memory: 3977248768 (3793.0 MiB) Free Memory: 3232992 (3.083221435546875 MiB) [bin]# /opt/IBM/WebSphere/AppServer/bin/managesdk.sh -listAvailable -verbose CWSDK1003I: Available SDKs : CWSDK1005I: SDK name: 1.6_32 - com.ibm.websphere.sdk.version.1.6_32=1.6 - com.ibm.websphere.sdk.bits.1.6_32=32 - com.ibm.websphere.sdk.location.1.6_32=${WAS_INSTALL_ROOT}/java - com.ibm.websphere.sdk.platform.1.6_32=linux - com.ibm.websphere.sdk.architecture.1.6_32=x86_32 -com.ibm.websphere.sdk.nativeLibPath.1.6_32=${WAS_INSTALL_ROOT}/lib/native/linux/x86_32/ CWSDK1001I: Successfully performed the requested managesdk task.