2009-02-05 13 views
15

Perché il jvm richiede circa 10 MB di memoria per un semplice mondo Hello, ma il clr no. Qual è il trade-off qui, cioè cosa guadagna il jvm facendo questo?decisione di progettazione di jvm

Lasciatemi chiarire un po 'perché non sto trasmettendo la domanda che è nella mia testa. Esiste chiaramente una differenza architettonica tra i runtime jvm e clr. Il jvm ha un footprint di memoria significativamente più alto rispetto al clr. Suppongo che ci sia qualche vantaggio in questo overhead altrimenti perché esisterebbe. Sto chiedendo quali sono i compromessi in questi due progetti. Quale beneficio guadagna il jvm dal sovraccarico della memoria?

+1

Come sai che è sovraccarico? Hai fatto un programma scheletro in ognuno di essi e li hai eseguiti? Posso solo fare in modo che JVM impieghi circa 7 mb all'avvio (secondo Task Manager), anche con -Xmx256m -Xms256m. –

+0

Puoi darci una lezione di prova che hai usato in entrambi? Questo aiuterà a riprodurre il problema e quindi dare buone risposte. –

+0

Non penso che la mia domanda fosse chiara, quindi l'ho appena modificata. Per una lezione di prova si è una semplice app HelloWorld. – jshen

risposta

6

Credo che una ragione sia che Java deve fare tutto da solo (un altro aspetto dell'indipendenza dalla piattaforma). Ad esempio, Swing disegna i suoi componenti da zero, non si basa sul sistema operativo per disegnarli. Questo è tutto ciò che deve accadere nella memoria. Un sacco di cose che Windows può fare, ma Linux non fa (o fa diversamente) deve essere completamente contenuto in Java in modo che funzioni allo stesso modo su entrambi.

Java inoltre insiste sempre che la sua intera libreria è "Collegata" e disponibile. Dal momento che non usa DLL (non sarebbero disponibili su ogni piattaforma), tutto deve essere caricato e tracciato da java.

Java fa anche un sacco di virgola mobile poiché le FPU spesso danno risultati diversi che sono stati ritenuti inaccettabili.

Quindi, se si pensa a tutto ciò che C# può delegare all'OS è legato a tutte le cose che Java deve fare per il sistema operativo per compensare gli altri, la differenza dovrebbe essere prevista.

Ho eseguito app java su 2 piattaforme incorporate ora. Uno era un analizzatore di spettro in cui effettivamente ha tracciato le tracce, l'altro è costituito da decoder via cavo.

In entrambi i casi, questo minimo ingombro di memoria non è stato un problema: ci sono stati problemi specifici di Java, che non sono stati uno solo. Il numero di oggetti istanziati e la velocità di verniciatura Swing erano problemi più grandi in questi casi.

1

CLR viene conteggiato come parte del sistema operativo, pertanto il task manager non segnala il consumo di memoria durante il processo di applicazione.

+0

Se uso mono su unix, utilizza ancora solo pochi meg rispetto a 30 per jvm – jshen

+2

Il CLR inizia all'interno di ogni processo, quindi dubito che questa risposta sia corretta. – Austin

+1

Austin: esiste un'istanza CLR in ogni processo. Con entrambi CLR e JRE, il codice di sola lettura è condiviso tra i processi. La domanda è: il codice viene conteggiato per ogni processo o per nessun processo. –

2

La JVM conta tutte le sue librerie condivise indipendentemente dal fatto che utilizzino la memoria o meno.

Task Manager è piuttosto inaffidabile quando si tratta di segnalare il consumo di memoria dei programmi. Dovresti prenderlo come guida.

+1

L'altro giorno la mia macchina da 4 GB Vista ha esaurito la memoria nonostante si sia mostra meno di 1 GB utilizzato dalle applicazioni. –

+0

Non utilizzo Windows, quindi non utilizzo il task manager – jshen

5

Sembra che Java stia usando solo più memoria virtuale.

USER  PID %CPU %MEM VSZ RSS TTY  STAT START TIME COMMAND 
amwise 20598 0.0 0.5 22052 5624 pts/3 Sl+ 14:59 0:00 mono Test.exe 
amwise 20601 0.0 0.7 214312 7284 pts/2 Sl+ 15:00 0:00 java Program 

Ho fatto un programma di test in C# e in Java che stampa la stringa "test" e attende per l'ingresso. Credo che il valore della dimensione del set residente (RSS) mostri in modo più accurato l'utilizzo della memoria. L'uso della memoria virtuale (VSZ) è meno significativo.

Come ho capito, le applicazioni possono riservare una tonnellata di memoria virtuale senza effettivamente utilizzare alcuna memoria reale. Ad esempio, è possibile chiedere la funzione VirtualAlloc su Windows per riservare o salvare la memoria virtuale.

EDIT:

Ecco una bella immagine dalla mia scatola di finestre: alt text http://awise.us/images/mem.png

Ogni applicazione è stato un printf semplice seguito da un getchar. Un sacco di utilizzo della memoria virtuale da parte di Java e CLR. La versione C dipende praticamente da niente, quindi l'utilizzo della memoria è relativamente piccolo.

Dubito che sia davvero importante in entrambi i casi. Scegli semplicemente la piattaforma con cui sei più familiare e quindi non scrivere codice terribile, spreco di memoria. Sono sicuro che funzionerà.

EDIT:

Questo VMMap tool da Microsoft potrebbe essere utile in figureing dove la memoria sta andando.

+2

L'RSS di un processo inattivo non è una grande misura. –

+0

Non sto cercando di decidere quale piattaforma è migliore per me da usare. Sono curioso del motivo per cui hanno preso la decisione sul design che hanno fatto sul lato jvm e cosa ne hanno ricavato. – jshen

+0

L'utilizzo di tutta la memoria in uno spazio del processo è virtuale (almeno in Windows). Su un sistema operativo a 32 bit lo spazio degli indirizzi è suddiviso in codice da 2 GB e dati da 2 GB. Totale byte privati ​​si riferisce alla quantità allocata nello spazio degli indirizzi dei dati dell'applicazione. Il SO gestisce come questa allocazione si riferisce alla memoria fisica. –

5

Non so se l'ingombro di memoria iniziale o l'ingombro di un'applicazione Hello World siano importanti. Una differenza potrebbe essere dovuta al numero e alle dimensioni delle librerie caricate da JVM/CLR. Può anche esserci una quantità di memoria che è preallata per i pool di garbage collection.

Ogni applicazione che conosco, utilizza molto di più della funzionalità Hello World. Questo caricherà e libererà memoria migliaia di volte durante l'esecuzione dell'applicazione.Se siete interessati a differenze di memoria utilizzo di JVM vs CLR, qui ci sono un paio di link con buone informazioni

http://benpryor.com/blog/2006/05/04/jvm-vs-clr-memory-allocation/

Memory Management Case study (JVM & CLR)

Case Management Memory studio è in Power Point. Una presentazione molto interessante.

+0

Ovviamente non sto affermando chiaramente la mia domanda. Non sono interessato alle differenze nell'utilizzo della memoria. Sto cercando di scoprire perché jvm richiede una quantità di memoria significativamente maggiore all'avvio rispetto a qualsiasi altro runtime in linguaggio di programmazione che ho usato. Presumo che ci sia una ragione per questo, e sono curioso di cosa si tratta. – jshen

+0

Dubito che fosse troppo intenzionale. La vera potenza di un linguaggio basato su macchine virtuali viene mostrata quando l'applicazione implementa la logica di business e viene eseguita in un periodo di tempo. I parametri di avvio (Initial Memory Utilization e Startup Time) sono generalmente considerati di importanza secondaria. Una cosa che posso pensare è che il numero iniziale di librerie caricate all'avvio è diverso tra JVM e CLR potrebbe essere diverso. JVM potrebbe caricare più onfront rispetto a CLR caricando più su richiesta. Nel tempo più lungo, ciò non fa molta differenza –

2

JVM carica un sacco di classi core non necessarie per ogni esecuzione da rt.jar. Sfortunatamente, le dipendenze inter-cross (java.lang < -> java.io) dei pacchetti java rendono difficile fare un init parziale di runtime. Per non parlare del file rt.jar stesso che ha più di 40 MB, ha bisogno di molto tempo per la ricerca e la decompressione.

Post Java 6u10 sembra caricare le cose in un modo un po 'più intelligente (ha un jqs.exe = java quick starter service per mantenere i dati necessari in memoria e fare un avvio più veloce), ancora Java 7 dice di essere migliore.

Process Explorer in Windows segnala correttamente i Byte privati ​​(i byte privati ​​sono quelle regioni di memoria, che non sono condivise da alcuna dll).

Un disturbo leggermente più grande è che dopo 10 anni, JVM ha ancora un valore predefinito di 64 MB di memoria. È davvero fastidioso usare -Xmx quasi ogni volta e non è possibile eseguire programmi impegnativi in ​​jar con un semplice doppio clic (a meno che non modifichino il comando di assegnazione dell'estensione del file).