2009-07-27 11 views
20

La mia applicazione Java esegue un'altra applicazione Java, eseguendo il processo "java -jar j.jar". J.jar è noto per utilizzare un sacco di memoria a seconda del set di dati che viene fornito, e spesso ottiene un heap OutOfMemoryError. Quindi voglio usare -Xmx su di esso, in modo da poter allocare più memoria possibile (o vicino). Stavo pensando di ottenere la memoria totale sul sistema, quindi di specificare l'80-90% di quello in -Xmx.Java -Xmx, memoria massima sul sistema

C'è qualche soluzione al mio problema? E come suona la mia soluzione?

Modifica: Non riesco a ridurre il consumo di memoria poiché la memoria utilizzata è la compressione pack200 integrata di Java, che sto utilizzando per il confezionamento di alcuni file JAR.

+3

Così si sta effettivamente chiedendo come utilizzare Java per determinare la quantità di memoria di sistema? –

+0

Sì, sarebbe una soluzione possibile, e se conosci un modo, sapendo che sarebbe apprezzato. –

+0

stai usando un jvm a 64 bit? perché se stai usando un 32 bit, allora avrai problemi con il bit '80% 'se il tuo mem gratuito diventa 7G, ad esempio –

risposta

4

seconda del sistema operativo, questo potrebbe funzionare per ottenere la dimensione della memoria libera e disponibile:

java.lang.management.OperatingSystemMXBean mxbean = java.lang.management.ManagementFactory.getOperatingSystemMXBean(); 
com.sun.management.OperatingSystemMXBean sunmxbean = (com.sun.management.OperatingSystemMXBean) mxbean; 
long freeMemory = sunmxbean.getFreePhysicalMemorySize(); 
long availableMemory = sunmxbean.getTotalPhysicalMemorySize(); 

Da lì, si può capire 80-90% e lanciare il vostro vaso con la dimensione della memoria massima che si desidera .

Non so che questo funziona con tutti i sistemi operativi (ad esempio Windows), ma ha funzionato quando l'ho testato sia con OSX e Linux.

+1

Grazie! Ho provato questo comando su Windows e Linux, e ha funzionato perfettamente. –

+1

Sembra che funzioni solo sulla JVM sole, ho bisogno di distribuire su IBM JVM, quindi non posso correre con chiunque userà il sole. –

0

Beh, una cosa che posso dirti è non lasciare che la tua app si avvicini a riempire ram. Le app Java non si scambiano per niente con garbo. Penso che grazie alla Garbage Collection, java estrae costantemente la memoria dallo scambio.

Mi sono imbattuto in un punto morto in cui penso che il sistema chiedesse alla memoria Java che causerebbe un GC e tirerebbe fuori dal file di scambio: a questo punto il sistema girerebbe solo fino a quando non lo reimpostato.

Questo era con un sacco di RAM e un sacco di spazio di swap (per il tempo) e un vecchio VM Java, quindi il tuo chilometraggio può variare.

Inoltre, a seconda di come si avvia quell'altra app, potrebbe essere necessario specificare -Xms per l'app anziché l'altra. Se gli stai dando un comando completo, dagli il -Xms, ma se stai semplicemente chiamando la classe principale nel jar, allora la tua app ha bisogno di -Xms. (Oh, hai specificato, sì, devi passarlo nel comando "Java" che stai chiamando.)

0

C'è un motivo per cui stai usando il sistema operativo per eseguire il programma nel barattolo? Se non ne hai bisogno per eseguire in un processo separato dalla tua applicazione, puoi semplicemente invocare il metodo principale direttamente dal tuo codice e avviare l'applicazione con qualsiasi cosa -Xmx desideri.

+0

Avviare l'altra applicazione o avviare la mia applicazione pone gli stessi problemi. Se eseguo l'altra applicazione con il suo metodo principale, ho ancora bisogno che la mia applicazione sia in grado di utilizzare molta memoria. –

0

C'è un post completo sul blog su come risolvere le applicazioni java con jconsole e altri strumenti nel seguente blog. Tieni presente che la mancanza di controllo dell'uso della memoria è molto probabilmente una perdita di memoria, ma potrebbe anche essere dovuta ad altri motivi. Dai un'occhiata al post, prova a replicare quello scenario e vedi se questo ha risolto il tuo problema.

http://www.kiragiannis.com/cloud-computing/debug-a-java-application-in-the-cloud/

0

Se non è stato già fatto, è necessario eseguire il programma attraverso un profiler di memoria. Potresti scoprire che alcune strutture di dati non vengono smaltite, anche se non vengono più utilizzate.

JProfiler è piuttosto carino, ma è possibile ottenere le stesse informazioni utilizzando hprof, che è stato introdotto in Java 5: http://java.sun.com/developer/technicalArticles/Programming/HPROF.html

Tenete presente anche che piattaforme diverse hanno diverse dimensioni massime di heap, basata su architettura (32- bit vs 64-bit), sistema operativo e persino JVM.

Se si dispone di molti valori che possono essere riutilizzati (come le stringhe che si stanno leggendo da un file XML), si potrebbe ottenere un'enorme riduzione dei requisiti di memoria mediante il pooling degli oggetti.

13

Il limite per -XmX è -Xmx1500m su finestre a 32 bit. Le librerie condivise ostacolano un heap più grande. Per eseguire questa operazione sono necessari circa 2 GB di RAM.

Su sistemi operativi non Windows, è possibile aumentare le dimensioni e le JVM a 64 bit sono in grado di MOLTO di più.

Windows XP non consente di avere più di 3Gb di RAM (non interessa se si dispone di 4 GB fisici, a partire da XP SP3) Vista potrebbe essere diverso YMMV.

Ho provato -Xmx4000M su una JVM a 64 bit su Linux a 64 bit e andava bene. considerando che avevo 6 GB di RAM fisica, non era una grande richiesta.

L'idea dell'80% è interessante, ma i miei sistemi di test hanno percentuali più alte di quelle senza effetti negativi. (Fintanto che non provi a fare nient'altro.)

E l'altro commentatore ha ragione, l'immagine in memoria della tua JVM in memoria non è veloce. Più tardi JVM è meglio farlo con meno disordine (ma hanno anche migliori garbage collector)

Se non riesci a ridurre il consumo di memoria - e so quanto sia difficile - allora disponi di un sacco di RAM fisica e destinare la maggior parte di esso.

Problemi correlati