Maksimal mængde hukommelse pr. Java-proces på Windows?

Indlæg af Hanne Mølgaard Plasc

Problem



Hvad er den maksimale bunke størrelse, du kan allokere på 32-bit Windows til en Java-proces ved hjælp af -Xmx?


Jeg spørger, fordi jeg vil bruge ETOPO1-data i OpenMap, og den rå binære float-fil er omkring 910   MB. [9]

Bedste reference


Der er ikke noget bedre end et empirisk eksperiment til at besvare dit spørgsmål.
Jeg har skrevet et Java-program og kører det, mens du angiver XMX-flag (også brugt XMS=XMX for at tvinge JVM tildelingen af ​​hele hukommelsen).
For yderligere at beskytte mod JVM optimeringer, har jeg aktivt tildelt X antal 10MB objekter.
Jeg kører en række tests på en række JVM'er, der øger XMX-værdien sammen med stigende antal MB tildelt på et andet 32bit operativsystem, der bruger både Sun og IBM JVM'er, her er et resumé af resultaterne:


OS: Windows XP SP2, JVM: Sun 1.6.0\_02, Max bunke størrelse: 1470 MB

OS: Windows XP SP2, JVM: IBM 1.5, Max bunke størrelse: 1810 MB

OS: Windows Server 2003 SE, JVM: IBM 1.5, Max bunke størrelse: 1850 MB

OS: Linux 2.6, JVM: IBM 1.5, Max heap størrelse: 2750 MB


Her er de detaljerede forsøg på forsøg sammen med tildelingsklassen hjælper kildekoden:


WinXP SP2, SUN JVM:
C:>java -version
java version "1.6.0\_02"
Java(TM) SE Runtime Environment (build 1.6.0\_02-b06)
Java HotSpot(TM) Client VM (build 1.6.0\_02-b06, mixed mode)

java -Xms1470m -Xmx1470m Class1 142 ... about to create object 141 object 141 created

C:>java -Xms1480m -Xmx1480m Class1 145 Error occurred during initialization of VM Could not reserve enough space for object heap Could not create the Java virtual machine.


WinXP SP2, IBM JVM
 
C:>c:ibmjdkinjava.exe -version
java version "1.5.0"
Java(TM) 2 Runtime Environment, Standard Edition (build pwi32devifx-20070323 (if
ix 117674: SR4 + 116644 + 114941 + 116110 + 114881))
IBM J9 VM (build 2.3, J2RE 1.5.0 IBM J9 2.3 Windows XP x86-32 j9vmwi3223ifx-2007
0323 (JIT enabled)
J9VM - 20070322\_12058\_lHdSMR
JIT  - 20070109\_1805ifx3\_r8
GC   - WASIFIX\_2007)
JCL  - 20070131

c:ibmjdkinjava.exe -Xms1810m -Xmx1810m Class1 178 ... about to create object 177 object 177 created

C:>c:ibmjdkinjava.exe -Xms1820m -Xmx1820m Class1 179 JVMJ9VM015W Initialization error for library j9gc23(2): Failed to instantiate he ap. 1820M requested Could not create the Java virtual machine.

Win2003 SE, IBM JVM
C:>"C:IBMjava" -Xms1850m -Xmx1850m Class1
sleeping for 5 seconds.
Done.

C:>"C:IBMjava" -Xms1880m -Xmx1880m Class1 JVMJ9VM015W Initialization error for library j9gc23(2): Failed to instantiate he ap. 1880M requested Could not create the Java virtual machine.


Linux 2.6, IBM JVM
[root@myMachine ~]# /opt/ibm/java2-i386-50/bin/java -version
java version "1.5.0"
Java(TM) 2 Runtime Environment, Standard Edition (build pxi32dev-20060511 (SR2))
IBM J9 VM (build 2.3, J2RE 1.5.0 IBM J9 2.3 Linux x86-32 j9vmxi3223-20060504 (JIT enabled)
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 Initialization error for library j9gc23(2): Failed to instantiate heap. 2800M requested Could not create the Java virtual machine.




Her er koden:



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.");
    }

}

Andre referencer 1


For en stor fil foreslår jeg, at du bruger en hukommelseskartet fil. Dette bruger ikke bunkeplads (eller meget lille), så maksimal bunke størrelse bør ikke være et problem i dette tilfælde.

Andre referencer 2


Vi har for nylig portet fra Windows til Linux (på grund af VM-størrelsesproblemer).


Jeg har hørt om mange numre smidt rundt i fortiden til Windows VM-størrelse (1200, 1400, 1600, 1800). På vores Windows-servere (2003), i vores miljø, med vores applikationer , ... Jeg har aldrig brugt mere end 1280 MB. Derudover startede vores ansøgning udstillinger af GC og OOM.


Hver gang jeg fik en ny VM-version, forsøgte jeg at ændre nummeret, og det varierede aldrig.


Du har en 900MB fil nu, hvad nu hvis filen øges til 1300MB? Hvad vil du gøre?


Du har en række muligheder



  1. Port til Linux/Solaris. Dette har kun brug for hardware/software og det er ofte en simpel porting øvelse.

  2. Brug 64bit Windows. Dette er muligvis ikke fri for GC-problemer, men jeg har hørt om forskellige fortællinger med 64bit vms.

  3. Rediger appen til at behandle filen forskelligt. Kan du opdele filen logisk på en eller anden måde, kan du læse filen i klumper og behandle den anderledes osv.?



Andre personer, der bruger OpenMap, skal have fundet dette problem. Kan du få fat i deres viden og ikke opfinde noget hjul?

Andre referencer 3


Som bemærket i det spørgsmål, der er nævnt i kommentaren, er der en praktisk grænse, ca. 1200   MB.


Men den situation du beskriver beskriver mere dybde end den rene memory størrelse.


Når du læser en 910   MB binære data og opbygger en netværksobjekt ud af den (i modsætning til blot at opretholde dataene som en række byte), vil du ende med at indtage meget mere hukommelse end 910   MB. Et rimeligt skøn ville være, at repræsentationen i hukommelsen vil forbruge dobbelt så meget hukommelse - det skyldes (1) hver objekt indeholder en yderligere peger (til objektets klasse), og (2) der er mange bogføringsdata . Hvis du f.eks. Bruger en HashMap til at styre dine objekter, uddeler du i tillæg til hvert objekt også en Map.Entry-objekt, som let kan forbruge 16 eller 20 byte (implementeringsafhængig).


På den anden side er der stadig håb: behøver du virkelig at opretholde alle 910   MB i hukommelsen? Kan du ikke bare bygge noget, der læser dataene på en doven måde? Kombineret med WeakReferences Jeg tror, ​​du kan trække dette ud.

Andre referencer 4


På 32-bit Windows, kan hver applikation som standard bruge op til 2   GB virtuelt adresserum. Jeg tror det gør -Xmx2048M. Men hvis du har mere RAM installeret, kan du øge det virtuelle adresserum op til 3   GB ved at bruge starttidsparametre.


I boot.ini kan du oprette en ny opstartsindstillinger som denne:


[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>


Her kan du indstille din maskine ved at justere parameteren/USERVA=2800. Men vær opmærksom på, at nogle konfigurationer ikke kan lide høje værdier i denne parameter - forventer nedbrud.