2015-09-08 11 views
28

Sono in esecuzione Eclipse 4.3 con un Java 7 JRE. Quando eseguo l'upgrade a Java 8 JRE, Eclipse consuma improvvisamente più memoria. Se lancio Eclipse con JRE 7 direttamente nel mio spazio di lavoro, assegna 600 MB di RAM in base al Task Manager. Quando utilizzo JRE 8, questo valore è 750 MB.Java 8 che assegna troppa memoria

Ancora peggio, se eseguo un programma Java di grandi dimensioni che in genere alloca circa 10 GB di RAM con JRE 7, passando a JRE 8 provoca l'allocazione di 12 GB di RAM.

Qualcuno sa quale causa questa allocazione RAM aggiuntiva? Ho testato diverse opzioni tweaking, ma con successo pari a zero:

-XX:ReservedCodeCacheSize= 
-XX:MaxMetaspaceSize= 
-XX:MetaspaceSize= 
... 
+3

quale numero nel task manager stai guardando? – the8472

+0

Perché pensare di cazzeggiare con queste opzioni molto speciali 'ReservedCodeCacheSize',' MaxMetaspaceSize' o 'MetaspaceSize' è la strada da percorrere? Hai controllato che queste aree di memoria speciali sono la causa del maggiore consumo di memoria, piuttosto che della * dimensione heap ordinaria * prima? Oltre a ciò, qual è il punto di Eclipse che consuma 750 MB invece di 600 MB? Sarei felice se Eclipse fosse mai così frugale sulla mia macchina ... – Holger

+4

infatti, la mia eclissi di solito si aggira intorno a 2 GB di RAM (ho bisogno di aumentare il valore predefinito a volte) e le applicazioni java che usano TEN GIGABYTES sono sicuramente difettose in base alla progettazione ; non dovresti usare questa app. Non esiste una cosa come un "grande programma Java", se riesci a ottenere le tue dimensioni JAR sensibilmente più alte di qualche centinaio di MB stai già costruendo enormi strutture applicative - Java è davvero efficiente in termini di dimensioni del file, non lo farai raggiungere mai la barriera di gigabyte a meno che tu non stia sbagliando. – specializt

risposta

9

Nel modo in cui viene posta la domanda

perché Java 8 allocazione troppa memoria sulla mia macchina

non lo faccio pensa che chiunque sarà in grado di rispondere, tuttavia ci sono diverse linee guida che potrebbero aiutare. Dato che stai misurando la memoria tramite il task manager, sei interessato al totale RSS usato. Così

  • Fase 1: Confronta default JVM tra la versione in esecuzione. Puoi ottenerli usando il comando java -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal -version per entrambi i jdks. Usando l'ordinamento del testo sopra l'output sarai in grado di ottenere una bella differenza usando qualsiasi strumento di confronto. Cose come cambiare il collector GC di default e le dimensioni dello stack thread influenzeranno molto l'RSS finale.
  • Passaggio 2: Misurare l'allocazione per ciascun pool di memoria. In memoria totale generale utilizzato da Java potrebbe essere calcolato utilizzando heap + metasize + code cache + native + (thread_stack_size * maximum_number_of_threads)
    • memoria heap facile misurabili (e potrebbe essere facile rispetto !!) da strumenti maturi (Eclipse Memory Analyzer, VisualVM, etc.). Se ricordi l'ingrandimento di nell'area di heap, sei molto fortunato. In vm visuale aggiuntivo è possibile installare plugin che mostreranno i valori di tutti i pool di memoria accessibili tramite jmx.
    • metasize (aka permgen in jdk < 8) dovrebbe più/meno uguale e potrebbe essere trovato con lo strumento jmap. Non c'è bisogno di giocare con la bandiera, è possibile ottenere il numero e confrontare ogni volta che è aumentato o meno.
    • Code cache: oltre alla cache del codice riservato, è possibile impostare la cache del codice iniziale (che influirà sulla quantità di RSS utilizzata).
    • nativo: è un po 'di pecora nera. Se tutti gli altri pool di memoria sono uguali (la memoria è di 2 GB), la memoria persa deve trovarsi da qualche parte nell'area nativa. L'unico strumento di cui sono a conoscenza è jcmd e ha una vasta documentazione nei documenti di Oracle.

non tecnico - mentre tweaking varie opzioni al fine di ridurre la memoria può aiutare, le probabilità di ottenere valori di destra sono vicino a trovare l'ago nel pagliaio. Consiglio vivamente di avere un about su come viene utilizzato RSS in java. Questa conoscenza sarà utile per diversi anni!

Per favore fatemi sapere quando volete più riferimenti concreti o una spiegazione migliore. E...buona fortuna con la tua ricerca ;-)

+0

Non vedo un aumento della memoria heap e memoria metaspace quando si confrontano JDK7 e JDK8. Ho eseguito le misurazioni con'jvisualvm'. Impostando ReservedCodeCacheSize su 48 MB come il valore predefinito in JRE7 ha solo un impatto minimo.È la memoria nativa che cresce di dimensioni. – RegedUser00x

+0

Entrambi i bit jdks 64 (o 32)? Chiedendo perché non lo hai specificato in questione. –

+0

Sì, utilizzo solo 64 bit: JDK7 a 64 bit, JDK8 a 64 bit, JRE7 a 64 bit e JRE8 a 64 bit. – RegedUser00x

1

Posso confermare che un'applicazione Web su cui sto lavorando (Jetty, Struts2, JDBC) consuma circa 300 MB di RAM in più (1.2G) subito dopo l'avvio quando è in esecuzione in JRE 1.8.0_72 rispetto a JRE 1.7.0_80. L'applicazione è in esecuzione su Centos 6 x64 e per rendere la misurazione della memoria il più trasparente possibile ho disabilitato swap e set -Xms pari a -Xmx (40% della RAM disponibile). Ho usato dstat --top-mem o top -m per ottenere la memoria totale consumata dal processo java.

Inoltre, quando i client Web si collegano troppo spesso all'applicazione, la memoria totale consumata aumenta fino a quando il sistema non ha memoria e uccide il processo java. L'unica cosa che posso vedere è un'informazione in/var/log/messages:

10 nov 21:29:54 mio kernel: Memoria insufficiente: Kill processo di 26610 (java) punteggio 570 o un bambino sacrificio

Quando eseguo un ciclo infinito da bash che richiama 4 client Web paralleli che si collegano all'applicazione (= stabilisce una nuova connessione TCP), richiedere lo stato dell'applicazione e disconnettersi, quindi la memoria totale consumata dall'applicazione aumenta di circa 100-200 KB ogni minuto. Ogni cliente fa 6-10 richieste al minuto. La dimensione della memoria heap utilizzata è stabile.