2010-06-30 34 views
7

Ho scritto una piccola applicazione java (la mia prima!), Che al momento fa solo alcune cose. Attualmente, esegue la classe Main che lancia una classe gui (una classe che ho scritto che estende JFrame che contiene solo un JTextArea), una classe che carica un file locale attraverso un BufferedInputStream che è di circa 40kb, e una classe che carica una voce da un File di proprietà Java.Utilizzo della memoria dell'applicazione Java

Tutto funziona meravigliosamente, tuttavia, stavo guardando il task manager di Windows e ho notato qualcosa che mi sembrava strano. Quando avvio l'applicazione, l'utilizzo della RAM salta a circa 40 MB mentre carica il file locale e ne estrae alcuni valori da visualizzare in JTextArea, cosa che a me sembra normale a causa della JVM, delle classi base Java, ecc. A questo punto, tuttavia, quando l'applicazione ha terminato il caricamento del file, rimane tranquillamente inattivo, poiché attualmente non lo faccio fare altro. Mentre è inattivo, finché la finestra è attiva, l'utilizzo della memoria dell'applicazione inizia a salire di 10-20kb al secondo. Questo mi sembra strano. Se faccio clic su un altro programma per fare in modo che questa sia la finestra inattiva, la memoria si alza ancora, ma a una velocità molto più lenta (circa 10kb ogni 3-5 secondi).

Non ho provato per vedere fino a che punto sarebbe salito, ma questo mi sembra un comportamento molto strano. È normale questo comportamento di Java? Immagino sia possibile che il mio codice stia perdendo memoria, ma non sono sicuro di come. Ho fatto in modo di chiudere il BufferedInputStream che sto usando, e non riesco a vedere che altro potrebbe causare questo.

Mi dispiace se la mia spiegazione non ha senso, ma apprezzerei qualsiasi intuizione e/o puntatori che qualcuno possa avere.

UPDATE:

su suggerimento, ho praticamente spogliato la mia domanda fino alla classe principale che chiama semplicemente la classe gui. La classe gui estende solo JFrame e imposta le dimensioni della finestra, l'operazione di chiusura e le proprietà visibili. Con questi cambiamenti, la memoria cresce ancora a 10-20kb, ma a un ritmo più lento. Questo, in combinazione con altri consigli che ho ricevuto, mi porta a credere che questo sia solo Java. Continuerò a giocarci e ti farò sapere se scoprirò qualcos'altro di interessante.

+0

Congratulazioni per la tua prima app !!! Forse potresti postare del codice? Senza codice stiamo solo indovinando. Inoltre continua a monitorarlo per vedere se continua a crescere o se si ferma a un certo punto. Pubblica i tuoi risultati. –

+1

@Romain, grazie! Ho pensato di pubblicare il mio codice, ma onestamente, ero più interessato a vedere se questo è in qualche modo normale comportamento di Java (non lo pensavo, ma tutto è possibile!). Investigherò di più e quindi pubblicherò il codice se non riesco a capire perché, tra qualche giorno. Grazie! –

+1

#masternosaj È normale che la memoria fluttui mentre si aggiorna internamente allo schermo e la garbage collection è terminata. Non è normale che la memoria continui a crescere. Se sei un principiante Java, ho visto persone che chiedono recensioni di codice di sezioni di codice su questo sito. –

risposta

9

Prova monitorare l'utilizzo heap con jconsole al posto di Windows Task Manager:

  • lanciare la vostra applicazione con l'opzione -Dcom.sun.management.jmxremote esempio

java -Dcom.sun.management.jmxremote -jar myapp.jar

  • lancio jconsole dalla riga di comando, e la connessione al pid locale del processo di Java è stato avviato nell'ultimo passaggio.
  • Clicca sopra per la memoria e guardare memoria heap (la visualizzazione predefinita)

Se si guarda per un po ', probabilmente otterrete un pattern "dente di sega", come la memoria si arrampica nel corso del tempo, ma poi ha affilato drop-off quando viene eseguito il garbage collector. Puoi provare a "suggerire" la garbage collection facendo clic sul pulsante così etichettato.

Quando si esegue questa operazione, l'utilizzo della memoria scende allo stesso livello minimo o l'aumento minimo complessivo nel corso di diversi minuti? Se l'utilizzo minimo aumenta, si verifica una perdita di memoria.Se ritorna sempre allo stesso livello minimo, allora stai bene.

+1

questa è stata una risposta molto perspicace. Farò un tentativo! –

+1

Ho dato una prova alla JConsole ed è un'utilità piuttosto elegante. Come ho visto, l'utilizzo della memoria heap ha continuato ad aumentare. Quando ho invocato il GC (con il pulsante che hai menzionato), l'utilizzo della memoria era al minimo. Ho provato questo un paio di volte e sempre sceso a circa lo stesso livello minimo. Grazie mille! –

+2

Si noti che JDK 6 ha un'utilità ancora più netta: JVisualVM. Inizialo digitando il comando 'jvisualvm' in un prompt dei comandi. – Jesper

2

Congratulazioni per la prima app! Ora, un paio di cose a cui pensare. Innanzitutto, il task manager di Windows non è una grande risorsa per capire quanto velocemente il tuo VM sta crescendo. Invece, dovresti monitorare le statistiche della raccolta dei rifiuti nella console (usa il parametro della riga di comando -verbose:gc). In secondo luogo, se sei preoccupato per potenziali perdite e la crescita del VM, ci sono un sacco di grandi profiler là fuori che sono facili da usare e possono aiutarti a diagnosticare problemi di memoria. dai un'occhiata a questi twoposts per alcune opzioni di profiler.

+1

@afk, grazie! Ho sentito che il Task Manager di Windows non era il massimo degli strumenti per il monitoraggio delle app Java, ma non sapevo quanto fossero affidabili tali informazioni. Bene, controlla quello che hai menzionato. –

2

Congratulazioni per la tua prima app Java!

Le applicazioni Java vengono eseguite in una macchina virtuale. Alla macchina virtuale è stata assegnata una quantità di memoria fissa dal sistema operativo, in genere 512 MB. Finché l'applicazione utilizza meno di 512 MB, il garbage collector non eseguirà il kick in e inizierà a cercare blocchi di memoria "morti". Il limite di memoria JVM può essere modificato nella maggior parte dei sistemi operativi. Prova ad esempio a cambiare il limite di memoria a 32 MB.

+1

grazie !! Lo terrò a mente. Cercherò di vedere fino a che punto si alza davvero. Grazie per i suggerimenti. –

+0

fondamentalmente corretto, ma nessuna JVM che ho trovato assegnerà un heap iniziale così grande (512 Mb) ... a meno che qualcosa in particolare non lo indichi tramite le opzioni di avvio di JVM. –

1

È normale questo comportamento Java?

No.

Credo che sia possibile che il mio codice potrebbe essere perde la memoria

che è sicuramente la causa. Per favore pubblica il tuo codice sorgente, altrimenti non è possibile effettuare ulteriori diagnosi.

Ho notato che stai utilizzando Swing, assicurati di avviare il tuo JFrame nel event dispatch thread, utilizzando il metodo invokeLater(Runnable).

Se stai utilizzando qualsiasi tipo di raccolta, assicurati di averle immesse una volta terminate con clear.

Dato che si sta eseguendo qualche file di I/O, assicurarsi di chiudere tutte le classi coinvolte nelle operazioni di I/O dopo aver finito con esse.

Se si utilizzano listener di eventi, ricordarsi di rimuovere esplicitamente i listener di eventi quando non sono più necessari.


Una cosa che si può provare è sperimentare. Prendi la tua applicazione e rimuovi il file IO, guarda cosa succede. L'utilizzo della memoria continua a salire come prima? Ora resotre la vostra applicazione alla normalità e rimuovere l'area di testo: la memoria continua a salire come prima? Ecc. Ecc. Ciò ti aiuterà a determinare qual è la fonte e potrai concentrare i tuoi sforzi lì. Molto probabilmente scoprirai quello che cerchi facendo questo.

Un altro strumento di diagnosi utile è quello di utilizzare System.gc() in determinati momenti nel tempo, di solito dopo i blocchi pesanti di codice. Questo dirà alla JVM di eseguire una garbage collection in quel punto dell'esecuzione, piuttosto che in un altro momento determinato dal consumo di memoria. Ciò ti aiuterà a tenere conto delle eventuali fluttuazioni periodiche nell'utilizzo della memoria della tua applicazione.

In caso contrario, è sempre possibile utilizzare un profiler di memoria. Se si utilizza NetBeans IDE, ce n'è uno integrato direttamente. Per Eclipse, ci sono diversi plugin che possono eseguire il profiling.

+1

Com'è utile? –

+0

Sì, questo è Java. Affrontarla. – matiasf

+1

@bguiz Non sono sicuro di capire cosa intendi per thread di invio dell'evento. Sono molto nuovo a Java e non ho visto quello menzionato. –

1

è normale. alcuni calc di sfondo potrebbero lasciare oggetti morti intorno, che JVM non ha fretta di ripulire. alla fine verranno raccolti dei rifiuti, quando viene avvicinato il massimo mem.

lasciare il programma in esecuzione durante la notte, e la macchina non esploderà.

+1

grazie, lo terrò a mente. –