Java Virtual Machine Heap Memory October 14, 2008 03:32 over 3 years ago
En Java proces har et lineart stigende hukommelsens forbrug. En uheldig arkitektur beslutning afstedkommer en konstant øgning af hukommelses forbrug ved eksekvering af processen. Beslutningen resulterer i en begrænset køretid afhængigt af den valgte mængde af hukommelse hvori processen eksekveres.
En proces med ca. 4000 enheder optager ca. femhundrede megabytes. Et anslået estimat på ca. 10.000 enheder vil optage ca. femtenhundrede megabytes og så fremdeles. Det betyder at man skal bruge virkeligt meget hukommelse for at køre programmet færdig.
Kan det lade sig gøre og hvad er hukommelse?
Alle Java processer eksekveres i en JVM, container, som har automatisk hukommelsesstyring. Den allokerede mængde hukommelsen som er afsat til at indeholde programmet kaldes Heap Memory. Denne container kan dekoreres med flag som bestemmer fordelingen mellem de enkelte hukommelsesområder der allokeres til hver applikation.
Der findes forskellige områder eller pools under den fælles betegnelse Heap Memory. Nogle af disse områder holder på nye objekter og andre på gamle. Heap er delt op omkring to hovedområder, heap space og non heap space.
- Eden Space – Pulje, hvorfra hukommelse er oprindelig blev tildelt for de fleste objekter.
- Survivor Space – Pool indeholder objekter, der har overlevet GC for Paradis rummet.
- Tenured generation – Pool indeholder objekter, der har eksisteret i nogen tid i den overlevende plads
- Faste Generation – Besidder alle de reflekterende data i den virtuelle maskine selv, såsom klasse og metode objekter. Med JVMs at bruge klasse deling af data, denne generation er opdelt i read-only og read-write områder.
- Code cache – Memory anvendes til udarbejdelse og opbevaring af native kode
- Perm Gen – Stak eller information om alle de objekter som er placeret i hukommelsen.
Den fælles samlede mængde hukommelse er den vigtigste faktor. Men hukommelsen har også direkte indvirkning på garbage collection. GC er den proces som administrer hukommelsen og sikre at de programmører som skriver Java kode ikke behøver at vide noget om allokering af hukommelse.
Ydeevnen ved garbage collection hænger tæt sammen med hukommelsen. Når hukommelsen når en vis udfyldings grænse kaldes GC af systemet med jævne mellemrum. Under en garbage collection re-allokeres alle objekter i heap. Nogle objekter flyttes mellem forskellige pools mens andre fjernes helt. Heap vokser eller falder ved hver GC for at bibeholde forholdet mellem fri plads og de levende objekter. Fx indeholder Perm information om objekter i Eden og dermed kan man begynde at ane et mønster om relationer mellem de enkelte rum.
Normalt er det god skik at stille JVM MIN til 512m og MAX til det samme. Ved denne indstilling kan systemet starte hurtigt og bruger ikke tid på store re-allokeringer af hukommelse ved GC.
-Xms512m
-Xmx512m
Hvis applikationen hænger eller får en ”java.lang.OutOfMemoryError” har man et heap problem. Typisk vil applikationer blot standse helt eller delvist. Hvis man angiver for stor hukommelse vil det tager langt tid at køre GC og derved vil applikationen opleve ”stop and go” funktionalitet med alvorlig forringelse i ydeevne.
Applikationer med dynamisk kode og mange klasser som fx GEN, JSP, groovy osv kan blive nødt til at øge MaxPermSize. Den default JVM størrelse for stakken er 64 megabyte.
-Xms512m -Xmx1024m -XX:MaxPermSize=128m
Hukommelsen gemmer objekter og stakken holder styr på oplysninger om objekter. Derfor, jo flere objekter, der findes, jo mere information finder der og jo større stak skal gennemløbes ved hver GC. Efter denne logik fyldes Perm hurtigere hvis din applikation indeholder mange små class-filer frem for få store class-filer.
Hvordan sikre man at disse opstarts parameter rent faktisk virker?
I Java 5.0 findes et omfattende overvågnings og ledelsesmæssig værktøj. Jconsole er en grænseflader indtil Java Virtual Machine men giver også out-of-the-box fjernbetjening, overvågning og forvaltning. Den bruger omfattende instrumentering af JVM for at give oplysninger om ressource forbrug af applikationer ved hjælp af Java Management Extension (JMX) teknologi..
Man kan lave sine egne beans til overvågning og styring af selvbyggede processer i JVM. En bean skal følger og opfylde JMX design mønstre. En bean kan repræsentere et program eller en ressource som skal forvaltes. Intern i bean findes læse og skrive attributter samt metoder til invokation. En bean kan også udsende meddelelser ved at foruddefinerede begivenheder.
Hvis man vil monitorere en remote proces i en JVM kan man tilføje disse –D parameter.
-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=[port] -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
Derefter er at blot at starte Jconsole og connected under remote fanen.
Der findes en række parameter man kan overføre til JVM via -D argument. Men måske må du ser realiteten i øjne og erkende at din applikation har alvorlige fejl som bør løses.
- Xmx1500m # Heap size på 1500 MB
- Xincgc # Incremental low pause collector. Løbende oprydning af tenured space.
- XX:GCTimeRatio=24 # lad JVM selv bestemme sit footprint ud fra en målsætning om at bruge 4% af tiden på GC
- Xmn1g # newsize på 1GB, svarer til ratio på 2/3 på jespers server (?)
- Xss128k # reducerer størrelsen af stakken ifht. det vi kører med nu mhp. at skabe mere plads til hoben.
- XX:+UseConcMarkSweepGC # Concurrent mark sweep collector
- XX:SurvivorRatio=10 # Survivor space 1:10
- XX:TargetSurvivorRatio=90 # Bedre pladsudnyttelse af survivor space
- XX:MaxTenuringTreshold=15 # Objekter kan overleve flere sweeps førend de bliver flyttet til tenured
By Frank Vilhelmsen - 2 tags: java server - 1 comment on Java Virtual Machine Heap Memory - Add comment
Andersen October 22, 2008 22:46 over 3 years ago
Spænende artikel.
Den giver et godt og kort indblik i hukommelsesstyring.