2015-11-02 15 views
6

Ho avuto una chiamata di un cliente lo scorso fine settimana che mi diceva che il loro programma Java non rispondeva quando eseguiva un'importazione di dati. I dati sono una semplice cartella di lavoro di Excel con 4 fogli di lavoro. Tutti i dati vengono letti dalle colonne e aggiunti a un database.Combattere la dimensione dell'heap Java, grande differenza tra Java localmente e Java web start

Così ho iniziato a indagare e ho avuto alcuni strani risultati.

  1. Testare l'importazione utilizzando Esegui in Netbeans. Questo utilizza Java esempio a 64 bit:

Prima esecuzione

local first run (64-bit)

Seconda manche

local second run (64-bit)

  1. Test l'importazione utilizzando Java Web Start. Questo è stato lanciato con l'apertura di un file JNLP e utilizza un Java un'istanza a 32 bit:

Prima esecuzione

webstart first run (32-bit)

In questo caso ho avuto lo stesso problema, che il cliente è stato segnalazione, il programma ha smesso di rispondere dopo un po 'durante il processo di importazione. Ciò è dovuto al fatto che sto raggiungendo la dimensione massima dell'heap per quanto posso dire (cerchio rosso).

Seconda manche

Così ho deciso di aumentare la dimensione heap iniziale e dimensione massima heap aggiungendo quanto segue al mio file JNLP: initial-heap-size="512m" max-heap-size="1024m". Quando ho provato nuovamente l'importazione, tutto sembrava funzionare, però ho notato c'è molto di più memoria utilizzata rispetto ai primi 2 casi:

webstart second run (32-bit)

  • Perché c'è una differenza 300MB di utilizzo della memoria tra caso 1 e 2 rispetto al caso 4?
  • L'elevato utilizzo della memoria è il risultato di una programmazione errata o di una perdita di memoria? O è normale avere valori così alti?
  • È l'aggiunta di initial-heap-size="512m" max-heap-size="1024m" una soluzione valida per questo problema?
+4

@StackFlowed Ne dubito molto. – Kayaman

risposta

2

Ebbene, le differenze evidenti sono che le prime uscite sono fatti con un 64-bit server VM e questi ultimi vengono effettuate con un 32-bit client VM.

Presumibilmente il client VM è ottimizzato per una migliore usabilità in un'applicazione di tipo desktop e la VM del server è ottimizzata per il lavoro "server". Non ho una lista completa delle differenze (o se è davvero qualcosa che funziona bene in casi d'uso reali). Non citatemi su questo, ma credo che il client VM eviti GC più della VM del server, perché almeno in un punto è stato percepito come lento.Questo spiegherebbe perché il client VM sta usando molta più memoria, invece di rilasciarlo in modo aggressivo.

Fugging con i parametri del GC a volte è la cosa giusta da fare, e in questo caso è praticamente l'unica cosa che puoi fare, a meno che non identifichino perdite di memoria significative. Non è una cattiva idea avere familiarità con ciò che rende il segno di spunta GC in ogni caso però.

+0

grazie mille per la tua risposta, ho controllato la mia applicazione ulteriormente sulla perdita di memoria guardando Eden & Old gen space ma non ho visto nulla di spettacolare. Per ora è stato corretto con le dimensioni iniziale-heap e max-heap, ma vedrò se posso ottimizzare di più il mio codice. Penso che i picchi di memoria siano causati dai controlli mostrati/nascosti. Anche se immagino che dovrebbe mantenere i riferimenti invece di crearne di nuovi in ​​memoria? – Perneel

+0

Sì, se stai solo nascondendo un componente non lo rende idoneo per GC. È necessario eseguire il campionatore di memoria per un po 'per vedere se è possibile identificare altri hotspot. – Kayaman

+1

Ho cambiato il mio codice. Ho fatto molte richieste di database per creare entità basate sull'input dell'utente, creando sempre un oggetto Client per gestire quella richiesta. Sembra che questo causasse problemi di memoria. Ora metto tutte le entità da creare in un wrapper e le creo in una singola richiesta. – Perneel

Problemi correlati