Максимальный объем памяти на процесс Java в Windows?

Каков максимальный размер кучи, который вы можете выделить в 32-битной Windows для процесса Java, используя -Xmx?

Я спрашиваю, потому что я хочу использовать данные ETOPO1 в OpenMap, а необработанный двоичный файл с плавающей запятой составляет около 910 МБ.

5 ответов

Решение

Нет ничего лучше, чем эмпирический эксперимент, чтобы ответить на ваш вопрос. Я написал программу на Java и запустил ее, указав флаг XMX (также использовал XMS=XMX для принудительного выделения JVM всей памяти). Для дальнейшей защиты от оптимизации JVM я активно выделяю число X для объектов размером 10 МБ. Я провел ряд тестов на нескольких JVM, увеличивая значение XMX вместе с увеличением количества выделенных МБ, в разных 32-битных операционных системах, использующих как Sun, так и IBM JVM, вот краткое изложение результатов:

ОС:Windows XP SP2, JVM: Sun 1.6.0_02, максимальный размер кучи: 1470 МБ
ОС: Windows XP SP2, JVM: IBM 1.5, максимальный размер кучи: 1810 МБ
ОС: Windows Server 2003 SE, JVM: IBM 1.5, максимальный размер кучи: 1850 МБ
ОС: Linux 2.6, JVM: IBM 1.5, максимальный размер кучи: 2750 МБ

Вот подробные попытки выполнения вместе с исходным кодом помощника класса выделения:

WinXP SP2, SUN JVM:

C:> Java-версия
Java-версия "1.6.0_02"
Java(TM) SE Runtime Environment (сборка 1.6.0_02-b06)
Клиентская виртуальная машина Java HotSpot(TM) (сборка 1.6.0_02-b06, смешанный режим)

java -Xms1470m -Xmx1470m Class1 142... о создании объекта 141 объект 141 создан

C:> Java -Xms1480m -Xmx1480m Class1 145 Произошла ошибка при инициализации ВМ Не удалось зарезервировать достаточно места для кучи объектов Не удалось создать виртуальную машину Java.

WinXP SP2, IBM JVM
 
C:> c: \ ibm \ jdk \ bin \ java.exe -version
Java-версия "1.5.0"
Среда выполнения Java(TM) 2, стандартная версия (сборка pwi32devifx-20070323 (если
IX 117674: SR4 + 116644 + 114941 + 116110 + 114881))
IBM J9 VM (сборка 2.3, J2RE 1.5.0 IBM J9 2.3, Windows XP x86-32 j9vmwi3223ifx-2007
0323 (JIT включен)
J9VM - 20070322_12058_lHdSMR
JIT - 20070109_1805ifx3_r8
GC - WASIFIX_2007)
JCL - 20070131

c: \ ibm \ jdk \ bin \ java.exe -Xms1810m -Xmx1810m Class1 178... о создании объекта 177 объект 177 создан

C:>c:\ibm\jdk\bin\java.exe -Xms1820m -Xmx1820m Class1 179 JVMJ9VM015W Ошибка инициализации для библиотеки j9gc23(2): не удалось создать экземпляр ап. 1820M запрошено Не удалось создать виртуальную машину Java.

Win2003 SE, IBM JVM
C:> "C: \ IBM \ java" -Xms1850m -Xmx1850m Class1
спать в течение 5 секунд.
Готово.

C:> "C: \ IBM \ java" -Xms1880m -Xmx1880m Class1 JVMJ9VM015W Ошибка инициализации для библиотеки j9gc23(2): не удалось создать экземпляр ап. 1880M запрошено Не удалось создать виртуальную машину Java.

Linux 2.6, IBM JVM
[root @ myMachine ~] # / opt / ibm / java2-i386-50 / bin / java -version
Java-версия "1.5.0"
Среда выполнения Java(TM) 2, стандартная версия (сборка pxi32dev-20060511 (SR2))
IBM J9 VM (сборка 2.3, J2RE 1.5.0 IBM J9 2.3 Linux x86-32 j9vmxi3223-20060504 (JIT включен)
J9VM - 20060501_06428_lHdSMR
JIT - 20060428_1800_r8
GC - 20060501_AA)
JCL - 20060511a

/ opt / ibm / java2-i386-50 / bin / java -Xms2750m -Xmx2750m Class1 270

[root @ myMachine ~] # / opt / ibm / java2-i386-50 / bin / java -Xms2800m -Xmx2800m Class1 270 JVMJ9VM015W Ошибка инициализации для библиотеки j9gc23(2): не удалось создать экземпляр кучи. 2800M запрошено Не удалось создать виртуальную машину Java.

Вот код:


import java.util.StringTokenizer;


public class Class1 {

        public Class1() {}

        private class BigObject {
                byte _myArr[];
                public BigObject() {
                        _myArr = new byte[10000000];
                }
        }
    public static void main(String[] args) {
                (new Class1()).perform(Integer.parseInt(args[0]));
        }
        public void perform(int numOfObjects) {
                System.out.println("creating 10 MB arrays.");
                BigObject arr[]  = new BigObject[numOfObjects];
                for (int i=0;i <numOfObjects; i++) {
                        System.out.println("about to create object "+i);
                        arr[i] = new BigObject();
                        System.out.println("object "+i+" created");
                }
                System.out.println("sleeping for 5 seconds.");
                try {
                Thread.sleep(5000);
                }catch (Exception e) {e.printStackTrace();}
                System.out.println("Done.");
    }

}

Для большого файла я предлагаю вам использовать отображенный файл памяти. Это не использует пространство кучи (или очень мало), поэтому максимальный размер кучи не должен быть проблемой в этом случае.

Мы недавно портировали с Windows на Linux (из-за проблем с размером виртуальной машины).

Я слышал о множестве чисел, разбросанных в прошлом по размеру виртуальной машины Windows (1200, 1400, 1600, 1800). На наших Windows-серверах (2003), в нашей среде, с нашими приложениями... Я никогда не использовал успешно более 1280 МБ. Кроме того, наше приложение начало выставлять проблемы GC и OOM.

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

Теперь у вас есть файл размером 900 МБ, что если размер файла увеличится до 1300 МБ? Что вы будете делать?

У вас есть несколько вариантов

  1. Портировать на Linux/Solaris. Для этого просто нужно аппаратное / программное обеспечение и то, что часто является простым упражнением по переносу.
  2. Используйте 64-битную Windows. Это не может быть свободным от проблем GC, хотя - я слышал о разных рассказах с 64-битным VMS.
  3. Перепроектируйте приложение, чтобы обрабатывать файл по-разному. Можете ли вы каким-то образом разделить файл логически, можете ли вы прочитать файл по частям и обработать его по-другому и т. Д.?

Другие люди, использующие OpenMap, должны были столкнуться с этой проблемой. Можете ли вы использовать их знания и не изобретать какие-либо колеса?

Как отмечено в вопросе, упомянутом в комментарии, существует практический лимит, около 1200 МБ.

Однако ситуация, которую вы описываете, имеет большую глубину, чем просто объем памяти.

Когда вы читаете двоичные данные размером 910 МБ и строите из них сетевые объекты (в отличие от простого обслуживания данных в виде массива байтов), вы в конечном итоге занимает гораздо больше памяти, чем 910 МБ. Разумной оценкой будет то, что представление в памяти будет занимать вдвое больше памяти - это потому, что (1) каждый объект содержит дополнительный указатель (на класс объекта); и (2) есть много бухгалтерских данных. Например, если вы используете HashMap для управления вашими объектами, то в дополнение к каждому объекту вы также выделяете объект Map.Entry, который может легко потреблять 16 или 20 байт (зависит от реализации).

С другой стороны, все еще есть надежда: вам действительно нужно поддерживать все 910 МБ в памяти? Разве вы не можете просто создать что-то, что читает данные лениво? В сочетании с WeakReferences я думаю, что вы можете осуществить это.

В 32-битной Windows по умолчанию каждое приложение может использовать до 2 ГБ виртуального адресного пространства. Я думаю, это делает -Xmx2048M, Однако, если у вас установлено больше ОЗУ, вы можете увеличить виртуальное адресное пространство до 3 ГБ, используя параметры времени загрузки.

В boot.ini вы можете создать новые параметры загрузки, например:

[boot loader]<br>
timeout=5<br>
default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS<br>
[operating systems]<br>
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional - magyar" /noexecute=optin /fastdetect /usepmtimer<br>
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional - magyar 3GB" /noexecute=optin /fastdetect /usepmtimer /3GB /USERVA=2800<br>

Здесь, отрегулировав параметр /USERVA=2800, вы можете настроить свою машину. Но имейте в виду, что некоторым конфигурациям не нравятся высокие значения в этом параметре - ожидайте сбои.

Другие вопросы по тегам