Memoria massima Java su Windows XP


103

Sono sempre stato in grado di allocare 1400 megabyte per Java SE in esecuzione su Windows XP a 32 bit (Java 1.4, 1.5 e 1.6).

java -Xmx1400m ...

Oggi ho provato la stessa opzione su una nuova macchina Windows XP utilizzando Java 1.5_16 e 1.6.0_07 e ho ricevuto l'errore:

Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.

Attraverso prove ed errori sembra che 1200 megabyte siano il massimo che posso allocare su questa macchina.

Qualche idea sul perché una macchina consentirebbe 1400 e un'altra solo 1200?

Modifica: la macchina ha 4 GB di RAM con circa 3,5 GB che Windows può riconoscere.


Noteresti una differenza nel massimo tra l'esecuzione dell'app in una shell a 32 bit o in una shell a 64 bit, almeno nella mia esperienza, sebbene i sistemi Windows XP a 64 bit siano rari.
Djangofan

Risposte:


124

Tieni presente che Windows ha la gestione della memoria virtuale e la JVM necessita solo di memoria contigua nel suo spazio degli indirizzi . Quindi, altri programmi in esecuzione sul sistema non dovrebbero necessariamente influire sulla dimensione dell'heap. Quello che ti ostacolerà sono le DLL che vengono caricate nel tuo spazio degli indirizzi. Sfortunatamente le ottimizzazioni in Windows che riducono al minimo il riposizionamento delle DLL durante il collegamento rendono più probabile che avrai uno spazio degli indirizzi frammentato. Le cose che potrebbero interferire con lo spazio degli indirizzi oltre alle solite cose includono software di sicurezza, software CBT, spyware e altre forme di malware. Le cause probabili delle variazioni sono diverse patch di sicurezza, versioni di runtime C, ecc. I driver di dispositivo e altri bit del kernel hanno il proprio spazio di indirizzi (gli altri 2 GB dei 4 GB di spazio a 32 bit).

Si potrebbe provare a passare attraverso le associazioni DLL nel processo JVM e guardare cercando di rebase la DLL di per uno spazio di indirizzamento più compatto. Non è divertente, ma se sei disperato ...

In alternativa, puoi semplicemente passare a Windows a 64 bit e una JVM a 64 bit. Nonostante ciò che altri hanno suggerito, mentre masticherà più RAM, avrai molto più spazio di indirizzi virtuali contigui e allocare 2 GB in modo contiguo sarebbe banale.


5
Utilizzare Process Explorer per vedere dove vengono caricati i dll in memoria. Spesso alcuni driver aggiornati si bloccano nel mezzo dello spazio degli indirizzi. Usando il comando REBASE puoi facilmente spingerli via. Tieni presente, tuttavia, che la dll è soggetta a essere aggiornata di nuovo e rompere le cose.
brianegge

2
Non l'ho mai accettato come risposta e tuttavia stackoverflow l'ha contrassegnato come risposta.
Steve Kuo,

@Christopher, è possibile utilizzare una JVM a 64 bit su un Windows XP a 32 bit?
Pacerier

@Pacerier Scusa, ho perso la tua domanda. AFAIK, non è possibile. OS X aveva alcuni trucchi per lo spazio utente a 64 bit con kernel a 32 bit, ma non ho sentito nulla di simile per Windows.
Christopher Smith

@ChristopherSmith, Btw, hai menzionato " altri programmi in esecuzione sul sistema non dovrebbero necessariamente influire sulla dimensione dell'heap ". In tal caso, come spieghiamo questo risultato: stackoverflow.com/questions/9303889/… ?
Pacerier

50

Questo ha a che fare con la memoria contigua.

Ecco alcune informazioni che ho trovato online per qualcuno che me l'aveva chiesto prima, presumibilmente da un "dio VM":

Il motivo per cui abbiamo bisogno di una regione di memoria contigua per l'heap è che abbiamo un mucchio di strutture di dati laterali che sono indicizzate da offset (scalati) dall'inizio dell'heap. Ad esempio, teniamo traccia degli aggiornamenti dei riferimenti agli oggetti con un "array di contrassegni di schede" che ha un byte per ogni 512 byte di heap. Quando memorizziamo un riferimento nell'heap, dobbiamo contrassegnare il byte corrispondente nell'array dei contrassegni della scheda. Spostiamo a destra l'indirizzo di destinazione del negozio e lo usiamo per indicizzare l'array dei contrassegni della carta. Giochi aritmetici divertenti che non puoi fare in Java che puoi (devi :-) giocare in C ++.

Di solito non abbiamo problemi a ottenere modeste regioni contigue (fino a circa 1,5 GB su Windohs, fino a circa 3,8 GB su Solaris. YMMV.). Su Windohs, il problema è principalmente che ci sono alcune librerie che vengono caricate prima dell'avvio della JVM che interrompono lo spazio degli indirizzi. L'utilizzo dell'opzione / 3GB non ridisegnerà quelle librerie, quindi sono ancora un problema per noi.

Sappiamo come creare cumuli in pezzi, ma ci sarebbe un po 'di sovraccarico per usarli. Abbiamo più richieste per una gestione dell'archiviazione più rapida rispetto a quelle per heap più grandi nella JVM a 32 bit. Se vuoi davvero grandi heap, passa alla JVM a 64 bit. Abbiamo ancora bisogno di memoria contigua, ma è molto più facile entrare in uno spazio di indirizzi a 64 bit.


È molto interessante. Mi sono sempre chiesto perché 1500 MB, ora ho capito, grazie!
Tim Büthe

3
Scusa per aver seguito una vecchia domanda, ma questa è la migliore risposta che ho visto finora. Ma perché la JVM non riesce all'avvio se non riesce a ottenere la dimensione massima dell'heap? Non dovrebbe tranquillamente accontentarsi della dimensione migliore sopra il minimo ?
Stroboskop

19

I limiti delle dimensioni dell'heap Java per Windows sono:

  • dimensione heap massima possibile su Java a 32 bit: 1,8 GB
  • limite di dimensione heap consigliato su Java a 32 bit: 1,5 GB (o 1,8 GB con l'opzione / 3 GB)

Questo non ti aiuta a ottenere un mucchio Java più grande, ma ora sai che non puoi andare oltre questi valori.


10

Oracle JRockit , che può gestire un heap non contiguo, può avere una dimensione di heap Java di 2,85 GB su Windows 2003 / XP con l'opzione / 3GB. Sembra che la frammentazione possa avere un impatto notevole su quanto può essere grande un heap Java.


6

La JVM necessita di memoria contigua e, a seconda di cosa è in esecuzione, cosa era in esecuzione prima e come Windows ha gestito la memoria, potresti essere in grado di ottenere fino a 1,4 GB di memoria contigua. Penso che Windows a 64 bit consentirà cumuli più grandi.


2
Penso che il sistema operativo moderno emuli la memoria continua per. Dall'80486 l'architettura x86 supporta il paging per semplificare la riorganizzazione della memoria fisica.
Mnementh

3
Mnemeth: in primo luogo, c'è un'API specifica (AllocateUserPhysicalPages) in WINAPI per strumenti avanzati come database e VM che sono meglio gestire la propria memoria con Windows fuori mano. In secondo luogo, il paging è una funzione della modalità protetta 80386, non 80486.
Tamas Czinege

6

La JVM di Sun necessita di memoria contigua. Quindi la quantità massima di memoria disponibile è dettata dalla frammentazione della memoria. Soprattutto le DLL del driver tendono a frammentare la memoria, quando vengono caricate in un indirizzo di base predefinito. Quindi il tuo hardware ei suoi driver determinano la quantità di memoria che puoi ottenere.

Due fonti per questo con dichiarazioni degli ingegneri Sun: blog del forum

Forse un'altra JVM? Hai provato Harmony ? Penso che prevedessero di consentire la memoria non continua.


Ma sono stato in grado di allocare 1300 MB su una macchina con solo 1 GB di RAM (più memoria virtuale). La mia macchina da 2 GB di RAM (anche con memoria virtuale) può allocare solo 1200 MB.
Steve Kuo

L'armonia è morta, non è vero?
Pacerier

Sì: "Apache Harmony è in pensione presso Apache Software Foundation dal 16 novembre 2011."
bobbel

3

Penso che abbia più a che fare con il modo in cui Windows è configurato come suggerito da questa risposta: Java -Xmx Option

Altri test: sono stato in grado di allocare 1300 MB su una vecchia macchina Windows XP con solo 768 MB di RAM fisica (più memoria virtuale). Sulla mia macchina da 2 GB di RAM posso ottenere solo 1220 MB. Su varie altre macchine aziendali (con Windows XP precedente) sono stato in grado di ottenere 1400 MB. La macchina con un limite di 1220 MB è piuttosto nuova (appena acquistata da Dell), quindi forse ha Windows e DLL più recenti (e più gonfie) (esegue Windows XP Pro versione 2002 SP2).


Potrebbe anche essere influenzato dalle impostazioni della memoria virtuale.
skaffman

Tutte le macchine con cui provo hanno una memoria virtuale almeno doppia rispetto alla RAM fisica.
Steve Kuo

nota che non vuoi davvero usare davvero la memoria virtuale con java, perché le prestazioni del GC peggioreranno La quantità di memoria dipende da quali DLL sono già state caricate e hanno frammentato la memoria.
kohlerm

2

Ho ricevuto questo messaggio di errore durante l'esecuzione di un programma java da un virtuozzo VPS (memoria limitata). Non avevo specificato alcun argomento di memoria e ho scoperto che dovevo impostare esplicitamente una piccola quantità poiché il valore predefinito doveva essere troppo alto. Ad esempio -Xmx32m (ovviamente deve essere regolato a seconda del programma che si esegue).

Mettendolo qui nel caso in cui qualcun altro riceva il messaggio di errore sopra senza specificare una grande quantità di memoria come ha fatto l'interrogante.


1

JDK / JRE di sun necessita di una quantità di memoria contigua se si alloca un blocco enorme.

Il sistema operativo e le app iniziali tendono ad allocare bit e pezzi durante il caricamento che frammentano la RAM disponibile. Se un blocco contiguo NON è disponibile, il SUN JDK non può utilizzarlo. JRockit di Bea (acquisito da Oracle) può allocare memoria da pezzi.


1

Tutti sembrano rispondere sulla memoria contigua, ma hanno trascurato di riconoscere un problema più urgente.

Anche con un'allocazione di memoria contigua al 100%, non è possibile avere una dimensione heap di 2 GiB su un sistema operativo Windows a 32 bit (* per impostazione predefinita). Questo perché i processi Windows a 32 bit non possono indirizzare più di 2 GiB di spazio.

Il processo Java conterrà perm gen (pre Java 8), dimensione dello stack per thread, JVM / overhead della libreria (che praticamente aumenta con ogni build), il tutto oltre all'heap .

Inoltre, i flag JVM ei loro valori predefiniti cambiano tra le versioni. Esegui quanto segue e avrai un'idea:

 java -XX:+PrintFlagsFinal

Molte delle opzioni influenzano la divisione della memoria dentro e fuori dall'heap. Lasciandoti con più o meno di quei 2 GiB con cui giocare ...

Per riutilizzare parti di questa mia risposta (su Tomcat, ma si applica a qualsiasi processo Java):

Il sistema operativo Windows limita l'allocazione di memoria di un processo a 32 bit a 2 GiB in totale (per impostazione predefinita).

[Sarai solo in grado] di allocare circa 1,5 GiB di spazio heap perché c'è anche altra memoria allocata al processo (l'overhead JVM / libreria, spazio di perm gen ecc.).

Perché Windows a 32 bit impone un limite di spazio di indirizzi di processo di 2 GB, ma Windows a 64 bit impone un limite di 4 GB?

Altri sistemi operativi moderni [cough Linux] consentono ai processi a 32 bit di utilizzare tutto (o la maggior parte) dello spazio indirizzabile di 4 GiB.

Detto questo, i sistemi operativi Windows a 64 bit possono essere configurati per aumentare il limite dei processi a 32 bit a 4 GiB (3 GiB su 32 bit):

http://msdn.microsoft.com/en-us/library/windows/desktop/aa366778(v=vs.85).aspx


1
Questa risposta riguarda solo il motivo per cui potrebbe essere in grado di allocare solo 2 GB, non perché può allocare 1,4 GB su un computer e solo 1,2 GB su un altro. Non raggiunge i limiti di 1,5 GB, 2 GB o 4 GB indicati qui.
vapcguy

1
Il paragrafo sui flag JVM spiega in qualche modo perché la memoria potrebbe variare tra le versioni. Inoltre, nota il mio punto sul modo in cui l'impostazione dell'heap è sempre una (grande) frazione della dimensione totale del processo, quindi un'impostazione inferiore che può ancora raggiungere il limite di processo di 2 GiB - un'altra potrebbe essere vincolata dall'allocazione di memoria contigua.
Michael

O forse il limite di 1,5 GB, su quella allocazione di 1,4 GB che sta facendo. Ha più senso ora - grazie per questo chiarimento.
vapcguy

0

Ecco come aumentare la dimensione del paging

  1. fare clic con il tasto destro su mio computer ---> proprietà ---> Avanzate
  2. nella sezione prestazioni fare clic su impostazioni
  3. fare clic sulla scheda Avanzate
  4. nella sezione Memoria virtuale, fare clic su modifica. Mostrerà le dimensioni correnti del tuo paging.
  5. Seleziona Unità in cui è disponibile lo spazio su disco rigido.
  6. Fornisci dimensione iniziale e dimensione massima ... ad esempio dimensione iniziale 0 MB e dimensione massima 4000 MB. (Quanto ti servirà)

0

** Esistono numerosi modi per modificare la dimensione dell'heap come,

  1. file-> impostazione-> build, exceution, deployment-> compilatore qui troverai la dimensione dell'heap
  2. file-> impostazione-> build, exceution, deployment-> compilatore-> andriod qui troverai anche la dimensione dell'heap. Puoi fare riferimento a questo per il progetto andriod se stai affrontando lo stesso problema.

Quello che ha funzionato per me è stato

  1. Imposta il percorso JAVA_HOME appropriato in caso di aggiornamento di Java.

  2. crea nuova variabile di sistema computer-> proprietà-> impostazioni avanzate- > crea nuova variabile di sistema

nome: _JAVA_OPTION valore: -Xmx750m

FYI: puoi trovare VMoption predefinita nella guida di Intellij- > modifica l'opzione VM personalizzata , in questo file vedi la dimensione minima e massima dell'heap. **


-1

Innanzitutto, utilizzare un file di paging quando si hanno 4 GB di RAM è inutile. Windows non può accedere a più di 4 GB (in realtà, meno a causa di buchi di memoria), quindi il file di paging non viene utilizzato.

Secondo, lo spazio degli indirizzi è diviso in 2, metà per il kernel e metà per la modalità utente. Se hai bisogno di più RAM per le tue applicazioni, usa l'opzione / 3GB in boot.ini (assicurati che java.exe sia contrassegnato come "large address aware" (google per maggiori informazioni).

Terzo, penso che non sia possibile allocare tutti i 2 GB di spazio degli indirizzi perché java spreca un po 'di memoria internamente (per thread, compilatore JIT, inizializzazione VM, ecc.). Utilizzare l'opzione / 3 GB per ulteriori informazioni.


1
L'idea che un file di paging sia inutile con 4 GB o RAM è sbagliata. Senza un file di paging, il sistema operativo non può eliminare i dati di processo inutilizzati (spazio dello stack per i servizi inutilizzati, ecc.) Dalla RAM fisica, riducendo così la quantità di RAM disponibile per il lavoro reale. Avere un file di paging libera la RAM.
nessuno
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.