Perché la dimensione heap è fissa su JVM?

20

Qualcuno può spiegarmi perché le JVM (non ne ho controllate troppe, ma non ne ho mai viste una che non l'abbiano fatto in quel modo) devono essere eseguite su una dimensione di heap fissa? So che è più semplice da implementare su un semplice heap contiguo, ma Sun JVM ha ormai più di dieci anni, quindi mi sarei aspettato che avessero avuto il tempo di migliorarlo.

La necessità di definire la dimensione massima della memoria del programma al momento dell'avvio sembra una cosa del 1960 da fare, e poi ci sono le cattive interazioni con la gestione della memoria virtuale dell'OS (GC che recupera i dati scambiati, incapacità di determinare la quantità di memoria Il processo Java è veramente che utilizza dal lato del sistema operativo, enormi quantità di spazio su VM sprecato (lo so, non ti importa delle tue fantasiose macchine a 48 bit ...)). Immagino anche che i vari tristi tentativi di costruire piccoli sistemi operativi all'interno della JVM (server applicativi EE, OSGi) siano almeno in parte responsabili di questa circostanza, perché l'esecuzione di più processi Java su un sistema porta inevitabilmente a risorse sprecate perché devi dai a ciascuno di loro la memoria che potrebbe dover usare al massimo.

Sorprendentemente, Google non ha suscitato le tempeste di indignazione per questo che mi sarei aspettato, ma potrebbero essere stati seppelliti sotto milioni di persone che hanno scoperto la dimensione dell'heap e l'hanno semplicemente accettata per un fatto.

    
posta themel 06.12.2012 - 13:30
fonte

4 risposte

23

Ti sbagli. La dimensione heap di JVM non è fissa, solo limitata:

  • -Xmx imposta la dimensione massima della memoria heap
  • -Xms imposta la dimensione minima della memoria heap

L'impostazione di un limite superiore è necessaria per diversi motivi. In primo luogo, dice al netturbino quando entrare in azione. Secondo, impedisce alla JVM di intasare l'intera macchina consumando troppa memoria. La dimensione minima dell'heap è probabilmente utile per riservare l'ammontare di memoria di cui il programma ha bisogno, per evitare che esaurisca la memoria (perché altri processi consumano troppo).

    
risposta data 06.12.2012 - 13:39
fonte
5

Immagino che la risposta abbia qualcosa a che fare con l'eredità di Java. Originariamente era stato progettato come linguaggio da utilizzare per i sistemi embedded, dove ovviamente le risorse sono limitate e non si desidera che i processi semplicemente divorino tutto ciò che è disponibile. Aiuta anche con l'amministrazione del sistema, poiché semplifica il provisioning delle risorse su un server se è possibile impostare limiti di risorse. Vedo che le ultime JVM sembrano utilizzare più heap non continui, anche se ovviamente tutto appare come un singolo heap per il tuo codice.

(FWIW, dovevi specificare i requisiti di memoria di un programma nelle versioni MacOS pre-Darwin di Apple [fino a System 7 in ogni caso, che era l'ultimo che usavo], che andava bene negli anni '80.)

    
risposta data 06.12.2012 - 15:11
fonte
2

Devi dare il meccanismo alcuni di GC per dirgli quando eseguire, o il tuo programma riempirà l'intero spazio di memoria virtuale. Esistono molti modi alternativi per attivare GC: tempo trascorso, numero di allocazioni, numero di assegnazioni, probabilmente altre che non riesco a pensare in questo momento. IMO nessuno di questi è buono come semplicemente impostare un limite di memoria ed eseguire GC quando lo spazio allocato raggiunge quel limite.

La chiave è impostare i limiti corretti . Considero -ms come "questa è la quantità di memoria di cui la mia app ha bisogno" e -mx come "non dovrebbe mai superare questo importo". In una distribuzione di produzione, i due dovrebbero essere vicini se non uguali e dovrebbero essere basati su requisiti effettivi e misurati.

Le tue preoccupazioni sulla memoria virtuale "sprecata" sono malriposte: è virtuale, è (quasi) gratuita. Sì, assegnare un lotto troppo grande significa che non è possibile avviare il maggior numero di thread o caricare tanti file mappati in memoria. Ma questo fa parte del design dell'applicazione: hai risorse scarse, devi partizionarle in un modo che permetta alla tua applicazione di funzionare. In un heap in stile "C", che si espanderà fino a raggiungere la cima della memoria, il problema di base è lo stesso, non devi pensarci finché non sei nei guai.

L'unica cosa che un grande heap potrebbe "sprecare" è lo spazio di swap, perché tutti i segmenti scrivibili richiedono un impegno da swap. Ma questo fa parte della progettazione del sistema: se vuoi avere un sacco di JVM in esecuzione sulla stessa scatola, aumenta il tuo swap o diminuisci la loro allocazione di heap. Se iniziano a battere, allora stai cercando di fare troppo con il sistema; acquista più memoria (e se stai ancora utilizzando un processore a 32 bit, acquista una nuova scatola).

    
risposta data 08.12.2012 - 13:40
fonte
-2

Come dice utente281377, si specifica solo un limite superiore della quantità di memoria che il processo può consumare. Ovviamente, l'applicazione stessa prenderà solo lo spazio di cui ha bisogno.

Se ci dovrebbe essere un limite superiore predefinito o no è un'altra domanda, sia con pro che contro.

    
risposta data 06.12.2012 - 14:00
fonte

Leggi altre domande sui tag