Você está na página 1de 96

Gerncia de memria em Java

Edio 1.0 (outubro 2005)

Tutorial

Helder da Rocha (helder.darocha@gmail.com)

1 Arquitetura da JVM, memria e algoritmos de coleta de lixo 2 Arquitetura da HotSpot JVM e otimizao de performance 3 Finalizao, coletor de lixo, memory leaks e objetos de referncia

ArgoNavisJ281

GernciadememriaemJava

2005,HelderdaRocha.OsdireitosautoraissobreestaobraestoprotegidospelaLei9.610/98 (LeideDireitosAutorais).Estetutorialpodeserusadoparaestudopessoal.Ousocomomaterial detreinamentos,cursoseareproduoparaoutrosfinsrequerautorizaodoautor.

Sobre o autor
HelderdaRochanasceuemCampinaGrande,Paraba,em1968,viveuofinaldainfnciaem Waterloo, Canad (19751980) e reside em So Paulo desde 1995. instrutor e consultor em tecnologia da informao. Fundador da Argo Navis empresa de treinamento e consultoria especializadaemsistemasabertosrealizapesquisasemJavadesde1995.Ocasionalmenteescreve para revistas especializadas e est sempre presente como palestrante nos principais eventos nacionaissobreJava.autordemaisde20cursossobreJava,XMLetecnologiasInternet. Em 1996, comeou a escrever um livro sobre Java e nunca terminou, mas acredita que ir conseguiratempoparaoJava6,em2006. Alm do mundo da informtica, o autor tambm explora diversas outras reas do conhecimento,comoaecologia,aliteratura,aastronomia,amsicaeoteatro,nemsemprecomo hobby.EntresuasatividadesalternativasestatraduoparaoportugusdaDivinaComdiade Dante e do poema O Corvo de Edgar Allan Poe, adaptado para o teatro. Tem feito tambm adaptaes para teatro de outros autores, pesquisa teatral, dramaturgia e cenografia alm de apresentarse como ator e msico em peas de teatro amador em So Paulo. Quando no est viajandoatrabalho(ounosintervalos)aproveitaparaacamparnasmatasepantanaisdoplaneta, observaroUniversoevezououtraarriscarumafotodosplanetasoudaLua. Paraentraremcontatocomoautor,utilizeosemailsousitesabaixo: helder.darocha@gmail.com(email) www.argonavis.com.br(empresa) www.helderdarocha.com.br(sitepessoaleblog)

Sobre a Argo Navis


A ArgoNavis tem como objetivo explorar, assimilar e divulgar novas idias do mundo das tecnologias abertas de informtica, mapeando o territrio e indicando os melhores caminhos. Suamissodifundirainformaoeremovendobarreirastecnolgicas,culturaiseeconmicas. Essa ao realizada atravs da pesquisa e desenvolvimento de palestras, cursos, artigos, tutoriais, livros e exemplos didticos em portugus que tem seu material distribudo gratuitamente e so financiados por atividades de treinamento, consultoria, mentoring, venda delivroseparceriasdetreinamento. A Argo Navis realiza treinamentos personalizados em tpicos bsicos e avanados de Java, XML e tecnologias Web (HTML, JavaScript, CSS e assuntos relacionados) para grupos ou empresas em qualquer parte do Brasil ou do mundo. Ministramos treinamentos em ingls e portugus e desenvolvemos material de treinamento sob demanda nos dois idiomas. Para maioresinformaesedownloadgratuitodetodoomaterialdetreinamentousadonoscursos pblicos,visiteositewww.argonavis.com.br.
R672g

Rocha,HelderLimaSantosda,1968 Tutorial:gernciadememriaemJava.EdioemPDF.Primeiraedioconcludaem 31deoutubrode2005.FormatoA4.NOREVISADA.

1.Java(Linguagemdeprogramaodecomputadores)Gernciadememria.2.Gerncia de memria virtual em computadores (Administrao de sistemas). 3. Algoritmos de coletadelixo(EngenhariadeSoftware).I.Ttulo.

CDD005.133

2005HelderdaRocha

ArgoNavisJ281

GernciadememriaemJava

ndice
Introduo.................................................................................................................. 4 ParteIGerenciadememria?EmJava?............................................................ 6 1.AnatomiadaJVM ............................................................................................. 7 Apilha,oheapeaJVM ....................................................................................... 8 AnatomiadaJVM:reasdedados ....................................................................... 9
OregistradorPC....................................................................................................... 9 Pilhas.......................................................................................................................... 9 Quadrosdepilha(frames) .................................................................................... 10 Oheap...................................................................................................................... 11

2.Algoritmosdecoletadelixo.......................................................................... 13 Algoritmosparacoletadelixo ........................................................................... 14 Contagemdereferncias .................................................................................... 15 Coletadeciclos................................................................................................... 17 Algoritmosderastreamento(tracingalgorithms)............................................. 19 AlgoritmoMarkandSweep............................................................................... 19 AlgoritmoMarkandCompact........................................................................... 20 Algoritmodecpia............................................................................................. 21 3.Estratgiasdecoletadelixo .......................................................................... 24 Generationalgarbagecollection......................................................................... 24 Ageorientedgarbagecollection......................................................................... 27 4.Coletadelixoemparalelo ............................................................................. 29 Coletoresincrementais....................................................................................... 29 Trainalgorithm.................................................................................................. 32 SnapshotseSlidingViews................................................................................. 32 Coletoresconcorrentes ....................................................................................... 33 Concluses ......................................................................................................... 33 ParteIIMonitoraoeconfiguraodamquinavirtualHotSpot ............ 34 5.ArquiteturadaHotSpotJVM ........................................................................ 35 Opesdelinhadecomando .............................................................................. 35 BrevehistriadacoletadelixoemJava ............................................................. 36 OcoletordelixoserialdoHotSpot .................................................................... 37 Geraojovem.................................................................................................... 38 Geraoestvel................................................................................................... 39 Geraopermanente........................................................................................... 40 6.Configuraodememria ............................................................................. 41 Definiodelimitesabsolutosparaoheap ........................................................ 41 Tamanhofixodapilha........................................................................................ 42 Variaodotamanhodoheap............................................................................. 43 Proporogeraojovem/estvel ....................................................................... 45 Proporoden/sobreviventes ........................................................................... 46

2005HelderdaRocha

ArgoNavisJ281

GernciadememriaemJava

7.Seleodocoletordelixo............................................................................... 48 Algoritmosutilizados ........................................................................................ 48 Coletaincremental ............................................................................................. 50 Opesdeparalelismo........................................................................................ 51 Comoescolherumcoletordelixo?..................................................................... 52 8.Monitoraodeaplicaes............................................................................. 55 Comoobterinformaessobreascoletas ........................................................... 55 Monitoraocomojconsole ............................................................................. 56 Monitoraocomasferramentasdojvmstat .................................................... 58 Outrasferramentas............................................................................................ 59 9.Ajusteautomtico:ergonomics..................................................................... 61 Controlesdeergonmicanocoletorparalelo ..................................................... 61 Comoutilizaraergonmica............................................................................... 62 Concluses ......................................................................................................... 63 10.Apndice:Classdatasharing(CDS) .......................................................... 63 ParteIIIFinalizao,memoryleakseobjetosdereferncia........................ 64 11.Alocaoeliberaodememria ............................................................... 65 Criaodeobjetos............................................................................................... 65 Destruiodeobjetos ......................................................................................... 66 Alcanabilidade.................................................................................................. 68 Ressurreiodeobjetos ...................................................................................... 69 Comoescreverfinalize()..................................................................................... 70 FinalizerGuardian ............................................................................................ 74 Finalizaodethreads........................................................................................ 74 Comotornarumobjetoelegvelremoopelacoletadelixo? ......................... 75 Resumo............................................................................................................... 77 12.Memoryleaks ................................................................................................ 78 Comoachareconsertarvazamentos? ................................................................ 80 13.Refernciasfracas.......................................................................................... 82 APIdosobjetosdereferncia ............................................................................. 82 Comousarobjetosdereferncia......................................................................... 83 Alcanabilidadefracaeforte .............................................................................. 84 Foradaalcanabilidade .................................................................................... 85 SoftReferenceeWeakReference.......................................................................... 86 ReferenceQueue ................................................................................................. 88 Finalizaocomreferenciasfracas ..................................................................... 89 Refernciasfantasma ......................................................................................... 91 WeakHashMap................................................................................................... 93 Concluses ......................................................................................................... 94 Referncias .............................................................................................................. 95

2005HelderdaRocha

ArgoNavisJ281

GernciadememriaemJava

Gerncia de Memria em Java


HelderdaRocha ESTE TUTORIAL explora detalhes sobre o uso de memria virtual em aplicaes Java.Estdivididoemtrspartes. Aprimeiraparteexploraosdetalhesdofuncionamentodamquinavirtual emrelaoexecuoegernciadememria,ostiposdealgoritmosusados para coleta de lixo, as diferentes regies da memria onde eles atuam. So detalhados aspectos da arquitetura da mquina virtual de acordo com a especificao,enocomalgumaimplementaoespecfica(comoaSunHotSpot.) Existem vrios diferentes tipos de coletores de lixo e diversas estratgias de coletaquecombinamalgoritmos.Estetutorialconcentrasenosmaisimportantes. Nem todos so implementados nas mquinas virtuais Java mais populares, porm como as tcnicas usadas mudam a cada nova verso dos ambientes de execuoJava,valeapenaconheclasjquepoderoseropesemmquinas virtuaisnofuturo. Asegundapartedotutorialabordaaarquiteturadememriadasmquinas virtuaisHotSpot.Essasmquinasvirtuaissodistribudascomosambientesde execuo da Sun e vrios outros fabricantes. Suportam configurao de vrios recursos, entre eles estratgias de alocao e coleta de lixo. So discutidos os efeitosdaalteraodeparmetrosecomoconfigurlosparaobterosmelhores resultados,ajustandoaorganizaodamemriaealgoritmosdecoletadelixo. Para otimizar preciso medir, e para isto existem vrias ferramentas de monitorao e minerao de dados distribudas como parte dos ambientes de desenvolvimento Java. Ser mostrado como usar os dados obtidos com as ferramentasJConsole,JstateGCViewer. A terceira e ltima parte discute detalhes sobre a criao e destruio de objetos em Java. Diferentemente das outras duas sees, esta mostra o que o programadorpodefazerarespeitodagernciadememriaemJava.Algumas dasquestesabordadasso:comofuncionaacriao,finalizaoeremoode objetos; o que so memory leaks, como identificlos e consertlos; como controlar eficientemente o coletor de lixo usando objetos de referncia; e como construiraplicaesrobustasquelidameficientementecomamemriaalocada pelamquinavirtual. O leitor deste tutorial deve ser um programador, no necessariamente experienteemJava.AterceiraparterequerconhecimentosbsicosdeJava.
2005HelderdaRocha 5

Tutorial

ArgoNavisJ281

GernciadememriaemJava

Parte I - Gerencia de memria? Em Java?


PorquesepreocuparcommemriaemJava?DiferentementedeCouC++, programadores Java no tm a responsabilidade e nem a possibilidade de gerenciaramemriadosistemaexplicitamente.EmJava,possveldesenvolver aplicaes programando em alto nvel sem se preocupar com questes como alocao e liberao de memria, que so realizadas automaticamente pela mquina virtual usando algoritmos. Um programador Java pode desenvolver aplicaes preocupandose apenas com a lgica do programa. Ento para que discutir esses detalhes, j que um esforo to grande foi realizado exatamente paraquenofossenecessriodiscutilos? Como tudo o que feito automaticamente, as solues foram construdas para os casos mais comuns, mais genricos. Todas as mquinas virtuais modernas buscam adaptarse o melhor possvel ao ambiente onde suas aplicaesiroexecutar,porm eseseuambienteforatpico?Sesuaaplicao for gigante, usar muita memria, mantiver muitos objetos vivos, ou realizar algumacomputaoincomum,aconfiguraodefaultdamquinavirtualpode revelarse inadequada. A maior parte dos algoritmos de coleta de lixo, por exemplo,sootimizadosparasituaestpicas,ondeasaplicaesoutmuma vidacurtaoucontamcomumadistribuioprevisveldeobjetosduradouros.O mesmoocorrecomadistribuiodememriaqueinfluenciaaalocaoeficiente. A maior parte das aplicaes iro funcionar satisfatoriamente nas mquinas virtuais mais populares sem requerer nenhum ajuste sequer, porm outras aplicaes podem se beneficiar de ajustes para melhorar sua performance, escalabilidade,segurana,consumodememria,etc. Fazerajustesnoumaatividadetrivial.Muitosajustestmefeitocolateral. Ajustes no coletor de lixo, por exemplo, geralmente comprometem a eficincia daaplicaonatentativadereduzirpausas.Quandosebuscaamaioreficincia, geralmente ganhase pausas mais longas. Alm disso, os ajustes que uma mquina virtual oferece so disponibilizados atravs de opes que no so padronizadas. Podem mudar de uma verso para outra. Os algoritmos de gernciadememriamudamdeumaversoparaoutra.Assim,cadavezmais importante que o administrador do sistema tenha conhecimentos sobre a arquiteturadasmquinasvirtuaisealgoritmosdecoletadelixo.Saberoquanto, quando, onde ajustar requer conhecimentos elementares da organizao da memria, dos algoritmos de alocao e coleta de lixo empregados pela implementaodaJVM1usada. O objetivo desta seo cobrir os principais tpicos de arquitetura da mquina virtual Java que afetam a performance da gerncia automtica de memria.Aabordagemnestaseosermaisacadmica,semlevaremconta nenhumaimplementaoespecfica.
1

JVM=JavaVirtualMachine:mquinavirtualJava.amquinaondeexecutaqualqueraplicao Java.

2005HelderdaRocha

ArgoNavisJ281

GernciadememriaemJava

1. Anatomia da JVM
A mquina virtual Java (JVM) uma mquina imaginria implementada como uma aplicao de software [JVMS]2. Ela executa um cdigo de mquina portvel (chamado de Java bytecode) armazenado em um formato de arquivo chamadodeclassfileformat(formatodearquivoclass).Umarquivoemformato class geralmente3 gerado como resultado de uma compilao de cdigofonte Java,comomostradonafigura1.

Figura1ProcessodeconstruodeaplicaesemJava:cdigofonteemJavacompiladoemlinguagem demquinavirtual(arquivo.class)quelidopeloambientedeexecuo(mquinavirtual).

Uma das decises de design da plataforma Java foi a de esconder do programador detalhes da memria. A especificao da mquina virtual (Java VirtualMachineSpecification[JVMS])noespecificadetalhesdesegmentaoda memria(comoocorreousodememriavirtual,ondeficaapilha,oheap,etc.), oalgoritmodecoletadelixousadoparaliberarmemria(dizapenasquedeve haverum),nemvriosoutrosaspectosdebaixonvelcomoformatodetipos,etc. Diferentes implementaes da JVM tm a liberdade de organizar a memria diferentemente e escolher algoritmos de coleta de lixo diferentes. Exemplos de implementaesdemquinasvirtuaisJavaso: SunHotSpotJVM:amaispopularemdesktopseservidores;amquina virtualdaIBMsimilar,pormusaoutrasopesdeconfigurao.H mquinasdeoutrosfabricantes(Oracle,Borland,etc.)emboracompatveis comaHotSpotpodemnoterosmesmoscomandosdeconfigurao. SunKVM:oumquinavirtualK.usadaemdispositivoscomopalmtops ecelularesparaexecutaraplicaesJ2ME. JikesRVM:umamquinavirtualexperimental,construdaapartirde umprojetodaIBMehojeumprojetodecdigoaberto.amquina virtualmaispopularentrecientistas.Amaiorpartedosartigoscientficos sobrecoletoresdelixousamcomobenchmarkaJikesRVM,mesmoosque tmcomoalvooutrasplataformas,como.NET.
2 3

Asrefernciasentrecolchetesestorelacionadasnaltimaseodestetutorial. possvelgerarbytecodeJavaapartirdeoutraslinguagensdiferentesdeJava,apesardeno sercomumnemseroficialmentesuportado(comoocorrecom.NET).

2005HelderdaRocha

ArgoNavisJ281

GernciadememriaemJava

A pilha, o heap e a JVM


Existem linguagens em que a alocao de memria trivial, e no requer gerenciamentocomplexo.Asprincipaisestratgiasso: Alocaoesttica:reasdememriasoalocadasantesdoinciodo programa;nopermitemudanasnasestruturasdedadosemtempode execuo(ex:Fortran) Alocaolinear:memriaalocadaemfilaouempilha;nopermite remoodeobjetosforadaordemdecriao(ex:Forth) Alocaodinmica:permiteliberdadedecriaoeremooemordem arbitrria;requergernciacomplexadoespaoocupadoeidentificao dosespaoslivres(ex:Java,C++) Java utiliza alocao dinmica (heap) para objetos e alocao linear (pilha) para procedimentos seqenciais, mas todo o gerenciamento feito automaticamente. A figura 2 ilustra um diagrama lgico de segmentao de memria virtual. A representao apenasummodelogenricoenorepresentanenhuma implementao real, porm til para ilustrar os diferentes papis assumidos pela memria em linguagens que usam alocao dinmica e linear. Os blocos no heap indicam memria alocada dinamicamente. O espao entre os blocos ilustra a fragmentao,queumproblemaquepodeocorrerem alocao dinmica. Se o modelo representar uma mquina virtual Java, os blocos na pilha podem representar frames (seqncias de instrues de cada mtodo) de um nico thread. As setas da pilha para o heapedeblocosdoheapparaoutrosblocosdoheapso ponteiros. DopontodevistadeumprogramadorJava,asreas de memria virtual conhecidas como a pilha e o heap Figura2 Esquema lgicode so lugares imaginrios na memria de um baixo nvel. Este diagrama computador. No interessa ao programador nem apenas um modelo genrico (inspirado em modelos de adianta ele saber onde esto nem os detalhes de como segmentao de memria soorganizados,umavezqueJavanoofereceopes C++) e no reflete nenhuma de escolha para alocao no heap ou na pilha como implementaoreal. ocorre em C ou C++. Alm disso, a especificao da mquinavirtualgaranteliberdadeaoimplementadordemquinasvirtuaisJava paraorganizaramemriacomobementender.Oqueinteressaaoprogramador Java onde as alocaes so feitas: em Java, tipos primitivos ficam sempre na pilhaeobjetosficamsemprenoheap. Implementaes da especificao da JVM, (como a HotSpotJVM), oferecem parmetrosquepermitemalgumcontrolesobreagernciadememriavirtual.

2005HelderdaRocha

ArgoNavisJ281

GernciadememriaemJava

Conhecer as escolhas de algoritmos e arquitetura da mquina virtual usada importante para saber como configurla e ter uma base para saber quais parmetros ajustar para obter melhor performance. Ainda assim, o controle muito limitado, voltado principalmente para administradores e muito pouco pode ser feito por programadores. Portanto no existe, em Java, a disciplina gernciadememriadaformacomoexisteemCouC++.Mashestruturase escolhasqueumprogramadorpodefazerusandoalinguagemqueinfluenciam ocoletordelixoeaalocaodememria.Essesrecursosserovistosnaterceira partedestetutorial.

Anatomia da JVM: reas de dados


A mquina virtual define vrias reas de dados que podem ser usadas durante a execuodeumprograma. Registradores Pilhasesegmentosdepilha(quadros) Heapsereademtodos Existem reas de dados que so compartilhadas por operaes que executam em paralelo e outras que so privativas. As reas de dados privativas esto associadas a threads e so criadas (alocadas)quandoumthreadnovocriado, Figura 3 reas de dados usadas pela sendo destrudas (liberadas) quando o mquinavirtualJava. thread termina. As reas ligadas mquina virtualsocompartilhadasentreosthreadsativosesocriadasquandoaJVM iniciadaedestrudasquandoaJVMtermina. O registrador PC Cada thread de execuo tem um registrador PC (program counter), que mantm controle sobre as instrues da mquina virtual que esto sendo executadas. Em qualquer momento, cada thread estar executando o cdigo de um nico mtodo. Um mtodo (em cdigo bytecode) consiste de uma lista de instrues executadas em uma seqncia definida. O registrador PC contm o endereodainstruodaJVMqueestsendoexecutada.Ovalordoregistrador PC s no definido se o mtodo for um mtodo nativo, que um mtodo implementadoemlinguagemdemquinadaplataformaonderoda. Pilhas Cada thread criado com uma pilha associada que usada para guardar variveis locais e resultados parciais. A memria usada pela pilha podeseralocadanoheap,noprecisasercontguae liberada automaticamente depois de usada. Uma Figura4Apilhadeumthread. ilustrao esquemtica da pilha mostrada na figura 4. A pilha pode ter um

2005HelderdaRocha

ArgoNavisJ281

GernciadememriaemJava

tamanhofixoouexpandirseecontrairsenamedidaemquefornecessrio.As implementaes de mquinas virtuais Java podem oferecer controles para ajustartamanhodepilhas. Quando a memria acaba em uma operao relacionada pilha, dois erros podemocorrer: StackOverflowErrorocorreseacomputaodeumthreadprecisardeuma pilhamaiorqueapermitida.Mtodosquecriammuitasvariveislocais oufunesrecursivassoaprincipalfontecausadoradessetipodeerro. OutOfMemoryErrorocorresenohouvermemriasuficientepara expandirumapilhaquepodecrescerdinamicamente.Esteerrotambm podeocorreremaplicaescommuitothreadsquecriammuitaspilhasa pontodeesgotaramemrianecessriaparaalocaroespaomnimo determinadoparaapilha.Asoluopodeserdiminuironmerodo threadsouotamanhoinicial(oufixo)dapilhadecadathread. Quadros de pilha (frames) Um quadro (frame) um segmento alocado a partir da pilha de um thread. Um quadro criado cada vez que um mtodo chamado e destrudo quandoachamadatermina(normalmenteouatravs deexceo).Todomtodotemumquadroassociado e ele sempre local ao thread, no podendo ser compartilhado com outros threads. usado para guardar resultados parciais, dados temporrios, Figura5Umquadrocontma realizar ligao dinmica, retornar valores de execuo de um mtodo. mtodosedespacharexcees. Em um determinado thread, apenas um quadro est ativo em um determinado momento: o quadro corrente: seu mtodo chamado de mtodo correnteesuaclassechamadadeclassecorrente.Cadaquadropossuiumarray de variveis locais, uma pilha de operandos e uma referncia ao pool de constantes de tempo de execuo da classecorrente. Chamadas de mtodos continuamente criam e destroem quadros durante a execuo de operaes. A figura 6 ilustra esse comportamento. Quando o mtodo correntem1,associadoaoquadroq1,chamaoutromtodo m2,umnovoquadroq2criado,quepassaaseroquadro corrente. Quando o mtodo m2 retornar, o quadro q2 retornaoresultadodasuachamada(sehouver)aoquadro q1. O quadro q2 descartado e q1 volta a ser o quadro corrente. Figura 6 Criao e Cadaquadropossuiumvetordevariveiscontendoas destruio de quadros nas variveis locais do seu mtodo associado. Variveis de at chamadasdemtodos 32 bits ocupam um lugar no array. Variveis de 64 bits
2005HelderdaRocha 10

ArgoNavisJ281

GernciadememriaemJava

ocupam dois lugares consecutivos. So usadas para passar parmetros durante a chamadademtodos. Na linguagem de mquina Java, as variveislocaissoacessadaspeloseundice (a partir de 0). Em mtodos estticos, a varivel local de ndice 0 o primeiro parmetro passado ao mtodo, mas em mtodos de instncia, os parmetros so passadosapartirdavarivellocaldendice 1. Isto ocorre porque a varivel local de Figura7Arraysdevariveislocaispara ndice0semprecontmovalor doponteiro doismtodos:soma(),mtododeinstncia, paraoobjetoqueocontm.Esteponteiroa emain(),mtodoesttico. refernciaqueemJavachamasethis. A figura7 mostra um diagrama lgico do array de variveis locais e alguns mtodosassociados. Cada quadro contm uma pilha LIFO conhecida como pilha de operandos. Quando o quadro criado, a pilha vazia. Durante a execuo do programa, instrues da mquina virtual carregam constantes ou valores devariveis locais ou campos de dados paraa pilhadeoperandos,eviceversa. Figura8Pilhadeoperandos A pilha de operandos tambm serve para preparar parmetros a serem passados a mtodos e para receber seus resultados. Qualquer tipo primitivo pode ser armazenado e lido da pilha de operandos. Tiposlongedoubleocupamduasunidadesdapilha.Operaessobreapilhade operandosrespeitamostiposdosdadosguardados. O heap O heap a rea de dados onde todas as instncias e vetoressoalocados.compartilhadaportodososthreads. O heap criado quando a mquina virtual iniciada. Noprecisaserumareacontgua.Oseuespaoocupado por objetos reciclado por um sistema automtico de gerenciamento de memria o coletor de lixo cujo algoritmodependedaimplementaodaJVM. O heap pode ter tamanho fixo ou ser expandido e contrado automaticamente. Diferentes implementaes damquinavirtualpodemoferecercontrolesparaajustar Figura9reasdoheap. tamanho inicial, mnimo, mximo ou fixo do heap. Seum programa precisar de mais heap que o que foi disponibilizado, a JVM causar OutOfMemoryError. A rea de mtodos (figura 9) a parte do heap usada para guardar cdigo compiladodemtodoseconstrutores.criadaquandoamquinavirtualinicia
2005HelderdaRocha 11

ArgoNavisJ281

GernciadememriaemJava

egeralmentearmazenadaemumareadealocaopermanente(aespecificao no determina a localizao 4 ). Assim como as outras reas do heap, compartilhada por todos os threads.Guarda estruturas que so compartilhadas por todos os mtodos de uma classe como: pool de constantes de runtime (constantesdediversostiposusadospelomtodo)edadosusadosemcampose mtodos. OutOfMemoryError pode tambm ocorrer se em algum momento no houvermaisespaoparaarmazenarocdigodemtodos. A ferramenta javap permite visualizar o contedo de um arquivo de classe. Para obter informaes sobre a estrutura de uma classe e instrues da JVM usadasuse
javap c nome.da.Classe

Asintaxe
javap [-opes] nome.da.Classe

Usando opes c e verbose possvel ver a seqncia de instrues da JVM, o tamanho dos quadros de cada mtodo, o contedo dos quadros, o pool de constantes, etc. A opo l imprime tabela de variveis locais. Se no for passadanenhumaopo,sermostradaainterfacedaclasse. O diagrama da figura 10 ilustra relacionamentos entre o cdigo Java e o cdigo de arquivos .class (bytecode). As instrues de bytecode e outras informaesforamobtidosatravsdaferramentajavap.

Figura10DiagramamostrandoorelacionamentoentrecdigoJavaelinguagembytecode(cdigode mquinaJava)representadoporinstruesdamquinavirtual.

A mquina virtual HotSpot guarda a rea de mtodos em uma regio do heap chamada de geraopermanente.

2005HelderdaRocha

12

ArgoNavisJ281

GernciadememriaemJava

2. Algoritmos de coleta de lixo


Emlinguagensqueusamalocaodinmicaealocaolinear(heapsepilhas), dadosarmazenadosnapilhasoautomaticamenteliberadossemprequeapilha esvazia para ser reutilizada, mas dados armazenados no heap precisam ser reciclados atravs de liberao. A liberao pode ser explcita (manual) em linguagens como C e C++ (usando recursos como freelists e comandos como delete,freeousimilares),ouimplcita(automtica),comoemJavaemaiorparte daslinguagensdinmicas5. Aliberaoautomticadememriadoheaprealizadaatravsdealgoritmos decoletadelixo.Hvriasestratgias,comvantagensedesvantagensdeacordo comataxaemqueobjetossocriadosedescartados.Acoletadelixoautomtica tm um considervel impacto na performance, porm a gerncia explcita de memriatambmtem,emuitomaiscomplicada. DeacordocomaespecificaodalinguagemJava,amquinavirtualprecisa incluir um algoritmo de coleta de lixo para reciclar memria dinmica do heap noutilizada.Oprincipaldesafiodacoletadelixodistinguir oquelixodo que no lixo. Na engenharia de software, podese classificar os coletores em duas categorias quanto deciso do que ou no lixo: exatose conservadores. Algoritmos exatos garantem a identificao precisa de todos os ponteiros e a coleta de todo o lixo. Algoritmos conservadores fazem suposies e podem deixar de coletar lixo que pode no ser lixo (permitindo um possvel memory leak).TodososcoletoresusadosnasmquinasvirtuaisJavasoexatos.Ocritrio paradefiniroquelixooquememrianoutilizadaodealcanabilidade. Lixo so os objetos inalcanveis. A especificao no informa qual algoritmo deveserusadoapenasquedeveexistirum. AmquinavirtualHotSpot,daSunamaisusadaemaplicaesdeservidor e desktops , usa vrios algoritmos e permite diversos nveis de ajuste. O comportamento desses algoritmos o principal gargalo na maior parte das aplicaesdevidalonga.Algoemtornode2%a20%dotempodeexecuode umaaplicaotpicagastocomcoletadelixo.Opesodocoletordelixomais evidente em aplicaes de vida longa, como servidores. Idealmente, deve manterse sempre abaixo de 5%, mas existem aplicaes onde pode chegar a 40%.Muitasvezesumasoluonopossvelseminvestimentosdehardware, mas dependendo da natureza da aplicao, uma grande parte da sua ineficinciapodevirdamelhorescolhaeconfiguraodosalgoritmosdecoleta de lixo usados. Conhecer os detalhes do funcionamento desses algoritmos importanteparasabercomomelhorajustlosparaobteramelhorperformance deumsistema. A liberao de memria pode influenciar a alocao e degradar a performance depois de vrias coletas. Isto um efeito colateral do algoritmo
5

Perl, Python, Rubi, Basic, LISP, Algol, Dylan, Prolog, PostScript, Scheme, Simula, Smalltalk, ML e Modula3(namaiorparteusacoletadelixo,massuportacontrolemanualemalgunsmdulos).

2005HelderdaRocha

13

ArgoNavisJ281

GernciadememriaemJava

usado.Comoobjetospodemsercriadoseremovidosaqualquermomentoede qualquerlugardoheap,aremoodeobjetosdeixaburacos.Comoocoletorde lixo remove muitos objetos de uma vez, ele pode causar fragmentao no heap tornando o sistema ficar mais lento com o passar dotempo. Para alocar novos objetos em um heap fragmentado, o algoritmo usado precisar procurar nas listas de espaos vazios (free lists) um espao que caiba o prximo objeto. A alocaosermaisdemoradaemaiscomplexaeousodoespaoserineficiente, pois os espaos no usados so desperdiados. Existem algoritmos que compactamoheapdepoisderealizaracoleta,movendoosobjetosparaoincio doespaoeatualizandoosponteiros.Algoritmosdessetipotornamaalocao maissimpleseeficiente,pormsomaiscomplexosepodemdemorarmais.

Algoritmos para coleta de lixo


Existem duas estratgias gerais para coleta de lixo: a contagemdereferncias, quedescobreolixoanalisandoosobjetosativos,eorastreamentodememria,que varreoheapinteiroprocuradeobjetosinalcanveis.Existemmuitasvariaes nas tcnicas e centenas de algoritmos diferentes que podem ser classificados nessasduascategorias.Osprincipaisalgoritmosso: Referencecountingalgorithm[Collins1960]:mantm,emcadaobjeto,uma contagemdasrefernciasquechegamnele.Objetosquetmcontagem zerosocoletados. Cyclecollectingalgorithm[Bobrow1980]:extensodoalgoritmode contagemderefernciaparacoletarciclos(refernciascirculares). Markandsweepalgorithm[McCarthy1960]:rastreiaobjetosdoheap,marca oquenolixoedepoisvarreolixo(liberamemria). Markandcompactalgorithm[Edwards]:extensodoalgoritmoMarkand sweepquemantmoheapdesfragmentadodepoisdecadacoleta. Copyingalgorithm[Cheney1970]:divideoheapemduaspartes.Cria objetosemumapartedoheapedeixaoutrapartevazia.Recolheoque nolixoecopiaparaarealimpa,depoisesvaziaareasuja. Ostrsltimossoalgoritmosderastreamento. Diversas estratgias usam ou baseiamse em um ou mais dos algoritmos citados para obter melhores resultados em um dado cenrio. Vale a pena destacar duas tendncias de classificao: quando organizao de memria e idadesdosobjetos,equandoaonveldeparalelismo. Algoritmos que organizam reas de memria diferentes para classificar objetos de acordo com a sua idade so chamados de algoritmos baseados em geraesouemidade.Asprincipaisestratgiasso:generationalgarbagecollection, onde objetos so transferidos para reas de memria diferentes conforme sobrevivem a vrias coletas de lixo, e ageoriented garbage collection, onde algoritmos diferentes so usados conforme a idade dos objetos. As duas so muitosemelhantes(ageorientedGCpodeserconsideradaumtipodegenerational GC),masorganizamamemriadiferentemente.

2005HelderdaRocha

14

ArgoNavisJ281

GernciadememriaemJava

Quantoaonveldeparalelismohoscoletoresseriais,queexecutamemsrie parando a aplicao para executar em um nico thread da CPU; incrementais (tambm chamados de onthefly), que rodam em threads de baixa prioridade concorrendo com a aplicao sem interrompla; e concorrentes, que executam emvriosthreadsemparalelo,masnonecessariamenteeliminamtotalmenteas pausas. A escolha de um coletor depende das caractersticas de uma aplicao. As principais metas de ajuste so eficincia e pausas. Eficincia (throughput) a relao entre o tempo em que uma aplicao passa fazendo sua funo til divididopelotempoquepassafazendocoletadelixo.Oidealquesejaamaior possvel. As pausas so os momentos em que a aplicao inteira (todos os threads)daaplicaoparamparaexecutarocoletordelixoeliberarmemria.O idealqueaspausassejammnimas,oumesmozeroemsistemasdetemporeal quenoadmitempausas. Freqentemente, essas metas podem ser alcanadas atravs da escolha de um coletor de lixo adequado, j que diferentes estratgias usam algoritmos diferentes,deformasdiferentes,ecausamimpactosdiferentesnosistema. possvel tambm configurar parmetros que modificam o espao usado, influenciando a forma como um mesmo coletor reage ao ambiente (a maior parte dos coletores reage ao espao disponvel.) Nas sees a seguir explicaremosofuncionamentodosprincipaisalgoritmosdecoletadelixo.

Contagem de referncias
o algoritmo mais simples. Cada objeto possui um campo extra que conta quantas referncias apontam para ele. O compilador precisa gerar cdigo para atualizaressecamposemprequeumarefernciaformodificada. Descriodoalgoritmo: 1. Objetocriadoemthreadativo:contagem=1 2. Objetoganhanovarefernciaparaele(atribuioouchamadademtodo compassagemdereferncia):contagem++. 3. Umadasrefernciasdoobjetoperdida(saiudoescopoondefoi definida,ganhounovovalorporatribuio,foiatribudaanullouobjeto queacontinhafoicoletado):contagem. 4. Secontagemcairazero,oobjetoconsideradolixoepodesercoletadoa qualquermomento. As figuras 11 e 12 ilustram o funcionamento do algoritmo de contagem de refernciasemvriasetapas.Cadasetaquechegaemumobjetocontadacomo uma referncia para ele (independente de onde tenha vindo). Observe que as referncias circulares impedem que contagem caia para zero quando deveria. Essa uma das principais desvantagens do algoritmo de contagem de referncias, e requer tratamento por via de outros algoritmos para que no ocorrammemoryleaks.

2005HelderdaRocha

15

ArgoNavisJ281

GernciadememriaemJava

O conjunto raiz so as referncias iniciais acessveis atravs de variveis locaisdemtodosemexecuo,constantes,variveisglobais,etc.

Figura11Cadaobjetopossuiumacontagemdequantassetaschegamnele(referncias).

Figura12Quandoumobjetoperdesuasreferncias,acontagemalterada,eobjetosquetmcontagem zeroserocoletados.Ociclonocoletadoporqueseusobjetosaindarecebemreferncias.

O algoritmo de contagem de referncias no precisa varrer o heap inteiro. Varre apenas espao ocupado. Pode executar em paralelo com a aplicao e assim considerado um algoritmo incremental. Impe um overhead alto j que precisa varrer as referncias recursivamente e incrementar um contador. O suporte a paralelismo tambm implica em custos adicionais para garantir a sincronizao. Mas sua principal desvantagem a incapacidade de recuperar ciclos (objetos que mantm referncias circulares entre si). Em implementaes decontagemdereferncias,comumusarumoutroalgoritmo(geralmentede rastreamento)comobackupparalimparosciclosnocoletados. Apesar de simples, a contagem de referncias tem sido pouco usada em coletores de lixo comerciais. As pesquisas tm ressurgido com o aumento do tamanhodosheaps,quetornaosalgoritmosatuaisbaseadosemrastreamento menos eficientes. Existem propostas eficientes para coletores incrementais (on

2005HelderdaRocha

16

ArgoNavisJ281

GernciadememriaemJava

thefly) [LevanoniPetrank 2001] que reduzem overhead, custo do paralelismo, eliminandotambmtotalmenteaspausas(oqueotornavivelparasistemasde temporeal). Existem tambm algoritmo eficientes de coleta de ciclos, cujo processoserdescritoaseguir.

Coleta de ciclos
Resolve o principal problema do algoritmo de contagem de referncias. Baseiaseemduasobservaes:1)cicloslixospodemsercriadosquandouma contagemcaiparavalordiferentedezero,e2)emcicloslixo,todaacontagem devidoaponteirosinternos. Objetosquetemcontagemdecrementadaparavaloresdiferentedezeroso candidatos (observao1) a seremlixo. O algoritmo realiza trs passos locais nos candidatos 1. Mark:marcaapenasobjetosquetmponteirosexternos(observao2) 2. Scan:varreocicloapartirdoobjetocandidatocomponteiroexternoe restauraamarcaodeobjetosqueforemalcanveis. 3. Collect:coletaosnscujacontagemforzero. Asfiguras13,14 e 15ilustram um algoritmo de coleta de ciclosdescrito em [PazPetrank 2003], compatvel com mquinas virtuais executando em ambientesmultiprocessados.Afigura13ilustraoestadodoheapdepoisdeuma coleta. Dois objetos so candidatos remoo: objetos cuja contagem foi decrementadaparavalordiferentedezero.Afigura14ilustraopassoseguinte, ondeoalgoritmonaveganasrefernciasapartirdocandidatoecontaapenasas referncias externas ao ciclo. Nesta etapa, todos os objetos que so lixo esto marcados,pormexistemobjetosquenosolixomarcadostambm.Nafigura 15 foi restaurada a contagem dos ns que puderam ser alcanados atravs das referncias externas. Os objetos que continuarem com contagem zero nesta etapaserocoletados.

Figura13Fasedeidentificaodosobjetoscandidatos,apsumacoletadecontagemdereferncias normal.Oscandidatossoosobjetoscujacontagemdiminuiumasnoazero.

2005HelderdaRocha

17

ArgoNavisJ281

GernciadememriaemJava

Figura14Fasedemarcao.Osponteirosinternosapartirdosobjetoscandidatosnosocontados.

Figura15Fasedevarredura:seumobjetodocicloforacessvelatravsderefernciaexterna,sua contagemrestabelecida.

Oalgoritmotrabalhaapenascomobjetosativosenoprecisapesquisartodo oheap.Istoumavantagemqueotornaumfortecandidatoparaheapsgrandes, jqueasalternativasusadasatualmente(algoritmosderastreamento)precisam pesquisar o heap inteiro. Alm disso, por ser um algoritmo incremental, pode trabalharemparaleloseminterromperaaplicaoprincipal. Por outro lado pode ser muito ineficiente se houver muitos ciclos, j que precisapassartrsvezesporcadaumdeles,oquetornaraaplicaomaislenta mesmo no havendo pausas. Tambm precisar garantir a atomicidade das etapasdecoletadeciclos,casovenhaaserusadoemsistemasparalelos. O algoritmo de coleta de ciclos no usado nas mquinas virtuais Java comerciais(ataverso5.0).Temsidousadocomsucessoemmquinasvirtuais experimentais (Jikes RVM) e fundamental em estratgias como coletores age orientedparalelos[Pazetal.2005]queassumemheapsgrandes.

2005HelderdaRocha

18

ArgoNavisJ281

GernciadememriaemJava

Algoritmos de rastreamento (tracing algorithms)


Marcamasrefernciasquesoalcanveis(navegandoapartirdoconjunto raiz), e remove todas as referncias que sobrarem. A figura 16 ilustra um caminho de referncias alcanveis marcadas como ativas. As que sobrarem seroremovidas.

Figura16Objetosativosmarcadosporumalgoritmoderastreamento.

Algoritmo Mark and Sweep


O algoritmo markandsweep (ou marksweep) o mais simples algoritmo de rastreamento. geralmente disparado quando a memria do heap atinge um nvelcrtico(ouacaba)eentotodososthreadsdaaplicaoparamparaexecut lo. Esse comportamento chamado de stoptheworld. Difere do modo incrementalpossibilitadopelacontagemdereferncias,quenoprecisaparara aplicao. O algoritmo marksweep foi originalmente projetado para a linguagem LISP peloseucriador[McCarthy1960].Temduasfases(ilustradasnafigura17) Mark:navegapelosobjetosalcanveisapartirdoconjuntoraizedeixa umamarcaneles. Sweep:varreoheapinteiropararemoverosobjetosquenoestiverem marcados(lixo),liberandoamemria. A principal vantagem do algoritmo marksweep est na sua simplicidade. Remove todo o lixo sem complicao. No importa se h referncias circulares ou no. Desta forma, pode ser mais rpido que a contagem de referncias se o heapnoforexcessivamentegrandeeseobjetosmorreremcomfreqncia.Em heaps grandes com objetos longevos a contagem de referncias com coleta de ciclostendeasermaisvantajosa. Por outro lado o algoritmo marksweep (e todos os algoritmos de rastreamento) precisa interromper todos os threads da aplicao principal para poderexecutar.Umdesafiodoscoletoresdelixomodernosgarantirqueessa pausa seja imperceptvel. Outro problema a fragmentao do heap, que pode aumentar rapidamente se houver coletas freqentes. Uma desfragmentao

2005HelderdaRocha

19

ArgoNavisJ281

GernciadememriaemJava

(a)

(b)

(c)

(d)

Figura17AlgoritmoMarkandSweepmostrandooheap(a)antesdamarcao;(b)apsamarcaodos objetosalcanveis;(c)apsaliberaodamemria;(d)duranteaalocaodeumnovoobjeto.

necessria(apsvriascoletas)caraerequerainterrupodetodososthreads da aplicao por um tempo maior que as pausas de coleta. Um heap muito fragmentado diminui a disponibilidade de memria e pode aumentar a freqncia em que as coletas ocorrem, com passar do tempo. Finalmente, em heaps grandes esse algoritmo tem baixa performance. Embora precise visitar apenasosobjetosalcanveisnafasedemarcao,depoisprecisavarreroheap inteiroparalocalizarobjetosnomarcadoseliberaramemria.

Algoritmo Mark and Compact


Um dos problemas do algoritmo marksweep solucionado pelo algoritmo markcompact.umalgoritmoderastreamentobaseadonoalgoritmomarksweep que acrescenta um algoritmo de compactao que elimina a fragmentao de memria. Assim, depois de cada coleta os objetos esto todos juntos e a memria livre contgua, tornando a alocao mais simples e dispensando a necessidade de um algoritmo de alocao baseado em free lists. Para alocar memriaparaumnovoobjeto,bastalocalizarofinaldoltimoobjetoalocadoe usaramemriaquefornecessria.

2005HelderdaRocha

20

ArgoNavisJ281

GernciadememriaemJava

Oalgoritmoconsistededuasfases.Aprimeiraidnticaaomarksweep,que marca os objetos alcanveis. A fase seguinte move os objetos alcanveis sobreviventesparafrenteatqueamemriaqueelesocupamsejacontgua.O funcionamentodoalgoritmomarkcompactestilustradonafigura18apartirda compactaodoheap.

(a) (b) Figura18AlgoritmoMarkandCompact:(a)estadodoheapapsumacoleta;(b)alocaodeumnovo objetonoheapnofragmentado.

Aprincipalvantagemdestealgoritmoemrelaoaoalgoritmomarksweep no causar fragmentao da memria. Isto torna a alocao rpida e sua performance no se degrada com o tempo devido ao aumento das coletas. A alocao rpida importante no apenas na criao de objetos novos, mas tambm durante a coleta. Estratgias de coleta de lixo que dividem o heap em reas chamadas de geraes realizam freqentes coletas em reas dedicadas a objetosjovensseguidasporalocaesemreasparaobjetossobreviventes.Um heapnofragmentadoessencialparaqueessascoletassejameficientes. O markcompact continua sendo um algoritmo stoptheworlde seu algoritmo de compactao introduz um overhead maior, j que requer vrias visitas aos objetos.Aspausas,portanto,tendemasermaioresqueaspausasemmarksweep. Tambm mais difcil implementar uma verso concorrente (existem verses experimentaismasnenhumafoiainda(ataverso5.0)utilizadanasmquinas virtuaisJavacomerciais).

Algoritmo de cpia
O algoritmo de cpia (Copying algorithm [Chenney 1970]) divide o heap em duas reas iguais chamadas de espao origem (fromspace) e espao destino (to space).Funcionadaseguintemaneira: 1. Objetossoalocadosnareafromspace. 2. Quandoocoletordelixoexecutado,elenavegapelacorrentede refernciasecopiaosobjetosalcanveisparaareatospace. 3. Quandoacpiacompletada,osespaostospaceefromspace trocamdepapel.

2005HelderdaRocha

21

ArgoNavisJ281

GernciadememriaemJava

Asfiguras19a22mostramofuncionamentodoalgoritmodecpia.

Figura19Oheaporigemencheedisparaacoletadelixo.

Figura20Objetosalcanveissocopiadosesuasrefernciassovarridaseatualizadas.

Figura21Osobjetosquerestaremnaorigemsoeliminados.Aorigemtornaseodestinoeodestino tornaseaorigem.Odestinopermanecevazioataprximacoleta.

2005HelderdaRocha

22

ArgoNavisJ281

GernciadememriaemJava

Figura22Todasasalocaessofeitasemreanofragmentada.

Este algoritmo possui vrias vantagens. mais simples, a cpia rpida (principalmente se a quantidade de objetos alcanveis for pequena, o que comum), e no precisa visitar o heap inteiro: apenas os objetos alcanveis. Tambmnofragmentaamemriadoheap. Por outro lado a aplicao ainda precisa parar (stoptheworld) enquanto o algoritmoestsendoexecutado(comoemqualqueralgoritmoderastreamento). possvelreduzirbastanteaspausasusandoversesconcorrentes(propostoem [Baker78])nasplataformascomvriosprocessadores. A principal desvantagem o consumo e desperdcio de memria. Esse algoritmo dobra a necessidade de memria do heap, e ainda mantm metade semuso6.Hdoisproblemasrelacionadosaisto.Oprimeiroapossvelfaltade memria se o heap necessrio for muito grande. O segundo a freqncia de coletasquepodeaumentaraoreduziroheapaumtamanhomenor(commetade dotamanhonormal)diminuindoaeficinciadacoletadelixo.

Tabela1Quadrocomparativoentreosalgoritmosdecoletadelixoelementares.

Isto depende da implementao. Vrias implementaes reservam espaos de tamanho desigualbaseadonadistribuiodeciclodevidadosobjetos.


6

2005HelderdaRocha

23

ArgoNavisJ281

GernciadememriaemJava

3. Estratgias de coleta de lixo


Coletores modernos combinam vrios algoritmos em estratgias mais complexas, aplicando algoritmos diferentes conforme as idades e localizao dos objetos, e utilizando tcnicas que possibilitem a coleta de lixo paralela (algoritmos incrementais e concorrentes). Nesta seo apresentaremos as principaisestratgiasusadas(epropostas)paracoletoresseriaiseparalelos: Generationalgarbagecollection(usadanaJVMHotSpot) Ageorientedgarbagecollection(usadaemimplementaesexperimentais) Ambas baseiamse na idadedosobjetos paratornar as coletas mais eficientes. Fundamentamseemtrsobservaesempricas: Seumobjetotemsidoalcanvelporumlongoperodo,provvelque continueassim; Emlinguagensfuncionais,amaiorpartedosobjetos(95%)morrepouco depoisdecriados(figura23); Refernciasdeobjetosvelhosparaobjetosnovossoincomuns. Concluso:podesetornarmaiseficienteocoletordelixoanalisandoseosobjetos jovenscommaisfreqnciaqueosobjetosmaisvelhos.

Figura23Objetosmorremjovens!Fundamentoparaotratamentodiferenciadodeobjetoscombasena suaidade.Coletasmenoresliberammemriadeobjetosjovens.Coletasmaioresliberammemriadoheap inteiro.Fonte[Sun05].

Generational garbage collection


A estratgia de coleta de lixo com base em geraes classifica objetos em diferentes grupos de acordo com a sua idade. Os grupos so chamados de geraes.SeconsiderarmosngeraesG0,G1,...,Gn,ageraoG0seragerao quecontmosobjetosmaisjovens(recmcriados.)Ageraoseguinteconter objetosquesobreviveramaumacoletadelixoeassimpordiante7.Acoletade lixo realizada separadamente em cada gerao, e ser mais freqente nas geraesmaisjovensquenasgeraesmaisvelhas,ouseja,Gnservarridamais freqentemente que Gn+1. Pressupese que a maior parte dos objetos jovens
7

Aformadeimplementaodoalgoritmopodevariar.

2005HelderdaRocha

24

ArgoNavisJ281

GernciadememriaemJava

(90%) j seja lixo antes da prxima coleta. Os objetos sobreviventes so promovidosparaageraoseguinte. As geraes mais velhas devem ser maiores que as geraes mais novas. Tipicamente so exponencialmente maiores. Implementaes tpicas dessa estratgia usam apenas duas geraes chamadas de geraojovem (G0) e gerao estvelouvelha(G1). As geraes representam reas do heap. A gerao jovem a rea menor, ondeinicialmentealocadaamemriaparanovosobjetos.Ageraoantiga,ou estvel,umareamaiorondeoespaoalocadonoparanovosobjetosmas para acomodar objetos que sobrevivem a uma ou mais coletas de lixo na rea menor. Na transferncia, todos os ponteiros entre objetos precisam ser atualizados. Quando um objeto criado, suas referncias geralmente apontaro para objetos mais antigos. Se houver ponteiros entre geraes, provavelmente sero dageraonovaparaageraovelha.Maspodeacontecerdeumobjetoantigo receber referncia para um objeto novo algum tempo depois de criado. Neste casoosistemaprecisainterceptarmodificaesemobjetosantigosemanteruma lista de referncias. Isto deve ocorrer raramente (se ocorrer com freqncia, as coletasmenoresserodemoradas). NaHotSpotJVM,usadaumatabeladereferncias(cardtable)paracontrolar ponteirosentregeraes(intergenerationalpointers).Ageraoantigadividida em blocosde 512kb (chamadas de cards).Alteraesso interceptadas e blocos onde elas ocorrem so marcados. As coletas menores (coletas realizadas na geraojovem)verificamapenasosblocosmarcados. Acoletadelixobaseadaemgeraesusamaisdeumalgoritmopararealizar as suas coletas de lixo, uma vez que cada gerao possui tamanhos e comportamentosdiferentes. Na gerao jovem, aproximadamente 90% dos objetos j esto mortos e a rea total do heap usado pequena (geralmente bem menor que a gerao estvel). Neste caso, o algoritmo de cpia a melhor opo pois seu custo proporcionalaosobjetosativos.Comoamaiorpartedosobjetosestmorto,h poucosobjetosacopiar. Nageraoestvelpodehavermuitosobjetosativosereagrande.Nessa situao o ideal seria usar um algoritmo como contagem de referncia com coleta de ciclos j que eficiente com heaps maiores e pode ser incremental. O HotSpot prefere usar uma implementao de marksweep concorrente ou mark compact serial. Ambos precisam varrer o heap inteiro e no so totalmente incrementais (so stoptheworld), embora a verso concorrente consiga reduzir significativamenteaduraodaspausasemsistemascommuitosprocessadores. Nasimplementaesmaiscomunsdecoletadelixobaseadaemgeraesque usamduasgeraes(G0:jovemeG1:estvel),usaseumalgoritmodecpiana gerao jovem. Um algoritmo de coleta de lixo disparado sempre que uma

2005HelderdaRocha

25

ArgoNavisJ281

GernciadememriaemJava

gerao enche. As coletas podem ser parciais (apenas na gerao jovem) ou completas(noheapinteiro.) A coletaparcial,oumenor ocorre quando a gerao jovem enche. Ela sempre encheprimeiro,jqueacumulaobjetosmaisrapidamente.Quandoistoacontece, eladisparaumacoletamenor,querpida(proporcionalaonmerodeobjetos ativos).Ossobreviventesdacoletaserocopiadosparaageraoantiga. A coletacompleta,oumaior ocorre quando a gerao antiga enche. Ela cresce ao receber os sobreviventes da gerao jovem. Vrios objetos iro morrer na gerao antiga. Depois de vrias coletas menores, a gerao antiga enche, e quandoistoacontecerhaverumacoletamaior(maislenta)noheapinteiro,que ir no s remover objetos velhos como eventuais objetos jovens que forem encontrados. Asilustraesdafigura24mostramofuncionamento.

Figura 24 Ilustrao de duas coletas menores (parciais) usando algoritmo de cpia. Neste modelo 8, o to_space sempre a gerao estvel. As coletas ocorreram apenas na gerao jovem. Quando a gerao estvelenchar,haverumacoletanoheapinteiro.

A estratgia de coleta de lixo baseada em geraes consegue obter pausas menores,jquecoletasrpidasefreqentesdistribuemaspausasdetalmaneira que podem tornarse imperceptveis. Tambm consegue aumentar a eficincia (throughput), concentrando a coleta nas reas de memria onde o lixo se encontra,gastandomenostempo. Apequenageraojovempodecausaruminciomaislentodevidoamuitas coletascurtas,oquecausabaixaeficincia.Essascoletasprovocaropausasque podemacontecernoinciodaaplicaoseageraojovemenchervriasvezes quandoaaplicaoestiversendoiniciada.Esseumcomportamentopossvele talvezcomumemvriasaplicaes.Aspausascurtaspodemnoserpercebidas,

O modelo usado noHotSpot difereum pouco destemodelo mais simples.Veja aseo2para detalhessobreaimplementaonoHotSpot.
8

2005HelderdaRocha

26

ArgoNavisJ281

GernciadememriaemJava

massevriasocorrerememumacurtaseqncia,podeparecerquehouveuma longapausa. Por usar uma rea maior, a coleta na gerao antiga ainda lenta, principalmente com algoritmos de rastreamento (usados no HotSpot). Os algoritmos usados atualmente nas mquinas virtuais comerciais ainda no conseguemeliminartotalmenteaspausas. Na JVM HotSpot, a gerao antiga permite a escolha entre diversos algoritmos: marksweep, markcompact e um algoritmo incremental (train). Existem pesquisas usando contagem de referncias com coleta de ciclos para coletar gerao antiga eficientemente (veja, por exemplo, [AzatchiPetrank 03], no qual implementaes foram testadas na JVM experimental Jikes RVM com bonsresultados.)

Age-oriented garbage collection


Aestratgiadecoletadelixobaseadonaidadedosobjetostambmdivideobjetos emgeraes,masestaspodemocuparespaosdetamanhovariveldoheap.As geraesestoassociadasnoaumlugarespecficonoheap,masacadaobjeto. As coletas sempre varrem o heap inteiro, o que pode provocar pausas muito longas. A soluo proposta busca diminuir as pausas com concorrncia (seria ineficienteemambientesmonoprocessados). Aindaumasoluoexperimental.Asimplementaesrecomendadasusam um algoritmo de rastreamento (cpia) na gerao jovem (da mesma forma que implementaes tpicas do generational garbage collection) e um algoritmo de contagemderefernciascomcoletadeciclosnageraoantiga. Inicialmente gerao jovem ocupa todo o espao (figura 25), o que garante altaeficincia(demoraaocorrnciadaprimeiracoleta).Oespaoreservadopara ageraoantigacrescemedidaemqueocorremcoletasnageraojovem,mas ela sempre menor que a gerao jovem. Uma pequena gerao antiga com maisobjetosativosquemortosepoucaatividadepermiteeficinciamximado algoritmodecoletadeciclos.

Figura25Geraesdeobjetosnovoseantigosemduasestratgiasbaseadasnaidadedosobjetos.Fonte: [PazPetrankBlackburn05](slides).

2005HelderdaRocha

27

ArgoNavisJ281

GernciadememriaemJava

Atabela2comparaaestratgiadecoletadelixoageorientedcomaestratgia generational.
Generational Age-oriented

Gerao jovem menor que gerao velha. Faz coletas freqentes apenas na gerao jovem. Aps vrias coletas da gerao jovem, faz coleta do heap inteiro, com algoritmos diferentes para cada gerao.

Gerao jovem maior que gerao velha. Sempre coleta o heap inteiro, usando algoritmos diferentes para cada gerao.

Tabela2Comparaoentreestratgiasdecoletadelixobaseadasemidadedosobjetos.

A estratgia ageoriented procura manter a maior gerao jovem possvel, o que torna as coletas de lixo mais raras e pausas menos freqentes. Tambm permite um incio mais rpido da aplicao. A eficincia buscado da mesma formaquenaestratgiagenerational:tratandocadageraodiferentemente. A principal desvantagem dessa estratgia no funcionar bem para pequenos sistemas. ideal para sistemas com muita memria e muitos processadoresparalelos.Foiconcebidatendoessetipodeambienteemvista.As pausasserolongasnageraojovemsenoforimplementadoemumcoletor paralelo, executando um algoritmo de cpia concorrente. E como a gerao antiga coletada freqentemente, importante que se use um algoritmo incrementalcomocontagemdereferncias.Acoletaserineficienteseforusado algoritmoderastreamentoeaspausasintroduzidaspoderoserexcessivas. Atualmente esse algoritmo usado apenas experimentalmente e no suportado por nenhuma mquina virtual comercial como a HotSpot, mas algumas de suas idias podero influenciar algoritmos de coleta de lixo nas mquinas virtuais do futuro. O artigo [PazPetrankBlackburn 05] documenta benchmarksrealizadoscomimplementaesdessealgoritmonamquinavirtual experimental JikesRVM que obtiveram uma performance mdia melhor que a implementaodogenerationalGCqueatualmenteusadanoHotSpot.

2005HelderdaRocha

28

ArgoNavisJ281

GernciadememriaemJava

4. Coleta de lixo em paralelo


Osmaioresproblemasdacoletadelixo:aspausaseareduodaeficincia da aplicao podem ser minimizados usando coleta de lixo em paralelo, principalmenteemsistemascommaisdeumprocessador.Coletoresparalelos geralmentecombinamosalgoritmosbsicosjvistoseimplementamextenses paratornlosseguroseeficientesnessesambientes. Noqueserefereaoparalelismo,asprincipaisestratgiasso: Coletaserial:ocoletorocorreemsriecomaaplicao,parandoomundo (stoptheworld)quandoprecisarliberarmemria.svezescoletasseriais so realizadas em estratgias paralelas para realizar tarefas mais raras, buscandomaioreficinciaemdetrimentodepossveispausaslongas. Coleta incremental (onthefly): o coletor executa em paralelo realizando coletas pequenas (no necessariamente completas) sempre que possvel, usandovriosthreadsbuscandomenos(ouzero)pausas. Coleta concorrente: o coletor realiza suas principais tarefas em um processadorouthreadexclusivo(podeparartodososthreadsparamarcar, senecessrio)buscandomaioreficincia.

Coletores incrementais
Os algoritmos seriais de rastreamento precisam parar todos os threads para realizarcoletadememria.Istoinaceitvelparaaplicaesdetemporeal.Uma soluosoosalgoritmosdecoletaincremental(onthefly.) Umalgoritmoincrementalpermitequeaaplicaoexecuteenquantoacoleta delixoacontece.Umadassoluesoalgoritmodemarcaotricolor(tricolour markingTCM).TCMumalgoritmoderastreamentoqueatribuiumentretrs estados (cores) a um n do grafo de objetos. o principal algoritmo de rastreamento incremental (considerando a engenharia de software como um todo, e no apenas Java) e a base para outras implementaes populares. Classificaosnsemdiferentestiposmarcandooscomascores:branco,cinzae preto.Executaosseguintespassos: 1. Inicialmente todos os ns so brancos (inalcanveis) e o conjunto de refernciasraizmarcadacinza. 2. Quando o coletor encontra um caminho entre um n cinza e um n branco,pintaonbrancodecinza.Depoisprosseguerecursivamenteat encontrartodososobjetosalcanveisapartirdele,pintandocadaobjeto encontradodecinza. 3. Quandotodososcaminhosdeumncinzalevamanscinzaoupretos,o npintadodepreto. 4. Quando no houver mais ns cinzas, todos os ns alcanveis foram encontrados.Osnsbrancosrestantessoreciclados. Oprocessoestilustradonasfiguras26a30.

2005HelderdaRocha

29

ArgoNavisJ281

GernciadememriaemJava

Figura26Inicialmentetodasasrefernciassobrancas.Asrefernciasraizsomarcadascinza.

Figura27Apartirdasrefernciasraiz,asrefernciasalcanadassomarcadascinza.

Figura28Objetosquenotemrefernciasbrancassomarcadoscomopretos.

2005HelderdaRocha

30

ArgoNavisJ281

GernciadememriaemJava

Figura29Objetosalcanveissomarcadoscomocinzas.

Figura30Memrialiberada.

Umobjetopretonuncapoderterrefernciasparaobjetosbrancos.Quando aplicao gravar uma referncia entre um n preto e um branco, o coletor precisarpintarouonpaiouonfilhodecinza.Quandoaaplicaoquiserler um n branco, ele tem que ser pintado de cinza. Para realizar isto, o sistema precisa: 1. Rastreargravaesemnspretos(atravsdeumabarreiradegravao writebarrier)e 2. Rastrearleiturasemnsbrancos(atravsdeumabarreiradeleituraread barrier). A principal vantagem do algoritmo TCM a possibilidade de uso incrementaleeliminaodepausasnacoletadelixo,permitindooseuusoem aplicaesdetemporeal.Tem,pelasmesmasrazes,umamelhorperformance
2005HelderdaRocha 31

ArgoNavisJ281

GernciadememriaemJava

aparente. Por outro lado complexa a sincronizao complexa entre a aplicao e o coletor de lixo. Barreiras podem dificultar a implementao em diferentessistemasediminuiraeficincia.

Train algorithm
As mquinas HotSpot no usam TCM mas um outro popular algoritmo incrementalchamadodealgoritmodotrem(trainalgorithm).Estealgoritmoaplica alguns dos princpios das estratgias de classificao dos objetos por idade. Divideamemriaemblocosdetamanhofixo(noHotSpotsoblocosde512kB) apelidadosdevages.Coleesdetamanhoarbitrriodevagesinterligadosso chamadosdetrens.Trensevagessoordenadosporidade;osmaisantigosso coletadosenquantonovostrensevagesseformam.Entreaformaoecoleta, atualizaserefernciasentreobjetos. Este algoritmo muito ineficiente com objetos populares (objetos que tm muitas referncias) que podem ocorrer com freqncia nas geraes estveis. Verses eficientes deste algoritmo lidam com esse problema mas podem ter pausas.Aspausassopequenasmasnosoprevisveis.) um dosalgoritmos usados no HotSpot e ser explorado em mais detalhes naprximaseo.

Snapshots e Sliding Views


Coletores paralelos precisam trabalhar com heapsquemudamduranteacoletaeaindaassim garantiracoletadetodoolixo,masemsistemas paralelos enquanto um thread marca os objetos outro thread pode estar liberando referncias (gerandolixo).Pararealizarumacoletacompleta precisotrabalharcommodelosestticosdoheap (snapshots ou sliding views) e coletar de forma incremental. Snapshots e sliding views so a mesma coisa (devem representar os mesmos dados). A Figura 31 Coleta concorrente vs. diferena est na forma como so obtidos e coletaincremental usados. Snapshots so as vises estticas do heap usadas por coletores de lixo concorrentes,masnonecessariamenteincrementaissempausas(vejafigura31). Umcoletordelixoconcorrenteusavriosthreadsparaexecutarosalgoritmosde coleta,maspodeaindaserdotipostoptheworldesincronizarasinterrupesde todososthreadsdaaplicaopararealizaracoletamaisrpidaeeficientemente. Mesmoquerealizepartedacoletaincrementalmente,paraobterummodelodo heap completo: o snapshot, o coletor de lixo precisa parar em um determinado momentotodososthreads. Slidingviewssovisesestticasdoheapusadasporcoletoresincrementais,ou onthefly. Esses coletores param um thread de cada vez, em tempos

2005HelderdaRocha

32

ArgoNavisJ281

GernciadememriaemJava

desencontradosparaobtervisescompletasdoheap.Destamaneiraconseguem evitar pausa na aplicao, porm podem afetar a eficincia da aplicao, uma vezquevriosslidingviewsterodadosrepetidoseotempodeprocessamento daaplicaoserdisputadocomocoletordelixo. Apesar das mquinas virtuais HotSpot atualmente no usarem algoritmos incrementais completamente sem pausas (possuem alternativas de pausas mnimas), provvel que os utilizem no futuro. uma rea de pesquisa emergente fundamental para sistemas de tempo real. Essa necessidade tem trazidodevoltaapossibilidadedeusodealgoritmosdecontagemdereferncia (com coleta de ciclos ou com backup de rastreamento), pois eles so eficientes comheapsgrandesesistemasparalelos.

Coletores concorrentes
OsalgoritmosdecpiaconcorrenteusadosnoHotSpotsotodosalgoritmos derastreamentocompausasenototalmenteincrementais.Existemalgoritmos decpiaincrementais(inicialmentepropostosem[Baker78]).Aimplementao simples: ponteiros so lidos apenas em to_space; se ponteiro estiver em from_space na leitura, primeiro copia objeto depois obtm ponteiro. Um algoritmo similar usado pela HotSpot JVM para coletar paralelamente a geraojovem.Veja[Floodetal2001]. UmalgoritmomarksweepconcorrenteusadopeloHotSpotJVMparacoletar paralelamenteageraoantiga[Printezis00].Nocompletamenteincremental, porm reduz pausas. H pausa pequena para obter snapshot (pra todos os threads ao mesmo tempo). Por no compactar, causa fragmentao. Existe uma verso com compactao em desenvolvimento [Flood 01] mas ela no usada emnenhumamquinavirtualatual(atJava5.0).

Concluses
Existemmuitasestratgiasdecoletadelixo.Hmuito,muitomaisdoquefoi exposto aqui. Embora o programador Java no tenha a opo de escolher qual usar, as mquinas virtuais podem permitir essa escolha e configurao pelo administradordosistemaouusurio.Muitopodemudarnasprximasverses das mquinas virtuais existentes atualmente: h muitas estratgias experimentais que podero ser usadas em verses futuras, em diferentes plataformas; h estratgias antigas caindo em desuso. Conhecer o funcionamento dos principais algoritmos ajudar a configurar e ajustar a performancedamquinavirtualJavaemdiferentestiposdeaplicaes.

2005HelderdaRocha

33

ArgoNavisJ281

GernciadememriaemJava

Parte II - Monitorao e configurao da mquina virtual HotSpot


A mquina virtual HotSpot a mquina virtual da Sun para a plataforma Java. Foi concebida com o objetivo de obter a melhor performance para aplicaesJavaexecutandotantoemambientesservidorescomoemambientes cliente.umamquinavirtual,ouseja,emulaumprocessadorcominterfacede execuo e programao uniforme, atravs de diferentes plataformas de hardware. Oferece um modelo de consistncia de memria prprio, altamente flexvel e facilmente adaptvel a ambientes mono e multiprocessados, um otimizador adaptativo para compilao de suas instrues de mquina e um sistemadegerenciamentoautomticodememria. Apesar da mquina virtual HotSpot ser previamente configurada para as situaes mais comuns, ela permite a configurao de vrios aspectos relacionadosgernciadememria.Entreeles: Escolhaentredoistiposdemquinavirtual,previamenteconfiguradase otimizadas para ambientes distintos: 1) ambientes servidores e grandes aplicaes de longa durao, ou 2) aplicaes cliente de curta durao geralmenteexecutandoemdesktops; Escolha de diferentes algoritmos e estratgias de coleta de lixo, permitindo a escolha e combinao de diferentes algoritmos em diferentesregiesdoheap; Configurao de diversos parmetros dos algoritmos de coleta de lixo comoredimensionamentodegeraesepolticasdeativao; Parmetrosdeajusteabsoluto,relativoouautomticodotamanhototale geraesdistribudasnoespaodoheap; Ajustedetamanhodapilha(paratodososthreads); Configurao automtica (ergonomics) baseada em metas de eficincia e pausasmximas; Polticadetratamentoderefernciasfracas(softreferences9); Gerao de relatrios e logs contendo informaes e estatsticas que podemserusadasparaauxiliaraconfigurao. Esta seo explora esses recursos, mostra como usar as opes da mquina HotSpoteapontaestratgiasdeajustevisandomelhorperformancenaexecuo deaplicaesJava.

Mecanismoquepodeserusadopeloprogramadorparainfluenciaracoletadelixo.

2005HelderdaRocha

34

ArgoNavisJ281

GernciadememriaemJava

5. Arquitetura da HotSpot JVM


A mquina virtual configurada para as situaes mais comuns da plataformausada.Hduasopesbsicasdemquinavirtualaescolher: JavaHotSpotClientVM:minimizatempodeinciodaaplicaoememria utilizada.Parainiciaramquinavirtualcomestaopo,use:
java client [outras opes] nome.da.Classe

JavaHotSpotServerVM(opcional): maximiza velocidade de execuo da aplicao.Parainiciaramquinavirtualcomestaopo,use


java server [outras opes] nome.da.Classe

As configuraes so otimizadas para ambientes especficos. A Server VM noestdisponvelemtodasasinstalaesdoJavaHotSpot.Ambientesdesktop com um processador e menos de 2 GB de RAM no suportam ou sero ineficientesseusaremaServerVM. Amquinavirtualaserusadacomodefaultselecionadaautomaticamente,de acordocomaplataformausadaduranteainstalao,quedecidequemquinas grandes multiprocessadas usam ServerVM e demais usam ClientVM (a menos queousuriomudeatravsdasopes.).Aescolhaduranteaexecuofeita tambmautomaticamente,casonenhumparmetrosejapassadoparaselecionar amquinavirtual.Normalmenteaconfiguraoescolhidaautomaticamentea melhoropo. TodasasmquinasvirtuaisHotSpotpossuemumcompiladoradaptativode bytecode. Aplicaes so iniciadas usando o interpretador, mas, ao longo do processo o cdigo analisado para localizar gargalos de performance. Trechos ineficientessocompiladoseoutrasotimizaes(ex:inlining)sorealizadas. Todas as mquinas virtuais HotSpot tambm realizam alocao rpida de memria, liberao de memria automtica usando algoritmos eficientes de coletadelixoadaptadosaoambienteusado,esincronizaodethreadsescalvel. Hvriasdiferenasentreasduasmquinasvirtuais.Ostamanhosdefaultdo heapedasgeraespermanentesdiferemnasduasopes.Ocompiladorusado no Server VM faz otimizaes mais agressivas, fazendo inlining inclusive de cdigo que pode ter referncias alteradas dinamicamente. Caso uma alterao ocorra, o compilador desfaz a otimizao. Como as alteraes so raras, possvelobterumaperformancemaior. Opes de linha de comando A mquina virtual pode ser configurada e ajustada por administradores atravs de opes de linha de comando. As opes apresentadas neste tutorial valem para as distribuies HotSpot da Sun. Como no so padronizadas, podemserdiferentesounoexistiremoutrasimplementaes. Existem diversas opes X. Elas so documentadas na linha de comando atravsdocomandodeajuda:
java X

2005HelderdaRocha

35

ArgoNavisJ281

GernciadememriaemJava

ExistemtambmvriasopesXX.Elasnosodocumentadasnalinhade comandoepodemnoestardisponveis(verifiquenasuainstalao.)Asintaxe dasopesXXdiferedasopesX:


java -XX:+Opo1 -XX:Opo2=5 ... [+opes] pacote.Classe

Nem as opes X nem as opes XX so padronizadas. Elas no fazem partedaespecificaodamquinavirtualepodemmudaremversesfuturas. Tambm diferem entre diferentes implementaes do HotSpot e podem ter sintaxe e resultados diferentes em outras mquinas virtuais, como as da IBM. Elasestodocumentadasemhttp://java.sun.com/docs/hotspot/VMOptions.html. HdoistiposdeopesXX:booleanaseinteiras.Asbooleanaspossuemuma chave para ligar e desligar usando os smbolos + e . As inteiras recebem um parmetro. Opobooleana -XX:<+/-><nome> Opointeira -XX:<nome>=<valor> Nasopesbooleanas,o+ligaeo-desligaumaopo.Porexemplo: -XX:+Opcao(ligaumaopoqueestavadesligadapordefault) -XX:-Opcao(desligaumaopoqueestavaligadapordefault) Asopesinteirasrecebemovalordiretamenteatravsde=:
-XX:Valor=8

Breve histria da coleta de lixo em Java


Ataverso1.1daplataformaJava,asmquinasvirtuaisdaSunusavamum nico coletor marksweep para coletar todo o lixo. Esse coletor no s causava fragmentao de memria, como significava um alto custo de alocao e liberao (o heap inteiro precisava ser varrido em cada coleta). O resultado era pausas longas quando ocorriam as coletas e baixa eficincia da aplicao que perdiaCPUparaocoletordelixo. Com o HotSpot, a partir da verso 1.2, adotouse o generationalcollector que emprega na gerao jovem um algoritmo de cpia e na gerao antiga um algoritmomarkcompact.Amboseliminamafragmentaodememria,tornando as alocaes mais eficientes. O resultado foi uma melhoria considervel na execuodeaplicaesJava,tornandoaplataformaJavaextremamenteeficiente. O HotSpot tambm inovou ao fazer a compilao seletiva do cdigo Java, diminuindootempodeinciodasaplicaes. Novas implementaes e opes foram acrescentadas a cada lanamento novodalinguagem.Entreasverses1.3 e1.5surgiramdiversassoluesmais eficientes de coletores seriais, paralelos de alta eficincia, concorrentes e incrementais. Todos foram adaptados ao modelo de separao de objetos em geraes.Comtantasopes,aconfiguraoeescolhadocoletordelixotornou seumatarefardua.Finalmente,naverso1.5foramintroduzidosmecanismos deautoajuste,escolhaeotimizaobaseadoemanliseergonmica. Nas sees seguintes exploraremos a arquitetura dos coletores usados no HotSpot,comeandocomocoletormaissimples:oserial.

2005HelderdaRocha

36

ArgoNavisJ281

GernciadememriaemJava

O coletor de lixo serial do HotSpot


Em uma HotSpotClientVM o coletor serial o coletor default. No preciso configurarnadaparauslo.Eleotimizadoparaamaiorpartedasaplicaes, portanto,raramentesernecessrioalterarsuasconfiguraes. Utilizaumheapdivididoemgeraes(estratgiagenerationalgarbagecollection) implementado com uma gerao jovem e uma gerao estvel. A gerao jovem ainda dividida em trs reas, para uma implementao mais eficiente do algoritmodecpia. Possui uma rea do heap chamada de gerao permanente, que apesar do nome, no faz parte das geraes usadas pela estratgia generational garbage collectionusadanoHotSpot.umareadememriaalocadapartedoheaptotal usada para armazenar dados estticos como mtodos e classes. raramente coletada(geralmentenocoletada). Os algoritmos de coleta de lixo usados na implementao do generational garbagecollectiondoHotSpotso: Geraojovem: usa algoritmo de cpia com duas origens e dois destinos (um destino temporrio e um destino permanente, que a gerao estvel).Ageraojovemmenorqueageraoestvelerealizacoletas pequenasefreqenteschamadasdecoletasmenores(minorcollections). Geroestvel(ouvelha):usaalgoritmomarkcompact.umareamenor que recebe os sobreviventes da gerao jovem. As coletas quando ocorremsocompletaseabrangemtodooheap.Sochamadasdecoletas maiores(majorcollections). Gerao permanente: usa um algoritmo marksweep. A coleta rara e disparadaquandoessareaenche. Afigura32ilustraaorganizaodoheapnoHotSpot.AsopesXpermitem alteraraorganizaodefaultnosservidoresqueassuportarem.

Figura32HeapdivididoemgeraesgerenciadopelamquinavirtualHotSpot.

2005HelderdaRocha

37

ArgoNavisJ281

GernciadememriaemJava

Gerao jovem
Ageraojovemdivididaemtrspartes.Umapartemaior,sempreusada paraalocaodenovosobjetos,eduaspartesmenoresquerevezamospapisde origemedestinodeumalgoritmodecpia. A parte maior chamada de den. onde novos objetos so criados. No algoritmo de cpia, o den sempre origem e nunca muda de papel. Sobreviventes de uma coleta esvaziam o den e so copiados para as reas menores, chamadas de espaos sobreviventes. As reas da gerao jovem esto mostradasnafigura33.

Figura33AnatomiadageraojovemnamquinavirtualHotSpot.

Ascoletasmenores,ouparciais,sofreqenteserpidas.Acontecemsempre queodenenche.Executamumalgoritmodecpiaquetrabalhacomduasreas de origem e duas reas de destino. As reas sobreviventes alternam funo de origem e destino. Uma das duas est sempre vazia, como no coletor de cpia elementar.Areadensempreorigem.Objetossocriadosealocadosnoden, masdeixamodennaprimeiracoleta.Ageraoestvelsempredestino. Quando o coletor de lixo executa uma coleta menor, todos os objetos alcanveisqueexistiremnodenesobreviventeorigemsocopiadosparaarea sobreviventedestinoougeraoestvel.Seumobjetonocoubernosobrevivente, sercopiadodiretamenteparageraoestvel.Ocoletordelixopodepromover umobjetoquejfoicopiadovriasvezesentreasregiessobreviventesetorn loestvel. Nofinaldacoleta,odenereasobreviventeorigemestovazios.Aorigem mudadefunoepassaaserdestino.Coletasseguintescopiaroobjetosentre osdoissobreviventesouparaageraoestvel,quandotiveremidadesuficiente. Umobjetonuncamaisvoltaaoden.Oumorrenodenousobrevivecoletae transferidoparaumespaosobrevivente.Objetosqueforampromovidosparaa gerao estvel nunca mais voltam gerao jovem. A figura 34 ilustra a organizaodoheapantesedepoisdeduascoletas.

2005HelderdaRocha

38

ArgoNavisJ281

GernciadememriaemJava

Figura34Quandoodenenche,coletordelixocopiaobjetosalcanveisdoden(E)parasobrevivente To(St)sempreesvaziaoden;dosobreviventeFrom(Sf)paraStsempreesvaziaoSf;deSfparaa geraoestvel(T)(dependentedealgoritmo);dodenouSfparaT(senocabeemSt).

Quandoosobjetossocopiadosentregeraes,suasrefernciasprecisamser atualizadasparaconterosnovosendereos.Afigura35ilustraasalteraesnos endereos dos objetos aps duas coletas de lixo, cpia de objetos entre sobreviventes e promoo de um objeto para a gerao estvel. A mudana completamentetransparenteaoprogramador.ComoJavanorealizaaritmtica deponteiros,noexisteriscoalgumdasmudanasdeendereocausaremalgum defeitoemumprograma.

Figura35Adanadasreferncias:osendereosdasrefernciasmudamvriasvezesentreascoletas,mas istototalmentetransparenteaoprogramador.

Gerao estvel
A gerao estvel (ou velha) consiste principalmente de objetos que sobreviveram a vrias coletas menores, sendo copiados vrias vezes de um espaosobreviventeparaooutro.Oalgoritmodecoletadelixodecidequando
2005HelderdaRocha 39

ArgoNavisJ281

GernciadememriaemJava

promover um objeto. Basicamente, depende de quantas vezes o objeto foi copiado.Ovalorpodevariarmastemumteto.Sesobreviveaumcertonmero de coletas, um objeto necessariamente promovido, mas pode ser promovido antes. Objetos jovens que recebem referncias de objetos estveis podem ser emancipados para evitar ponteiros entre geraes, objetos que no cabem nos sobreviventes podem ser promovidos na primeira cpia e um objeto muito grandequenocabenodenpodesercriadodiretamentenageraoestvel. A gerao estvel pode estar sujeita fragmentao. Isto depende do algoritmo de coleta de lixo usado. No coletor serial no ocorre fragmentao devido ao uso do algoritmo markcompact, mas coletores paralelos podem apresentaresseproblema. No coletor serial, uma coleta maior ou completa acontece quando a regio estvel enche. Coletas menores vo gradualmente enchendo a regio estvel. Quandoageraoestvelestcheia,executadaumacoletaenvolvendotodos osobjetosdetodasasgeraes.Umacoletamaiorsempredemorabemmaisque umacoletamenor,pormmenosfreqenteepodenuncaacontecer. Acoletamaiorpodeacontecerantesseoalgoritmodocoletorescolhidofor incrementalouseumacoletamenornoforpossveldevidofaltadeespao. Istopodeacontecer,porexemplo,seossobreviventesestiveremcheiosehouver maisobjetosativosnodenquecaberiamnaregioestvel.

Gerao permanente
A gerao permanente consiste de memria alocada por processos que no estorelacionadoscriaodeobjetoscomo: Cargadeclasses(ClassLoader), reademtodos(readecdigocompilado), Classesgeradasdinamicamente(JSPereflexo), Objetosnativos(JNI). As coletas de lixo na gerao permanente so muito raras. Quando acontecem usam a algoritmo marksweep (com compactao quando cheio). PodesedesligaracoletadelixonestageraousandoaopoXnoclassgc. comumhaverduplicaodeclassesnageraopermanentequandoseusa mltiplas mquinas virtuais em uma mesma mquina rodando aplicaes de longadurao10. Ageraopermanentenofazpartedoheaptotalcujotamanhocontrolado pelas opes Xmx e Xms da mquina virtual. Para dimensionla preciso usaropesprpriascomoXX:MaxPermSizeeXX:PermSize(opesusadasno HotSpot).
EmsistemasMacOS,quepossuemvriasaplicaesdedesktopimplementadasemJava,isto motivouacriaodeumageraoadicionalcompartilhadapelasmquinasvirtuais.Chamase geraoimortal.naverdadeumapartedageraopermanentequecompartilhadaeno afetada por coleta de lixo. Essa gerao no a mesma coisa que o compartilhamentodeclasses realizadopelasJVMClient,disponvelnamaiorpartedossistemas(vejacaptulo11).
10

2005HelderdaRocha

40

ArgoNavisJ281

GernciadememriaemJava

6. Configurao de memria
Existem diversas opes da mquina virtual HotSpot para configurar o tamanho das geraes, do heap total e da gerao permanente. Tambm possveldeterminarotamanhodaspilhasdecadathread.Osajustespodemser realizados de forma absoluta, com valores em bytes; de forma relativa, com percentagens ou relaes de proporcionalidade 1:n; e de forma automtica usandoanliseergonmicabaseadaemmetasdeperformance.

Definio de limites absolutos para o heap


O heap total consiste do espao ocupado na gerao jovem mais o espao ocupado pela gerao estvel. No inclui a gerao permanente, que configuradaparte. Paraalterarolimitemximodoheaptotal,utilizeaopo:
-Xmx<nmero>[k|m|g]

quedefineumlimitesuperioraoheaptotal.Seessaoponoestiverpresente,o sistema usar valores default. O default para mquinas cliente 64 MB. Para mquinas servidoras, o valor calculado via ergonmica: memria fsica ou 1GB. Valores default podem variar entre plataformas, fabricantes, implementaeseversesdiferentesdemquinasvirtuais,portantonosedeve dependerdelesemsituaescrticas. Ovalorinicialdoheapdeterminadopelaopo
-Xms<nmero>[k|m|g]

que tambm estabelece o mnimo de espao que deve ser alocado para o heap (mesmo que no seja usado). O default em mquinas cliente 4MB e em mquinasservidores1/64memriafsicaou1GB. Por exemplo, para um heap ocupando entre 128 e 256 megabytes, podese chamarointerpretadordaforma:
java -Xmx256m -Xms128m ...

O exemplo seguinte configura a ocupao do heap em exatamente 256 megabytes(tamanhofixo).EssaconfiguraoevitaqueaJVMtenhaquecalcular sedeveounodeveaumentaroheap.


java -Xmx256m -Xms256m ...

Ageraopermanente(ondeclassescompiladassoguardadas)nofazparte doheaptotal.Podesernecessrioaumentlaemsituaesemquehmuitouso dereflexoegeraodeclasses(ex:aplicaesEJBeJSP).Duasopesexistem noHotSpotdaSunparaconfigurarseuslimites:


-XX:PermSize=<valor>[k,m,g]

quedefineotamanhoinicialdageraopermanente,e
-XX:MaxPermSize=<valor>[k,m,g]

2005HelderdaRocha

41

ArgoNavisJ281

GernciadememriaemJava

quedefineoseutamanhomximo.Casoosistemaprecisedemaisespaoqueo permitidonestaopo,acontecerOutOfMemoryError. Chamando o interpretador Java com as opes abaixo, sero alocados inicialmente 32 megabytes para a gerao permanente, e o espao ser expandidoatolimitede64megabytes,seforpreciso.
java -XXPermSize=32m -XX:MaxPermSize=64m ...

Uma gerao jovem menor causa coletas pequenas mais freqentes. Uma gerao jovem maior mais eficiente pois coletas sero mais raras, mas se ocorreremirodemorarmais,almdereduziremoespaoparaageraovelha, oquepodecausarcoletasdemoradasfreqentes. Paraalterarotamanhoinicialemximodageraojovem,existemtambm duasopes.Aopo
-XX:NewSize=<valor>[k,m,g]

defineotamanhoinicialdageraojovem,e
-XX:MaxNewSize=<valor>[k,m,g]

oseulimitesuperior.Comoolimitemximodoheapfixo,aumentaragerao jovemtemoefeitodereduzirageraoestvel. Seamquinavirtualforchamadacomasopesabaixo


java -XX:NewSize=64m -XX:MaxNewSize=64m ...

a gerao jovem ter um tamanho fixo de 64 megabytes. Para especificar um valor inicial de 64 megabytes e permitir que a gerao jovem varie at ocupar 128megabytes,devesechamaramquinavirtualdaforma:
java -XX:NewSize=64m -XX:MaxNewSize=128m ...

Tamanho fixo da pilha


Cadathreadtemumapilha.Apilhadivididaemquadros(frames)paracada mtodo cujos dados no so compartilhados. Uma pilha grande evita StackOverflowError, porm se a aplicao tiver muitos threads (ex: servidores) a memria total pode ser consumida de forma ineficiente levando a OutOfMemoryError.Nessassituaespodesereduzirotamanhodapilhaatum tamanhoidealquenocauseStackOverflowError. Otamanhodecadapilhapodeserdefinidocomaopo
-Xss=<valor>[k,m,g]

quedefineumtamanhofixoparaapilhadecadathread.Porexemplo,iniciara mquinavirtualcomaopo
java -Xss128k ...

alteraotamanhodapilhadecadathreadpara128quilobytes. A figura 36 resume os ajustes de tamanho fixo que podem ser realizados atravsdeopesdamquinavirtualHotSpot.

2005HelderdaRocha

42

ArgoNavisJ281

GernciadememriaemJava

Figura36Resumo:ajustesdememria;valoresdeajusteabsolutos

Variao do tamanho do heap


AocupaodoheapnamquinavirtualHotSpotvariadetamanhodurantea execuo de uma aplicao. Os valores fixos atribudos ao heap inicial e heap mximosovaloreslimite:amquinavirtualirprocurarutilizaramemriada formamaiseficiente,socupandooespaorealmentenecessrio.Existemcinco medidasassociadasaotamanhodoheap;duasfixasetrsvariveis: Heap inicial: o espao reservado para a aplicao quando a mquina virtualinicia.OvalorusadoserodefaultoufornecidopelaopoXms. Heapmximo: o maior espao que pode ser reservado para a mquina virtual.OvalorusadoserodefaultouofornecidopelaopoXmx. Heap reservado (committed): inicialmente igual ao heap inicial, mas medida em que a aplicao consome memria, aumenta gradualmente atovalormximoestipuladopeloheapmximo.Umacoletadelixopode diminuiroheapreservadoseoheaputilizadocairabaixodecertolimite. Heap utilizado: o espao realmente ocupado pelos objetos. sempre menorqueoheapreservado.Umacoletadelixoreduzoheaputilizado. Heapdisponvel(free):adiferenaentreoheapreservadoeheaputilizado. Se os valores para heap inicial e mximo forem iguais, o heap reservado ter o mesmo valor e no ir mudar. Se forem diferentes, a mquina virtual ir acompanhar o aumento e diminuio do heap utilizado e ajustar o espao reservado em cada caso. O aumento ou diminuio ocorre quando o heap utilizadoatingeumdeterminadovalor. possvelalterarosvaloresqueforamalteraodoheapreservadoatravsde duas opes da mquina virtual, que estabelecem as percentagens do heap

2005HelderdaRocha

43

ArgoNavisJ281

GernciadememriaemJava

utilizado em relao ao heap reservado que iro causar as mudanas dentro da faixaXms/Xmx.SeXmsforigualaXmxelasnoseroconsideradas. Aopo:
-XX:MinHeapFreeRatio=<percentagemMinima>

defineapercentagemmnimadoheapreservadoqueprecisaestardisponvelaps umacoleta.Odefaultgeralmente40%naClientJVM.Seapsumacoletaoheap disponvel no corresponder a no mnimo esse valor, a mquina virtual aumentaroespaodoheapreservadoproporcionalmenteatalcanarametaou atingirolimite. A percentagem mxima do heap reservado que pode estar disponvel aps umacoletapodeseralteradocomaopo:
-XX:MaxHeapFreeRatio=<percentagemMaxima>

O valor default geralmente 70% na ClientJVM. Se aps uma coleta oheap reservado for maior que este valor, a mquina virtual ir reduzir o espao reservadodoheapatalcanarametaouatingirolimitemnimo. Asfiguras37e38ilustramocrescimentoediminuiodoheapreservadopara aseguinteconfiguraodelinhadecomando:
java -Xms30m -Xmx100m -XX:MinHeapFreeRatio=50 -XX:MaxHeapFreeRatio=60 ...

Figura37Aumentodoheapreservadoapsaumentodoheaputilizadoquepassouaocuparumespao maiorqueoestabelecidoemMinHeapFreeRatio,fazendooheapdisponvelcairabaixode50%.

Figura38Reduodoheapreservadoapsareduodoheaputilizadoquepassouaocuparumespao inferioraoMaxHeapFreeRatio,fazendocomquehouvessemaisde60%deheapdisponvel.

2005HelderdaRocha

44

ArgoNavisJ281

GernciadememriaemJava

O ajuste do tamanho do heap o fator que tem o maior impacto na performance da coleta de lixo geral. Aplicaes que variam o heap com freqncia podero melhorar sua performance ajustando os parmetros de redimensionamento para adequarse ao comportamento da aplicao. Podese tambm definir Xms and Xmx para o mesmo valor, e assim evitar o redimensionamento a cada coleta. Isto evita que a mquina virtual recalcule o usodoheapacadacoleta.Poroutroladoelanocompensarescolhasmalfeitas.

Proporo gerao jovem/estvel


Se um heap tem tamanho limitado, o aumento da gerao jovem diminui a gerao estvel. As opes XX:NewSize e XX:MaxNewSize definem um tamanho absoluto para a nova gerao. O tamanho do espao reservado gerao jovem ir variar proporcionalmente ao heap total dentro desses limites. Umaoutraalternativausaraoporelativa:
-XX:NewRatio=n

quedefineaproporo1:nentreageraojovemeageraoestvel.Agerao jovempassaraocupar1/(n+1)doespaototaldoheap. Na Client JVM a relao default 11 1:8 (NewRatio=8) e a gerao jovem ocupar1/9doheap,comomostraafigura39.

Figura39DistribuiodoheapparaNewRatio=8.

NaServerJVMarelaodefault1:2(NewRatio=2)eageraojovemocupar 1/3doheap,comomostraafigura40.

Figura40DistribuiodoheapparaNewRatio=2.

Porexemplo,seforointerpretadorJavaforchamadodaforma
java -XX:NewRatio=3 ...

n ser 3, a relao ser 1:3 e a gerao velha ter 3 vezes o tamanho a gerao jovem,ocupando75%doespao.Ageraojovemocupar25%doheap. Cada coleta na gerao jovem pode necessitar de alocaes na gerao estvel.Esseespaoprecisasergarantidoouacoletairfalhar.Nahiptesede uma coleta improvvel em que todos os objetos esto ativos, ser preciso reservar memria livre suficiente na gerao estvel para acomodar todos os objetosexistentesnodeneespaossobreviventes.AYoungGenerationGuarantee [Sun 05] (YGG) definida como a reserva prvia de espao na gerao estvel
11

Valoresdefaultdependemdoservidorusado.

2005HelderdaRocha

45

ArgoNavisJ281

GernciadememriaemJava

nessassituaes.umespaoquepodernuncaserusado,masumagarantia necessrianoscoletoresseriais. Idealmente,osobjetosserocopiadosdodenesobreviventeorigemparao sobrevivente destino, mas no h garantia que todos os objetos cabero no sobrevivente. O espao reservado pelo YGG pressupe o pior caso: igual ao tamanhododenmaisosespaosocupadopelosobjetosnosobreviventeorigem. Nohavendocomoreservaresseespao,ocorrerumacoletacompleta. Devido YGG, um den maior que metade do espao do heap reservado inutilizaasvantagensdaGenerationalGC:apenascoletasmaioresiriamocorrer. Comoodenocupaamaiorpartedageraojovem,aopoXX:NewRatiotem forteinfluncianessaconfigurao. Umageraojovemmaiortercomoconseqnciamenoscoletasmenoresmas pausas maiores se ocorrerem. Uma gerao estvel menor como devido ao aumentodageraojovemtambmaumentarafreqnciadecoletasmaiores, j que o espao ser preenchido mais rapidamente. Uma gerao jovem menor causar maior freqncia de coletas menores, principalmente no incio da aplicao. Mas as pausas sero curtas, j que haver poucos objetos ativos e o algoritmo tem custo proporcional aos objetos vivos. Uma conseqncia da gerao jovem menor uma gerao estvel maior, causando o adiamento de coletasmaiores,masquedependendodaaplicao,podemnuncaocorrer. Para escolher o melhor tamanho para a gerao jovem preciso analisar a distribuio dos objetos alocados e estabilizados (tenured) durante a vida da aplicao. Para a maior parte das aplicaes, as configuraes default so suficientes.Amenosquehajapausasmuitolongasoucoletasmaioresexcessivas, devesealocaromximodememriageraojovem,observandoseagarantia da gerao jovem (YGG) continua valendo: no aumente alm da metade do espaousadodoheap.Aalocaodeobjetospodeocorreremparalelo,portanto devese aumentar o tamanho da gerao jovem medida em que houver mais processadores,paraotimizaraeficinciadosistema.

Proporo den/sobreviventes
Utilizandoaopo
-XX:SurvivorRatio=n

possvelalteraraproporoentreossobreviventeseoden.Onmerorefere seaoespaoocupadopelosdoisespaossobreviventes,ouseja,umarelao1:n reserva 1/(n+2) do espao da gerao jovem para cada sobrevivente. O default12 paran25(1/27)paraoClientJVMe30(1/32)paraoServerJVM(figura41).

Figura41Proporoentreodenegeraojovemparan=25.

12

VariaentreplataformaseversesdoHotSpot.

2005HelderdaRocha

46

ArgoNavisJ281

GernciadememriaemJava

SeointerpretadorJavaforchamadodaforma
java -Xmx=100m -XX:NewRatio=3 -XX:SurvivorRatio=3

a distribuio do heap mximo ser de 15MB para o den, 5MB para cada sobreviventee75MBparaageraoestvel,comoilustradonafigura42.

Figura42Exemplodedistribuiodoheapentregeraesestvel,jovem,denesobreviventes.

Umsobreviventemuitograndecausadesperdciodeespao,jqueumdos espaos estar sempre vazio. Tambm reduzir o tamanho do den que ter coletas mais freqentes. Se for muito pequeno poder encher muito rpido ou noconseguirsequeracomodarosobjetos,queserocopiadosdiretamentepara ageraoestvelaumentandoafreqnciadascoletasmaiores. A cada coleta, a JVM define o nmero de vezes que um objeto pode ser copiado entre sobreviventes antes de ser promovido gerao estvel. Este valorchamadodetenuringthreshold.Essecomportamentopodesermodificado comduasopes:
-XX:TargetSurvivorRatio=percentagem

apercentagemdoespaosobreviventequedeveestarcheiaantesdacoleta.O default 50%, que mantm os sobreviventes cheios pela metade. Valores menoresirofazercomqueosobjetossejamcopiadosmaisvezesealcancemo seutenuringthresholdmaisrapidamente. Onmeromximodecpiasnecessriaparaqueocorraapromoodeum objetoparaageraoestvelpodesermodificadoatravsdaopo:
-XX:MaxTenuringThreshold=n

Ovalordefaultparan31.Senforzeroosobjetossempreseropromovidosna primeira coleta. Mesmo com n maior que zero um objeto pode ainda ser promovidonaprimeiracoletaouapsmenosdencoletas,poisnrepresentaum valorlimite.Apromooapsncpiasgarantida,maspodeocorrerantes. Paraobterinformaessobreadistribuiodosobjetosestveis,aopo:
-XX:+PrintTenuringDistribution

gera um relatrio dos objetos na gerao estvel distribudos por idade, e contm, dentre outras informaes, o tenuringthreshold de cada um. Os dados listadossoimportantesparaauxiliarnoredimensionamentodasgeraes.

2005HelderdaRocha

47

ArgoNavisJ281

GernciadememriaemJava

7. Seleo do coletor de lixo


A coleta de lixo nos servidores HotSpot realizada por uma coleo de algoritmos diferentes que atuam em diferentes partes do heap. Uma forma de evitar ter que configurar essas combinaes escolher uma mquina virtual atravsdasopesserverouclient.Existemquatrocoletoresprconfigurados quepodemserselecionadosatravsdeopesdamquinavirtual. Ocoletorserial,ouserialcollector,defaultnoClientJVM.Podeserativadoou desativado(senecessrio)atravsdasopes
-XX:+UseSerialGC ou -XX:-UseSerialGC

O coletor de alta eficincia ou throughput collector default no Server JVM. Podeserativadooudesativado(senecessrio)atravsdasopes


-XX:+UseParallelGC ou -XX:-UseParallelGC

O coletor semiconcorrente de pausas curtas, chamado de mostlyconcurrent low pause collector ou ainda concurrent marksweep collector (CMS) pode ser ativadooudesativadoatravsdasopes
-XX:+UseConcMarkSweepGC

ou -XX:-UseConcMarkSweepGC

Finalmente o coletor incremental de pausas curtas, chamado de incremental low pause collector ou ainda de train collector pode ser ativado ou desativado atravsdasopes
-XX:+UseTrainGC ou -XX:-UseTrainGC

Cada coletor usa uma combinao de algoritmos disponveis otimizados parasituaesdistintas.possvelconfigurarecombinaralgoritmosdiferentes, mas no misturar os coletores prconfigurados. H opes de configurao prpriasquepermitemqueoscoletorescompartilhemalgumasfuncionalidades. Aativaoexplcitadeumcoletorimplicanadesativaodocoletordefault.As opes de desativao no so necessrias. Combinaes entre as opes de ativaogeralmentesoilegais.

Algoritmos utilizados
Algoritmosdiferentessousadosparaasdiferentesgeraesdecadacoletor. Ageraojovempossuitrsalgoritmos: 1. Coletorserial(copyingalgorithm)default 2. Coletorparalelo(concurrentcopyingalgorithm) 3. Coletorparalelodealtaeficincia(scavengingalgorithm) Ageraoestvelpossuioutrostrs: 4. Coletormarkcompactserialdefault 5. Coletormarksweepconcorrente 6. Coletortrainincremental Os coletores prconfigurados combinam esses algoritmos e permitem ajustesealteraesnaconfiguraodefault.
2005HelderdaRocha 48

ArgoNavisJ281

GernciadememriaemJava

Todos os trs algoritmos usados para coletar a geraojovem so algoritmos de cpia. No coletor default, todos os threads so interrompidos e um thread executaoalgoritmodecpiaserial.Noscoletoresparalelos,todososthreadsso interrompidos ao mesmo tempo (comportamento stoptheworld) e um ou mais threads executam um dos dois algoritmos de cpia concorrentes. A pausa provocada em um coletor paralelo diminui com o aumento do nmero de processadoresparalelos,comomostradonafigura43(a).

(a)

(b)

Figura43Coletoresdelixo:(a)dasgeraesjovens;(b)dasgeraesestveis

Na gerao estvel, o coletor serial markcompact compacta o espao a cada coleta.Ocoletorconcorrentemarksweepnofazcompactao,quesrealizada se espao acabar. Como conseqncia, a alocao na gerao estvel, que realizada durante coletas menores, ser mais demorada e ir aumentar as pausasdascoletasmenores.Ocoletorconcorrentefazamaiorpartedotrabalho emparalelo,comomostraafigura43(b),dividindoastarefasemquatroetapas13: 1. Initial mark: marca todos os objetos diretamente alcanveis de fora do heap,parandoaaplicaoefazendoamarcaoemumthread. 2. Mark/preclean: marca os objetos alcanveis recursivamente a partir das referncias achadas na primeira fase. Esta fase realizada em paralelo porumthreadepodedeixardemarcaralgunsobjetos,jqueaaplicao podeestarcriandoobjetosenquantoelessomarcados. 3. Remark:praaaplicaoeusatodososthreadsdisponveispararevisitar todososobjetosemarcarosqueescaparamdesermarcadosnafasemark. Apausaminimizadausandovriosthreads.
A rigor so seis, mas as especificaes descrevem quatro, combinando mark/preclean, e sweep/resetquesosemprerealizadasemseqncia.
13

2005HelderdaRocha

49

ArgoNavisJ281

GernciadememriaemJava

4. Sweep/reset:enquantoaaplicaoexecutaemparalelo,usaumthreadpara varrerdoheaposobjetosinalcanveis.

Coleta incremental
Usado apenas na gerao estvel, o algoritmo do trem, ou train algorithm, realizacoletaincrementalemparalelocomaexecuodaaplicao.Quandoeste algoritmo ativado, a gerao estvel dividida em blocos de memria de 512kB, chamados de vages, que so ordenados de acordo com a ordem de criao em trens, criados a cada coleta. Objetos sobreviventes de coletas na geraojovemsoalocadosnosvagesdetrensexistentes,ouemvagesnovos engatadosnessestrenssenocouberem.Socoletadossempreosvagesetrens mais antigos e alocaes podem ser feitas em qualquer trem que no esteja sendocoletado.Duranteumacoleta,objetosemumvagoqueestsercoletado so transferidos para outro trem at que o vago s contenha lixo. A coleta removevageslixosempararaaplicao. Afigura44ilustraoheapdageraoestveldivididoemtrensevages.

Figura44Divisodoheapdageraoestvelemtrensevagesnousodocoletorincremental.

O coletor do trem no um algoritmo de tempo real14, pois no consegue evitar totalmente a no ocorrncia de pausas, nem determinar um limite mximoparaelas,nemsaberquandoocorremenemcomoimpedirquetodosos threads parem ao mesmo tempo. um algoritmo que coloca a reduo das pausasacimadetodasasoutrasprioridades.Dosalgoritmosdisponveisparaa geraoestvelmenoseficienteesdeveserusadoquandoaausnciatotalde pausasrealmenteforessencial. Paraativaracoletaincrementaldoheapusandoestecoletorhduasopes quefazemamesmacoisa:
-XX:+UseTrainGC ou Xincgc

No existe nenhum algoritmo que seja verdadeiramente de tempo real (hard real time) no HotSpot.Amaiorpartedassoluespropostasetestadasatomomentotemumaltocustosobre aeficincia.Osalgoritmosusadosemmquinasvirtuaiscomunssochamadosdesoftrealtime. As APIse mquinas virtuais Javaque implementam aespecificao de temporeal (JSR1:Real TimeSpecificationforJava)requeremhard realtime e nousama mesma arquitetura do HotSpot. Utilizamumapartedoheapquenofazcoletadelixo(chamadadegeraoimortal)eoutraondeo programadorexplicitamentegerenciaociclodevidadeobjetosatravs de escopos(devolve parte da responsabilidadedegernciadememriaaoprogramador.)
14

2005HelderdaRocha

50

ArgoNavisJ281

GernciadememriaemJava

Comoacoletaafetaapenasageraoestvel,ageraojovemcontinuarsendo coletada usando o coletor de cpia serial default. possvel troclo por um coletor paralelo na gerao jovem usando a opo XX:+ParNewGC, para que todaacoletasejarealizadaemparalelo. O coletor incremental parou de ser atualizado desde a verso 1.4.2 do HotSpotepodernoestarpresenteemversesfuturas.

Opes de paralelismo
Asopesdescritasaseguirpermitemsousadasemconjuntocomaescolha deumdeterminadocoletor. Os coletores paralelos que concentram suas otimizaes na gerao estvel utilizampordefaultocoletorserialparaageraojovem.Istopodesermudado comaopo:
-XX:+UseParNewGC

Quefazcomqueamquinavirtualuseumcoletordecpiaparalelo(2)para a gerao jovem. Esta opo s pode ser usada com os coletores que no especificam um algoritmo para a gerao jovem: XX+:UseTrainGC ou XX:+UseConcMarkSweepGC. No compatvel com XX+:UseParallelGC que tem umalgoritmoprprioparaanovagerao. Onveldeparalelismodessaoperaopodesercontroladacomaopo
-XX:ParallelGCThreads=n (default:nmerode.threadsdisponveis)

queespecificaquantosthreadsocoletorusarparacoletarageraojovem. VriasopessoutilizadasapenasnocoletorCMS(ConcurrentMarkSweep) erequeremousodaopoXX:+UseConcMarkSweepGCumavezqueestecoletor nodefaultemnenhumaconfiguraodemquinavirtual. Aopo


-XX:+CMSParallelRemarkEnabled

usadaapenasnocoletorCMS,fazcomqueaetapaderemarcao(remark)seja realizada em paralelo usando quantos threads estiverem disponveis, diminuindo as pausas. Apesar de referirse apenas gerao estvel, requer o usodaopoXX:+UseParNewGCetambmdeXX:+UseConcMarkSweepGC. Uma coleta concorrente deve sempre iniciar e terminar antes que a gerao estvel fique cheia. Isto difere do comportamento do coletor serial que inicia quando a gerao enche. Para saber quando iniciar, o coletor mantm estatsticas para estimar o tempo que falta antes da gerao estvel encher e o temponecessriopararealizaracoleta.Assuposiessoconservadoras.Uma coleta concorrente tambm iniciar assim que a ocupao da gerao estvel passardeumcertolimite.Estevalorpodeseralteradocomaopo
-XX:CMSInitiatingOccupancyFraction=n

onde n a % do espao ocupado antes da coleta (0100). O valor inicial aproximadamente68%doheap.

2005HelderdaRocha

51

ArgoNavisJ281

GernciadememriaemJava

possveldiminuiraspausasdoCMS,atravsdoseumodoincremental.As principaisopesso:
-XX:+CMSIncrementalMode (default:desabilitado)

quehabilitamodoincremental,
-XX:+CMSIncrementalPacing (default:desabilitado)

quepermiteajusteautomticodociclo(pacing)combaseemestatsticas,
-XX:CMSIncrementalDutyCycle=n (default:50)

queespecificaapercentagemdetempo(0100)entrecoletasmenoresemqueo coletor concorrente pode executar. Se o pacing automtico habilitado, este o valorinicial.Finalmente
-XX:CMSIncrementalDutyCycleMin=n (default:10)

define a percentagem (0100) que ser o limite inferior do ciclo caso o pacing estejahabilitado. Maiores detalhes sobre as vrias outras opes do CMS podem ser encontrados na documentao oficial e nos artigos listados no final, particularmente[Gupta02]e[Nagarajayya02].

Como escolher um coletor de lixo?


Quandoaescolhadeumcoletordelixoimportaparaousurio?Paramuitas aplicaes ele no faz diferena. O coletor de lixo previamente instalado e configurado na mquina virtual geralmente suficiente. Ele realiza pausas de pouca durao e freqncia que em geral so desprezveis. Mas, em sistemas grandes,essaspausasouaCPUconsumidapelocoletorpodemterimportncia significativa.Nessassituaes,podecompensarescolhercorretamenteomelhor coletordelixoeajustlo. Paramaiorpartedasaplicaesocoletorserial,ouSerialGC,adequado.Os outrostmoverhead,somaiscomplexosepodempioraraperformancedeuma aplicao que realmente no precise deles. Se uma aplicao no necessita do comportamento especial de um coletor alternativo, deve usar o coletor serial. Emgeral,computadorescommenosde2gigabytesdememriaRAMemenos de dois processadores executam bem aplicaes tpicas com um coletor serial. Em grandes aplicaes com muitos threads, alto requerimento de memria, comportamento incomum, rodando em mquinas com heaps grandes e muitos processadores,ocoletorserialprovavelmentenoseramelhorescolha.Neste caso,aescolhadeveinicialmenterecairsobreocoletorparalelodealtaeficincia, ouParallelGC. O coletor paralelo de alta eficincia, tambm chamado de Parallel Collector ou ThroughputGarbageCollector(TGC)tem comoobjetivo a mxima eficincia com eventuaispausas.Aplicaesqueusamessecoletorraramenterealizamcoletas maiores, e quando realizam, no se incomodam muito se o sistema parar por

2005HelderdaRocha

52

ArgoNavisJ281

GernciadememriaemJava

alguns segundos. Consideram importante que coletas menores sejam rpidas (sosemprerealizadasemparalelo)equeaeficincia(taxaentreotempousado pela aplicao pelo tempo usado na coleta de lixo) seja a melhor possvel. A performance de aplicaes que usam este coletor aumenta proporcionalmente aonmerodeprocessadoresexistentes. A segunda alternativa a se considerar o coletorconcorrentedebaixalatncia (Low Latency Collector) tambm chamado de MostlyConcurrent Collector ou ConcurrentMarkSweep(CMS)garbagecollector.Seuobjetivoalcanaromnimo depausasemtrocadaeventualreduodaeficincia.Ascoletasmaiores,apesar de pouco freqentes, podem impor pausas muito longas (principalmente com heapsgrandes).Pormestecoletordiminuiaspausasdacoletamaior,rodando emparalelocomaaplicaoprincipal,queficaumpoucomaislenta.Aspausas no so totalmente eliminadas. Ocorrem duas pequenas pausas, porm so da mesma ordem das pausas que ocorrem nas coletas menores. indicado em aplicaes que tm muitos dados de vida longa (grande gerao estvel) e requerimento de pausas mnimas. Pode haver vantagens para aplicaes desse tipomesmoemmquinascomumprocessador. A figura45 compara duas configuraes tpicas usando esses dois coletores paralelos.

Figura45Comparaoentrealgoritmosdocoletorparalelo(TGC)edocoletorconcorrente(CMS).

Por fim, h o coletorincremental, tambm chamado de traingarbagecollector. Comoelenoeliminatotalmenteaspausas,suavantagememrelaoao CMS emumsistemacommuitosprocessadorespodernosergrande,devidosua baixaineficincia.OCMSnomodoincrementalpodealcanaralgumasdesuas vantagens.Deveserusadoquandohouverumrequerimentodepausasmnimas, e quando uma eficincia mais baixa no fizer tanta diferena. Esse coletor poder reduzir pausas em sistemas com menos (ou at um) processadores,

2005HelderdaRocha

53

ArgoNavisJ281

GernciadememriaemJava

sendo uma alternativa possvel em aplicaes com requerimento de pausas mnimasquerodamemsistemasmenores. A tabela 3 ilustra algumas das diferenas entre as opes de coletor de lixo existentesdoHotSpotatoJava5.0.
Coletor Opo de ativao Algoritmos utilizados Gerao Jovem Coletor serial Coletor paralelo com eficincia mxima Coletor paralelo com pausas mnimas Coletor incremental -XX:+UseSerialGC -XX:+UseParallelGC -XX:+UseConcMarkSweepGC Coletor de cpia serial (1) (default) Coletor de cpia concorrente de alta eficincia (3) Coletor default (1); Coleta concorrente (2) pode ser ativada com a opo -XX:+UseParNewGC Coletor mark-sweep concorrente (5) (sem compactao) Algoritmo do trem (train) incremental (6) Gerao Estvel Coletor mark-compact serial (4) (default)

-XX:+UseTrainGC

Tabela3ColetoresdelixousadosnoHotSpot.

2005HelderdaRocha

54

ArgoNavisJ281

GernciadememriaemJava

8. Monitorao de aplicaes
Para ajustar os parmetros configurveis da mquina virtual, preciso realizar medies. Vrios parmetros da mquina virtual HotSpot fornecem informaes teis. Alm disso, h ferramentas grficas que mostram o comportamentodamquinavirtualesuaalocao/liberaodememria. preciso saber: 1) oque ajustar e como ajustar; 2) oobjetivo do ajuste se menospausasoumaiseficincia;e3)asconseqnciasdoajuste. Podese tambm utilizar ajustes automticos usando o recurso do Java 5.0 chamadodeErgonomics.Mesmoparausarergonmica,precisoconhecercomo funcionaocoletordelixo. As metas desejveis geralmente envolvem obter menos pausas e mais eficincia de processamento (throughput). preciso avaliar qual das duas prioritria,jquemelhorarumapodepioraraoutra. Eficincia(capacidadedeprocessamento)apercentagemdetempototalno gastacomcoletadelixo.Istoincluitempogastocomalocao.Seaeficinciafor maiorque95%,geralmentenovaleapenafazerajustesnamquinavirtual. Aspausassootempoemqueumaaplicaoparecenoresponderporque est realizando coleta de lixo. Em alguns sistemas interativos elas devem ser mnimas.Emsistemasquerealizamprocessamentodemoradoelassotoleradas.

Como obter informaes sobre as coletas


Podeseobterinformaessobrequandoocorremcoletasecomoistoafetaa memriausandoaopo
-verbose:gc

queimprimeinformaesbsicassobreascoletasmaioresecoletasmenores.As estatsticassoredirecionadasparaasadapadro,masusandoaopo
-Xloggc:<arquivo>

junto com verbose:gc os dados sero gravados no arquivo especificado. O formado dos dados lido por vrias ferramentas de anlise de logs. Por exemplo,achamada
java verbose:gc Xloggc:aplicacao.gc aplicacao.Main

Imprime informaes de coleta da aplicao Main no arquivo de texto aplicacao.gc. Uma sada tpica de verbose:gc (em uma grande aplicao servidora) est mostradaaseguir:
[GC 325407K->83000K(776768K), 0.2300771 secs] [GC 325816K->83372K(776768K), 0.2454258 secs] [Full GC 267628K->83769K(776768K), 1.8479984 secs]

Asadamostraduascoletasmenoreseumacoletamaior.Osnmerosantes e depois da seta (325.407K>83.000K) indicam o tamanho total de objetos alcanveis antes e depois da coleta. Depois de pequenas coletas, a contagem

2005HelderdaRocha

55

ArgoNavisJ281

GernciadememriaemJava

incluiobjetosquenoestonecessariamentealcanveismasquenopuderam ser coletados. O nmero entre parnteses (776.768K) o total de espao disponvel (heap total usado menos um dos espaos de sobreviventes, sem contar o espao da gerao permanente). No exemplo, as coletas menores levaramemmdia0,24segundos.Acoletamaiorlevouquasedoissegundos. Podeseimprimirmaisinformaescom
-XX:+PrintGCDetails

quefazcomqueamquinavirtualmostremaisdetalhessobreacoletadelixo, comovariaessobreotamanhodasgeraesapsumacoleta.tilparaobter feedbacksobrefreqnciadascoletaseparaajustarostamanhosdasgeraes.H maisdetalhespormnocompleto:


java -XX:+PrintGCDetails GC [DefNew: 64575K->959K(64576K), 0.0457646 secs] 196016K-133633K (261184K), 0.0459067 secs]]

Para obter mais informaes preciso acrescentar mais opes. Para informar o tempo transcorrido e distribuio de objetos durante a aplicao importantesparatomadadedecisesdeajuste,hduasopes:
-XX:+PrintGCTimeStamps

queimprimecarimbosdetemporelativosaoinciodaaplicao,e
-XX:+PrintTenuringDistribution

queacrescentaaorelatriodetalhesdadistribuiodeobjetostransferidospara a rea estvel. Pode ser usado para estimar as idades dos objetos que sobrevivem gerao jovem e para descrever a vida de uma aplicao. O exemploabaixoilustraumusotpicodessasopes.
java -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintTenuringDistribution ... 5.350: [GC Desired survivor size 32768 bytes, new threshold 1 (max 31) age 1: 57984 bytes, 57984 total age 2: 7552 bytes, 65536 total 756K->455K(1984K), 0.0097436 secs]

Monitorao com o jconsole


O prprio ambiente de desenvolvimento Java possui uma ferramenta simplesqueforneceinformaesgrficassobreamemriausandoatecnologia JMX (Java Management Extensions): o jconsole. Para habilitar o agente JMX e configurarsuaoperao,precisodefiniralgumaspropriedadesdosistemaao iniciar a mquina virtual. As propriedades podem ser passadas em linha de comandodaforma
java Dpropriedade ... java Dpropriedade=valor ...

2005HelderdaRocha

56

ArgoNavisJ281

GernciadememriaemJava

Se um valor no for fornecido, a propriedade utilizar um valor default (se houvereseforaplicvel). AsduasprincipaispropriedadesJMXdamquinavirtualso
com.sun.management.jmxremote[=true|false] com.sun.management.jmxremote.port=valor

A primeira habilita o agente JMX localmente e permite monitorao local atravsdoconectorJMXusadopelaferramentajconsole.Seovalorforomitido, serconsideradotrue.Ovalorfalseomesmoqueomitirapropriedade. A segunda propriedade habilita o agente remoto JMX. Permite monitorao remotaatravsdeumconectorJMXdeinterfacepblicadisponibilizadaatravs deumaportaTCP/IP.Ovalorpassadocomoargumentodeveseronmeroda porta.Estaopopoderrequereroutraspropriedades15. ParahabilitaroagenteJMXparamonitoraolocalprecisoprimeiroexecutar aclasseouJARdaaplicaoviaJVMpassandoapropriedadejmxremote:
java Dcom.sun.management.jmxremote pacote.MainClass java Dcom.sun.management.jmxremote jar Aplicacao.jar

Depois,precisoobteronmerodoprocessoJVMusandoojps16:
> jps 3560 Programa 3740 pacote.MainClass 3996 Jps (mquinavirtual) (useestenmero!) .

Finalmente,iniciaseojconsolecomonmerodoprocesso.Ocomandodeveser iniciadopelomesmousurioqueiniciouaaplicao:
> jconsole 3740

Paramonitoraoemtempodeproduo,recomendaseusoremoto(devido ao overhead da aplicao). Para configurar, preciso obter uma porta de rede livre. A porta ser usada para configurar acesso remoto via RMI. O sistema tambmcriarnoregistroRMIumnomejmxrmi. Almdaportadeacesso,precisoconfigurarpropriedadesdeautenticao, dentre outras. Para configurao do acesso remoto e outras informaes, consulteadocumentao. Paraexecutarojconsoleparamonitoraoremota,deveseinformaronomeda mquinaenmerodoprocessoasermonitorado:
> jconsole alphard:3740

Se o nmero do processo for omitido no acesso local, o jconsole ir oferecer umalistadeprocessosativosparaescolha.Afigura46ilustraateladojconsole.

15 16

Vejatabela1em/docs/guide/management/agent.html(documentaoJ2SE5.0) FerramentadistribudanoJ2SDK.

2005HelderdaRocha

57

ArgoNavisJ281

GernciadememriaemJava

Figura 46 Tela do jconsole, mostrando aba de memria. Esta aba contm um grfico mostrando utilizao de qualquer gerao em relao ao tempo, cones ilustrando percentagem de utilizao de memrianasgeraes,ereadetextocontendoquantidadesdememriausada,reservada(committed), mxima,temposequantidadesdascoletasmaioresemenores.

Monitorao com as ferramentas do jvmstat


Outraferramentadisponvelnoambientededesenvolvimentoojstatuma ferramenta do pacote experimental jvmstat. Ela obtm dinamicamente estatsticas de uso das geraes, de compilao, de carga de classes em tempo real,semprecisardeJMX.Paraexecutar,precisotambmteroiddoprocesso doJVM.Asintaxe
> jstat <opes> jvmid

Afigura47ilustraumexemplodeexecuodojstatediferentesinformaes apresentadas.

Figura47Exemplodeutilizaodaferramentajstat.

2005HelderdaRocha

58

ArgoNavisJ281

GernciadememriaemJava

OVisualGCaferramentavisualdopacoteexperimentaljvmstat,masno distribuda com o SDK 5.0. preciso fazer um download separado17. Mostra geraes,coletas,cargadeclasses,etc.graficamente..Pararodar,precisoobter o nmero do processo da aplicao a monitorar e o perodo de coleta de amostras(emmilissegundos).Oexemploaseguirmostracomoexecutar:
> jps 21891 Java2Demo.jar 1362 Jps.jar > visualgc 21891 250

O Visual GC tambm permite monitoramento remoto. Para isto, preciso obteronmerodoprocessoremotoeacrescentaronomededomnio:


visualgc 21891@remota.com 250

Afigura48ilustraumateladesadadoVisualGC.

Figura 48 Monitorao com o Visual GC. A janela da esquerda contm dados estatsticos sobre o sistemaeascoletas,eespaosocupadospelasgeraespermanente(Perm),estvel(Old),ejovem(Eden, S0eS1).Ajaneladadireita(Graph)mostratemposdecompilaodoJIT,temposdoClassLoaderpara carregarclasses,tempototaldascoletasedistribuiodousodememrianasgeraes.Ajanelainferior umhistogramaquedestacaaidadedosobjetossobreviventes,atovalormximodetenuringthreshold, quenaimagemacima31.

Outras ferramentas
Existem vrias outras ferramentas de monitorao de memria que podem ser usadas para obter informaes sobre geraes, coletas de lixo, uso do heap, promoo,etc.Algumasdasmaispopularesso:

17

http://java.sun.com/performance/jvmstat/visualgc.html

2005HelderdaRocha

59

ArgoNavisJ281

GernciadememriaemJava

GCPortal18 uma aplicao J2EE que gera grficos e estatsticas. Requer instalaoemumservidoreconfigurao.Nositehumaversoonline quepodeserusadalivremente. GCViewer 19 analisa documentos de texto criados com Xloggc:arquivo, mostracomportamentodasgeraeseoutrasinformaes.Podetambm executaremtemporeal(vejafigura49.)

Figura49MonitoraocomoGCViewer.

Vrios profilers comerciais e gratuitos tambm oferecem informaes e capacidade de monitorao em tempo real da JVM. Alguns exemplos so os profilers comerciais: JProbe, OptimizeIt, JProfiler e tambm os gratuitos como: NetBeansProfiler,EclipseProfiler,JRat,Cougaar,etc. Seja qual for a ferramenta usada, importante entender o significado das informaesobtidasantesdetentarqualquertipodeajustedeperformance.

18 19

java.sun.com/developer/technicalArticles/Programming/GCPortal www.tagtraum.com

2005HelderdaRocha

60

ArgoNavisJ281

GernciadememriaemJava

9. Ajuste automtico: ergonomics


O objetivo da ergonmica obter a melhor performance da JVM com o mnimo de ajustes de linha de comando. Busca obter, para uma aplicao, as melhoresseleesdetamanhodeheap,coletadelixoecompiladordetempode execuo(JIT). Os ajustes so baseados em duas metas: pausa mxima e capacidade de processamentomnima.Tmcomoalvoaplicaesqueexecutamemservidores grandes (Server JVM). Os primeiros ajustes automticos so realizados na instalao e na execuo. Na instalao, o sistema tentar descobrir se est em umamquinadeclasseservidoroucliente.SetiverpelomenosduasCPUs epelomenos2GBdememriafsica,serconsideradaservidora,casocontrrio, cliente. Amquinavirtualinstaladaserdefault,passandoasersempreusadaano ser que seja especificada outra, durante a execuo, atravs das opes server ouclient.Seumaaplicaoestiveremumamquinaservidora,iniciaraServer JVM,quecomeamaislentamente,mascomotempoexecutamaisrapidamente. Seaaplicaoestiveremmquinacliente,usaraClientJVM,queconfigurada paramelhorperformanceemambientescliente. A parte mais interessante da ergonmica, porm, o ajuste automtico das geraes e parmetros de coleta de lixo. O ajuste baseado em metas. Para realizlo,ousurioespecificaumametadepausamxima,umametadeeficincia mnima e configura uso mnimo/mximo de memria do heap. A partir dessas informaes, o coletor de lixo ajusta automaticamente vrios parmetros para tentar alcanar as metas. Nem sempre consegue. Se no conseguir, o usurio poder ajustar outros parmetros at obter uma configurao aceitvel. Os ajustes feitos pelo coletor incluem o tamanho e proporcionalidade entre a geraojovem,espaossobreviventes,geraoestveleoutrosvalores,comoa alteraodapolticadepromooparageraoestvel. Aergonmicatrabalhacommetas,nocomgarantias.Nohcomogarantir queasmetasseroalcanadas.Algumasmetaspodemserincompatveiscomos parmetros ou com o ambiente disponvel. Mesmo falhando, podem fornecer umfeedbackimportante,eindicarnecessidadedesoftwareehardware.Devese realizarajustesatchegaromaisprximopossveldasmetasdesejadas.

Controles de ergonmica no coletor paralelo


As opes relativas ergonmica referemse a ajustes realizveis no coletor paralelodealtaeficincia.Todasasopesabaixorequeremousodoparmetro XX:+UseParallelGCouumServerJVMcomocoletordefault. Aopo
-XX:MaxGCPauseMillis=valor

estabelece a meta de pausas mximas. O valor representa uma quantidade em milissegundos, que o tempo mximo que o coletor poder parar a aplicao

2005HelderdaRocha

61

ArgoNavisJ281

GernciadememriaemJava

para realizar coleta de lixo. A mquina virtual tentar garantir pausas mais curtasqueovalorespecificado.Estaopotemprecednciasobreaopo:
-XX:GCTimeRatio=n

quedefineumametadeeficincia(throughput).Aeficincia tempodeaplicao tempodecoletadelixo =1 1 1 +n

Ondenumvalornormalizadoquemedeaproporodetempodedicado aplicaodaforma1:n.Senfor19,porexemplo,amquinavirtualreservar aplicao 20 (19 + 1) vezes mais tempo que a coleta de lixo (coleta ter 5% do tempo).EstaopotemmenosprecednciaqueXX:MaxGCPauseMillis,ouseja, se a meta de pausas estiver presente, ela ser buscada em detrimento da eficincia. Aopo
-XX:+UseAdaptiveSizePolicy

automaticamenteligadaseaopoXX:+UseParallelGCestiverpresenteouse a Server JVM estiver sendo usada com seu coletor default. Com esta opo presente,amquinavirtualcoletadadosesebaseianelespararedimensionaras geraesjovemeantiga. Servidoresdedicadoscompelomenos256MBdememriafsicapodemusar aopo
-XX:+AggressiveHeap

quelevaamquinavirtualautilizarinformaescomoquantidadedememria e nmero de processadores para configurar vrios parmetros buscando otimizartarefasquefazemusointensodememria.Seuusoimplicanousodas opes XX:+UseParallelGC e XX:+UseAdaptiveSizePolicy. uma opo exclusivadocoletordeparalelo (ParallelGC)enopodeserusadaemconjunto comXX:+UseConcMarkSweepGC.

Como utilizar a ergonmica


Inicialmente,noescolhaumvalormximoparaoheap(Xmx).Escolhauma meta de eficincia (throughput) que seja suficiente para sua aplicao. Em uma situao ideal, o sistema aumentar o heap at atingir um valor que permitir alcanarametadeeficinciadesejada. Se o heap alcanar o limite e o throughput no tiver sido alcanado, ento escolhaumvalormximoparaoheap(menorqueamemriafsicadamquina) erodeaaplicaodenovo.Seaindaassimametadeeficincianoforatingida, altademaisparaamemriadisponvelnaplataforma. Seametadeeficinciafoialcanadamasaspausasaindaforemexcessivas, estabeleaumametadetempomximoparapausas.Istopodefazercomquea meta de eficincia no seja mais alcanada. Escolha valores que garantam um tradeoffaceitvel.

2005HelderdaRocha

62

ArgoNavisJ281

GernciadememriaemJava

Concluses
Mquinas virtuais HotSpot implementam diversos algoritmos clssicos de coletadelixo.Todossofundamentadosemumheapdivididoemgeraeseso prconfiguradosparasituaes,plataformaseusosdiferentes.Todospermitem ajustesmanuaisouautomticos. O ajuste correto da mquina virtual em grandes aplicaes pode trazer ganhosdramticosdeperformance.Umajustepodesersimplesmenteaseleo da mquina virtual (servidora ou cliente) ou a definio manual de diversos e complexos parmetros. As verses mais recentes da JVM permitem ajustes automticos,masparaajustarquaisquerparmetros(mesmoosautomticos) preciso conhecer um pouco sobre o funcionamento dos algoritmos. A configurao manual (ex: tamanho de heap) impe conseqncias que tm impactosemoutrasreasdaperformance,inclusivenoajusteautomtico.Metas deajusteautomticotambmafetamoutrasmetasouparmetros.

10. Apndice: Class data sharing (CDS)


Classdatasharing(compartilhamentodosdadosdeclasses)umrecursodas JVMClient, verso 5.0 para reduzir o tempo de incio de pequenas aplicaes. Duranteainstalao,criadoumarquivodeclassesqueserocompartilhadas pelasmquinasvirtuaisqueestiveremexecutando,evitandoterquecarreglas novamenteemoutrasexecues. Para suportar este recurso, preciso usar uma plataforma que no seja Windows 95/98/ME e usar o JVM Client e coletor de lixo serial (default em desktops). AsopesdamquinavirtualHotSpotrelacionadascomCDSso:
-Xshare:[on|off|auto]

queliga/desligaouusaCDSautomaticamente,sepossvel,e
-Xshare:dump

que gera novamente o arquivo de classes compartilhadas. O arquivo fica armazenado na rea do ambiente de execuo. Para que o arquivo seja gerado de novo, preciso primeiro apaglo. No Java 5.0, este arquivo est localizado em$JAVA_HOME/client/classes.jsa.

2005HelderdaRocha

63

ArgoNavisJ281

GernciadememriaemJava

Parte III - Finalizao, memory leaks e objetos de referncia


A maior parte deste tutorial tratou de assuntos que interessam mais ao administrador de sistema que o programador Java. Por no precisar se preocupar com a liberao de memria, tampouco lidar com algoritmos complexos de alocao, um programador pode criar seus programas e sequer lembrar da existncia de heap, pilha, coletas de lixo e outras questes relacionadas memria. Esses temas geralmente no so parte das preocupaesdeumprogramadorJavaesurgemnormalmentenumafasemais avanadadodesenvolvimentoounafasedeotimizao. Masconheceremalgumdetalheoprocessodecriaoedestruiodeobjetos importantepoisalinguagemJavaflexvelosuficienteparapermitirqueum programador inadvertidamente sobreponha mtodos chamados de um construtor,esqueadeanularrefernciasdecoleesnoutilizadas,criemuitos objetos em um tempo muito curto, chame o coletor de lixo explicitamente, chame os finalizadores ou use mtodos da API como finalize() sem entender completamente como funcionam. Programas que usam inadequadamente recursosqueinterferemnaalocaoeliberaodememriapoderonofazer diferena,poderoeventualmenterodarmaisrpido,pormtmgrandechance decausarproblemasquelevaroaumaperformanceindesejvelouatmesmo seufuncionamentoincorreto. Estaseoexploraoprocessodeconstruoedestruiodeobjetosdoponto devistadeumprogramador,tratandoprincipalmentedafinalizao,queum tema menos abordado. Mostra como implementar corretamente o mtodo finalize(),comoevitarvazamentosderefernciasemconstrutores,ecomoevitar finalize().Tratadeumproblemafreqentementeignoradoporgrandepartedos programadoresJava:osvazamentosdememria,oumemoryleaks.Elesexistem em Java. Embora bem mais benignos que suas variaes em C ou C++, ainda provocam problemas como esgotamento dos recursos da mquina virtual. Algumasestratgiasparaachloseconsertlosserodiscutiudas.Porfim,uma API para controlar diversas etapas da finalizao dos objetos foi introduzida a partir do Java 1.2: os objetos de referncia. Apesar de no ser nova, pouco usada. Podem no s permitir maior controle nas etapas de finalizao de objetos,comopermitiracriaodeobjetoscomrefernciasfracasquepodemser recolhidosquandoamemriaestescassaouacadacoleta. Comoestaumaseovoltada paraprogramadores,havermaisexemplos decdigoqueargumentosdelinhadecomandoealgoritmosdecoletadelixo, masosassuntosabordadosnasseesanterioresseroteispoisoambienteque iremoscontrolarexatamenteoquefoiexploradoanteriormente.

2005HelderdaRocha

64

ArgoNavisJ281

GernciadememriaemJava

11. Alocao e liberao de memria


A criao de um objeto geralmente envolve a alocao de memria no heap paraconteroobjetoeaatribuiodoponteiroendereonoheapondeoespao para o objeto foi alocado a uma varivel de pilha que guardar a referncia. Objetospodemsercriadosexplicitamentededuasformas[JVM2.17.6]: atravsdeumaexpressonewClasse(); atravsdomtodonewInstance()daclassejava.lang.Class. Apenas objetos String podem ser criados implicitamente. A criao de Stringspodeserrealizadadetrsmaneiras: atravsdadefiniodeumliteral, atravsdacargadeumaclassequepossuiliteraisdotipoString,ou atravsdaconcatenaodeliteraisdotipoString. QuaisquerobjetoscriadossodestrudosautomaticamentepelaJVMatravs dosistemadegerenciamentodememriaporcoletadelixoautomtica.

Criao de objetos
Quandoumanovainstnciadeumaclassecriada,memriaalocadapara todas as variveis de instncia declaradas na classe e superclasses, inclusive variveis ocultas. No havendo espao suficiente para alocar memria para o objeto,acriaoterminarcomumOutOfMemoryError. Se a alocao de memria terminar com sucesso, todas as variveis de instncia do novo objeto, inclusive aquelas declaradas nas superclasses, sero inicializadasaseusvaloresdefault(0,null,false,\u0000).Nopassoseguinte,os valorespassadoscomoargumentosparaoconstrutorsocopiadossvariveis deparmetrolocaiseaconstruoiniciada. Aexecuodeumconstrutorenvolveachamadadeoperaesexclusivasda criaodeobjetos:super(),quefazumachamadadesubrotinaaoconstrutorda superclasse, e this(), que chama um outro construtor da mesma classe. A primeira instruo do construtor no pode ser outro cdigo exceto uma chamada implcita (oculta) ou explcita a super(), ou uma chamada explcita a this()quetambmpassarocontroleparaumoutroconstrutorqueemalgum ponto chamar super(). O controle sobe a hierarquia atravs da cadeia de construtores chamados pela instruo super(). Chegando na classe Object o nicoquenopossuisuper()realizaosseguintespassos: 1. Inicializa variveis de instncia que possuem inicializadores explcitos (atribuiesnolocaldadeclarao) 2. Executaocorpodoconstrutor 3. Retornaparaoprximoconstrutordahierarquia(descendoahierarquia), erepeteessestrspassosatterminarnoconstrutorquefoichamadopela instruo new. Quando o ltimo construtor for terminado, retorna a refernciadememriadonovoobjeto. mais fcil entender o processo com uma ilustrao. A figura50 mostra os vriospassosdacriaodeumobjeto.

2005HelderdaRocha

65

ArgoNavisJ281

GernciadememriaemJava

Figura50Passoapassodaconstruodeumobjeto

Destruio de objetos
Em Java, o coletor de lixo realiza a destruio de objetos liberando a memria que foi alocada para ele. No responsabilidade do programador preocuparse com a remoo de qualquer objeto individual. O instalador ou usurio da aplicao pode interferir ajustando as configuraes do coletor de lixo para o ambiente onde a aplicao ir executar. O programador pode interferirdemaneiralimitadanoprocessodedestruiodevriasmaneiras: rotinasdefinalizaoinseridasantesdaliberaodememria, chamadasexplcitasaocoletordelixo, remoodasrefernciasparaumobjetoparatornloelegvelcoleta, usoderefernciasfracas,ou finalizao. Antes que a memria de um objeto seja liberada pelo coletor de lixo, a mquinavirtualchamarofinalizadordesseobjeto[JLS12.6]. A linguagem Java no determina em que momento um finalizador ser chamado. A nica garantia que ele ser chamado antes que a memria do objetosejaliberadaparareuso(podenuncaacontecer).Tambmgarantidoque o construtor de um objeto completar antes que a finalizao do objeto tenha incio. Alinguagemtambmnoespecificaqualthreadchamarofinalizador,mas garante que esse thread no estar usando travas acessveis pelo usurio. No garante nenhuma ordenao: a finalizao pode acontecer em paralelo com outrosprocessos. A finalizao importante? Depende. H objetos que no precisam de finalizadores. So aqueles cujos recursos so automaticamente liberados pelo coletor de lixo, por exemplo, alocao na memria e referncias (inclusive

2005HelderdaRocha

66

ArgoNavisJ281

GernciadememriaemJava

circulares) de qualquer tipo. E h objetos que precisam de finalizadores. So os queprecisamliberarrecursosexternos.Elesprecisam Fechar arquivos abertos e soquetes: o sistema operacional limita quantos recursospodemserabertossimultaneamente;nofinalizardepoisdouso podeimpediracriaodenovosarquivosousoquetes; Fechar streams: fluxos de gravao podem ficar incompletos se o buffer noforesvaziado. Terminar threads: eles costumam rodar em loops; finalizadores ligam um flag para terminar o loop ou interrompem o thread para evitar que o programanuncatermine. Afigura51ilustraoprocessodedestruiodeobjetos.

Figura51Passoapassodadestruiodeobjetos

Os objetos da figura 51 possuem finalizadores automticos. Em Java, qualquerobjetopodeterumfinalizadorchamadoautomaticamenteantesdeser destrudo.FinalizadoresemJavasoopcionaisenosotoimportantesquanto finalizadoresemCouC++.Paraimplementar,precisosobreporaassinatura:


protected void finalize() throws Throwable {...}

O mtodo finalize() chamado automaticamente e apenas uma vez somente quando o objeto no for mais alcanvel atravs de referncias comuns (as refernciasraiz).Omtodofinalize()noserchamadose Nosobrepuserexplicitamenteomtodooriginal:ousoopcional! No houver necessidade de liberar memria (o coletor no executar), mesmoquetodasasrefernciasparaoobjetojtenhamsidoperdidas. Achamadadosfinalizadoresautomticos,portanto,nogarantidadurante avidadaaplicao.Suachamadatambmdependedevriosoutrosfatoreseda implementaodocoletordelixousado.

2005HelderdaRocha

67

ArgoNavisJ281

GernciadememriaemJava

Ociclodevidacompletodeumobjeto,envolvendosuacriao,finalizaoe destruioestilustradonafigura52.

Figura52Ciclodevidadeumobjeto

Alcanabilidade
Objetosalcanveissoobjetosquenopodemserdestrudospelocoletorde lixo.Podemseralcanadosatravsdeumacorrentederefernciaspartindodeum conjuntoraiz de referncias. O conjunto raiz contm referncias imediatamente acessveisaoprograma,emdeterminadomomento.Sorefernciasdoconjunto raiz: Variveislocais e argumentos dos mtodos quando esto executando um threadativo(refernciasarmazenadasnapilha); Variveisderefernciaestticas,depoisquesuasclassesforemcarregadas; Variveis de referncia registradas atravs da Java Native Interface, implementadasemoutraslinguagens. Existemtrsestadoselementaresdealcanabilidade: alcanvel (reachable): pode ser acessado atravs de um thread ativo; existemquatroforasdiferentesdealcanabilidade; inalcanvel(unreachable):nopodeseracessadopornenhummeioeest elegvelremoo; alcanvel por finalizador (finalizerreachable): um objeto quase inalcanvel,poisnopodeseralcanadoatravsdasviasnormais.Pode ser ressuscitado se, aps a morte, seu finalizador passar sua referncia thisparaalgumobjetoalcanvel. Ehtrsestadosemqueafinalizaodeumobjetopodeseencontrar: nofinalizado(unfinalized):nuncateveseufinalizadorchamado; finalizado(finalized):jteveseufinalizadorchamado;

2005HelderdaRocha

68

ArgoNavisJ281

GernciadememriaemJava

finalizvel (finalizable): seu finalizador pode chamlo automaticamente a qualquermomento.umobjetoquenomaisalcanvel. Odiagramadafigura53mostraatransioentreestadosduranteavidade um objeto. Se um objeto no tem finalizador explcito, o diagrama tem apenas dois estados de alcanabilidade: alcanvel e inalcanvel, e um estado de finalizao:nofinalizado.

Figura53Transioentreestadosdefinalizaoedealcanabilidade.Odiagramanolevaemcontaa existnciaderefernciasfracas.

Ressurreio de objetos
Umobjetofinalizerreachablenotemmaisrefernciasentreosobjetosvivos, mas,durantesuafinalizaopodecopiarsuarefernciathisparaumareferncia ativa. O objeto poder ento ser alcanado por referncias externas, e assim volta vida. Nesse estado, se morrer outra vez, vai direto ao estado unreachable e no passa mais pelo mtodo finalize() j que esse mtodo s executadoumavez. Considere as duas classes abaixo. HauntedHouse (casa malassombrada) permite acomodar um nico Guest (visitante). H mtodos para aceitar um visitanteeparamatlo:

public class HauntedHouse { private Guest guest; public void addGuest(Guest g) { guest = g; } public void killGuest() { guest = null; } }

2005HelderdaRocha

69

ArgoNavisJ281

GernciadememriaemJava

O visitante, por sua vez, possui uma referncia para HauntedHouse, que passada na sua criao. O construtor a sua prpria referncia (this) como argumentodomtodoaddGuest()daHauntedHouse.
public class Guest { private HauntedHouse home; Guest(HauntedHouse h) { home = h; home.addGuest(this); } protected void finalize() ... { home.addGuest(this); } }

Para executar, criamos uma instncia de HauntedHouse para passar como argumento do construtor na criao de um Guest. No guardamos uma referncia externa para o Guest, de forma que a nica referncia a mantida dentrodeHauntedHouse.
HauntedHouse h = new HauntedHouse(); new Guest(h); // cria objeto e mantm referencia em h

Ao chamar killGuest() na tentativa de livrarse da visita inoportuna, HauntedHouse destri a ltima e nica referncia restante de Guest, deixandoo candidato coleta de lixo. Porm, antes do objeto ser coletado, seu finalizador ser executado, e quando isto acontecer, a referncia this mais uma vez ser obtida e passada ao mtodo addGuest(), causando a resssurreio do objeto j dadocomomorto.
h.killGuest(); // mata objeto e finaliza, mas ele ressuscita!

O nico jeito de livrarse do fantasma matar o objeto de novo. Como a finalizao s ocorre uma vez, no h risco do objeto ressuscitar outra vez atravsdofinalizador.
h.killGuest(); // mata objeto de novo... desta vez ele vai

Osexemplosmostradossobreressurreiodeobjetostmfinalidadedidtica e foram usados para facilitar o entendimento do processo de finalizao. Mas acordar os mortos geralmente no uma boa idia. A ressurreio de objetos raramente tem aplicaes prticas e geralmente uma prtica a ser evitada, portanto, no ressuscite objetos. Os problemas que sugerem a ressurreio de objetoscomosoluogeralmentepodemsermelhorimplementadascomnovos objetosecpiadeseusestados(clonagem,porexemplo).Almdisso,objetosde referncia permitem prticas envolvendo finalizao que so mais seguras e previsveisparaproblemassimilares.

Como escrever finalize()


O mtodo finalize() opcional. Objetos que no tenham declarado finalizadoresexplcitos,noserofinalizadoseirodiretoparaolixo,portanto, usefinalizaoautomticaapenassefornecessrio.

2005HelderdaRocha

70

ArgoNavisJ281

GernciadememriaemJava

Se precisar mesmo usar um finalizador, ento escrevao corretamente. Construtores automaticamente chamam a sua superclasse, mas finalizadores no chamam automaticamente os finalizadores das superclasses. A correta implementao deve sempre chamar super.finalize() explicitamente, de prefernciaemumblocofinallyparagarantirsuaexecuo:
protected void finalize() throws Throwable { try { // cdigo de finalizao } finally { super.finalize(); } }

O trecho acima a tcnica padro para escrever finalize(). Excees no devemsercapturadasdentrodosfinalizadores,jquenoseroteisepodero atrasarafinalizao. A finalizao uma operao que s ocorre se houver coleta de lixo, portanto, para demonstrla, criaremos um programa intil cuja principal finalidadeserocuparmemriaparaforaracoletadelixo. Considere a classe e o trecho de cdigo a seguir, executado com pouca memria(1megabytedeheap)paragarantirumacoletadelixomaisfreqente. Os objetos usam refernciasfracas20 para que sejam liberados com freqncia. O construtor,omtodofinalize()eoblocofinallyfazemcontagemdechamadas.
public class FinalizingObject { private int[] state; public FinalizingObject(String state) { this.state = new int[1000]; creationCount++; } public void finalize() throws Throwable { finalizationCount++; super.finalize(); } } ... WeakHashMap fp = new WeakHashMap(); for (int i = 0; i < 1000; i++) { try { fp.put(-i, new FinalizingObject()); } finally { ++finallyCount; } } ...

Pergunta: quanto deve ser a contagem de cada um, se mil objetos forem criadosedepoisdestrudos?Oforacimairalocarmilentradasnomapafp,mas

20

Refernciasfracasseroabordadasmaisadiantenestetutorial.

2005HelderdaRocha

71

ArgoNavisJ281

GernciadememriaemJava

se a memria acabar, ela ser recuperada pois o WeakHashMap ir liberar suas refernciasautomticamenteemcasodememriaescassa. A execuo, com verbose:gc e heap limitado a 1 megabyte produziu os seguintesresultados:
> java -Xmx1M Xms1M -verbosegc -cp build/classes memorylab.Main ... [Criados agora: 200; total criados: 1000] [Finalizados agora: 83; total finalizados: 670]

Construtorfoiexecutado1000vezes. Blocofinallyfoiexecutado1000vezes. Finalizadorfoiexecutado670vezes. Observe que a mquina virtual terminou antes que todos os finalizadores fossem executados. Se havia 1000 objetos, era de se esperar que houvesse 1000 finalizaes.Masnemtodososobjetosforamcoletados. Seamemriaforaumentada,tudomuda:
> java Xmx8M Xms8M -verbosegc -cp build/classes memorylab.Main ... [Finalizados agora: 0; total finalizados: 0] [Criados agora: 1000; total criados: 1000]

Construtorfoiexecutado1000vezes. Blocofinallyfoiexecutado1000vezes. Finalizadorfoiexecutado0vezes. Nenhum objeto foi finalizado! Por que? Simples: no foi necessria a execuo docoletordelixo.Osobjetosnoforamcoletados. Concluso: no dependa da finalizao! Nunca dependa de uma chamada automtica a finalize(). Uma aplicao em ambiente com muita memria pode nunca chamar os finalize() dos objetos que perderam suas referncias, e assim deixar de executar cdigo importante. A mesma aplicao em um ambiente igual mas com menos memria faria chamadas ao finalize() de vrios objetos. Parafinalize()serchamado,necessrioqueoobjetoestejaprestesasercoletado. Se objetos so criados e suas referncias so sempre alcanveis, nunca sero finalizadosnemcoletados. O mtodo finalize()pode nunca ser chamado por no haver necessidade de rodar o coletor de lixo (em coleta completa), no haver necessidade de reusar sua memria, ou outras razes dependentes de implementao/plataforma. Alm dessa desvantagem, os finalizadores automticos tambm podem contribuirparaoconsumodememriaebaixaperformance,nosoprevisveis, funcionam diferentemente entre plataformas e ignoram excees. Nem o comandoSystem.gc()quechamaocoletordelixogaranteaexecuodeum finalizador.Porqueusarumfinalizador,ento? Finalizadoressoimportantes!Nofinalizadoresautomticos,comofinalize(), masfinalizadoresexplcitos!Finalizadoressoquaisquermtodosqueajudama encerrar o uso de um objeto. A finalizao de arquivos, soquetes, e outros

2005HelderdaRocha

72

ArgoNavisJ281

GernciadememriaemJava

recursosnorelacionadosliberaodememrianoserofeitaspelosistema de coleta de lixo e tm que ser realizadas pelo programador. Por serem to importantes, no devem depender da finalizao automtica do sistema atravs de finalize(), mas devem estar presentes atravs de mtodos de finalizao explcita! File.close(), Socket.close(), Window.dispose(), Statement.close() e outros mtodos existentes nas APIs Java so mtodos de finalizao explcita. Devem ser chamados pelo cliente geralmente em um bloco tryfinally para garantir sua execuo. Isto implica em uma mudana na atribuio de responsabilidades: a finalizaodeumrecursoapsoseuusoumaresponsabilidadedoclienteda API,enodoseuautor. Mtodosdefinalizaoexplcitapodemtambmserchamadosporfinalize() como uma rededesegurana, caso o cliente esquea de finalizar. A maioria dos mtodos de finalizao explcita da API Java usa finalize() como rede de segurana para liberar recursos de qualquer maneira, mesmo que o usurio cliente no tenha chamado o mtodo de finalizao. Eventualmente, quando a memria acabar, finalize() ser chamado e recursos que o usurio esqueceu de finalizarpoderoserrecuperados. Um exemplo de classe usando finalize() como rede de segurana est mostradoaseguir:
class Cache { ... Thread queueManager; void init() { Runnable manager = new Runnable() { public void run() { while(!done) { try { blockingOperation(); } catch (InterruptedException e) { done = true; return; } } } }; queueManager = new Thread(manager); queueManager.start(); } public void close() { // FINALIZADOR EXPLCITO done = true; if(!queueManager.isInterrupted()) queueManager.interrupt(); } protected void finalize() throws Throwable { // FINALIZADOR AUTOMTICO try { close(); } finally { super.finalize(); } } }

AformacorretadeusaraclasseCache:

2005HelderdaRocha

73

ArgoNavisJ281

GernciadememriaemJava

Cache c = new Cache(); try { c.init(); // usar o cache } finally { c.close(); }

Se o cliente esquecer de chamar close(), existe a possibilidade do Cache ser liberado se a memria acabar e o coletor de lixo for chamado. Se isto no acontecer,oCachenoserfinalizado.

Finalizer Guardian
Havendo necessidade de implementar finalize(), preciso implementlo corretamente. O que fazer se o cliente que sobrepe a classe no implementar corretamente finalize(), esquecendo, por exemplo. de chamar super.finalize()? PodeseusaropadroFinalizerGuardianparagarantirqueofinalizadordeuma superclasseserchamadoquandooobjetodeumasubclasseforfinalizado. OFinalizerGuardianumatributodoobjetoprotegidoquefuncionaporque antes de um objeto ter sua memria liberada, seus atributos sero liberados (e finalizados se preciso). um objeto que implementa seu prprio finalize() com uma chamada ao finalize() da classe que o contm (e guarda). Protege contra implementaoincorretadefinalize()porpartedassubclasses. O cdigo abaixo ilustra o uso do padro Finalizer Guardian implementado comoumaclasseinterna.
public class Recurso { ... private final Object guardian = new Object() { protected void finalize() throws Throwable { Frase.this.close(); // finaliza Recurso } }; public void finalize() throws Throwable { try { close(); // chama finalizador explcito } finally { super.finalize(); } } public void close() throws Throwable { // finalizao explcita } }

(Fonte:JoshuaBloch,EffectiveJava,Item6)

Finalizao de threads
A Interface Thread.UncaughtExceptionHandler 21 , usada para lidar com exceesquenoforamcapturadas.umainterfaceinternadaclasseThread:
21

EmversesanterioresaJava1.5,useThreadGroup.uncaughtException()

2005HelderdaRocha

74

ArgoNavisJ281

GernciadememriaemJava

public class Thread ... { ... public interface UncaughtExceptionHandler { void uncaughtException(Thread t, Throwable e); } }

Podese implementar a interface com cdigo a ser executado antes que o threadterminedevidoaumaexceonocapturada.
public static void main(String args[]) { Thread.UncaughtExceptionHandler handler = new Thread.UncaughtExceptionHandler () { void uncaughtException(Thread t, Throwable e) { // fazer finalizao } }; Thread.currentThread().setUncaughtExceptionHandler(handler); // segue cdigo que pode causar exceo }

Como tornar um objeto elegvel remoo pela coleta de lixo?


Apara que um objeto seja coletado, preciso primeiro que se torne inalcanvel.Istofeitoeliminandotodasassuasrefernciasapartirdosnsraiz dothreadprincipal(variveislocaiseestticas). Declarar a ltima referncia como null tornao inalcanvel imediatamente(oufinalizerreachable,setiverfinalizador). Atribuir outro objeto ltima referncia do objeto no o torna imediatamente inalcanvel (porm atuais implementaes de JVMs garantemomesmoefeitoquenull). Objetos criados dentro de um mtodo tornamse inalcanveis pouco depois que o mtodo termina. No basta sair do escopo de um bloco. precisosairdoescopodomtodo. importante garantir que no haja outras referncias para o objeto. comumesquecerrefernciasativasemlistasdeeventhandlersecolees.Esses sooscasosmaiscomunsdememoryleak. Chamar o mtodo System.gc() aps eliminar todas as referncias para um objeto pode liberar a memria dos objetos inalcanveis. System.gc() executa o garbagecollectorassimquepossvel.SugereJVMqueelafaaumesforopara reciclar objetos no utilizados, para liberar a memria que ocupam para que possa ser reusada, porm existe um nvel de incerteza associado execuo desse comando. A execuo pode no acontecer imediatamente ou nunca se o programapodeterminarantes. UmachamadaaSystem.gc()tambmnogarantiraliberaodememriade todos os objetos inalcanveis. Os algoritmos de coleta de lixo podem, para aumentaraeficincia,deixarderecolhertodososobjetosencontradoscomolixo que sero recolhidos em coletas posteriores. Podese resolver esse problema chamandoSystem.gc()vriasvezesatqueamemriaparedediminuir.

2005HelderdaRocha

75

ArgoNavisJ281

GernciadememriaemJava

Podese descobrir se a memria parou de diminuir usando o mtodo freeMemory()daclasseRuntime:


Runtime rt = Runtime.getRuntime(); do { long memLivreAntes = rt.freeMemory(); System.gc(); long memLivreDepois = rt.freeMemory(); while (memLivreAntes != memLivreDepois);

Chamar System.gc() repetidamente muito ineficiente e s deve ser usado em casosextremos.intilsenohouverobjetosdisponveisremoo.Oideal encontrar estratgias que no precisem chamar System.gc(), exceto em raros casoseparadepurao. UmmtodoassociadoSystem.runFinalization(),queexecutaafinalizaode mtodos de quaisquer objetos cuja finalizao ainda no foi feita. Isto s aconteceseobjetojforcandidatoliberaoatravsdocoletordelixo(sefor finalizable).UmachamadaaSystem.runFinalization()sugeremquinavirtualque realizeomelhoresforoparaexecutarosmtodosfinalize()deobjetosqueesto marcados para remoo, mas cujos mtodos de finalizao ainda no foram executados. Este mtodo ainda menos previsvel que System.gc(). O antigo mtodo System.runFinalizersOnExit()onicoquegaranteaexecuodosfinalizadores, masinseguroefoideprecado. O trecho de cdigo abaixo fora o coletor de lixo como meio de garantir a finalizao de um objeto. O bloco finalize() imprime o seu nome passado no construtorparaquepossamossaberqualobjetofinalizou.
public static void main(String[] args) { System.out.println("Creating object..."); Citacao cit = new Citacao("Primeiro objeto..."); cit = null; System.out.println("Forcing GC..."); System.gc(); cit = new Citacao("Segundo!"); cit = null; System.out.println("Forcing GC again..."); System.gc(); System.out.println("Done"); }

Naexecuo,apenasaprimeirafinalizaoocorreu22.
Creating object... Forcing GC... Forcing GC again... finalize(): Primeiro objeto...; Done

Na minha mquina! Na sua pode funcionar diferente. O comportamento dependente da plataformaeimplementaodaJVM


22

2005HelderdaRocha

76

ArgoNavisJ281

GernciadememriaemJava

Se o finalizador realizasse alguma tarefa crtica, como por exemplo, o fechamento de arquivos, e a aplicao continuasse por mais tempo, esses arquivos ficariam bloqueados usando recursos da mquina. Portanto, mesmo usandoSystem.gc()nohcomogarantiraexecuodosfinalizadores.

Resumo
Na API e linguagem Java, as alternativas que o programador possui para chamarouinduziracoletadelixoso: System.gc():chamaogarbagecollectorassimquepossvel,masselimina objetos que j estiverem inalcanveis. ineficiente, pois pra o sistema para remover os objetos, e tem comportamento dependente da mquina virtual. Runtime.getRuntime().gc():fazomesmoqueSystem.gc(). ref=null:declararaltimarefernciaparaumobjetocomonull,vaitorn loelegvelcoletadelixo(estadoinalcanveloufinalizerreachable).mais rpido que reutilizar a referncia, ou fechar o bloco do mtodo onde o objetofoideclarado. Referncias fracas: permitem um controle mais eficiente; sero abordadas maisadiante.

2005HelderdaRocha

77

ArgoNavisJ281

GernciadememriaemJava

12. Memory leaks


Umvazamentodememria,oumemoryleak,nosentidoC++,ocorrequando umobjetonopodeseralcanadoenoliberadoatravsdacoletadelixo.Isto nopodeocorreremaplicaes100%Java23. Memoryleaks em Java so considerados em um sentido mais abrangente. considerado um memory leak um objeto que no coletado depois que no mais necessrio. Apesar de no serem mais usados, no so liberados porque ainda so alcanveis. Uma interface que impede ou que no garante que o clienteirliberarumarefernciadepoisdousotempotencialparamemoryleak. Jquebaseiasenoperodoemqueumobjetotil,ocritrioparadefinirum memory leak nem sempre muito claro: pode ser subjetivo, depender de um contextoouaindadealgumevento,porexemplo:ofatodamemriaestarsendo consumidamuitorapidamente,ouumOutOfMemoryError. Considereaclasseabaixo24.umapilhacommtodopop()parainserirdados epush()paraextrair.PossuiummtodoensureCapacity()queaumentaotamanho dapilhacasosejanecessrio.Halgumproblemacomestaclasse?
public class BadStack { // no thread-safe! private Object[] elements; private int size = 0; public BadStack(int initialCapacity) { this.elements = new Object[initialCapacity]; } public void push(Object e) { ensureCapacity(); elements[size++] = e; } public Object pop() { if (size == 0) throw new EmptyStackException(); return elements[--size]; } public int size() { return size; } private void ensureCapacity() { if (elements.length == size) { Object[] oldElements = elements; elements = new Object[2 * elements.length + 1]; System.arraycopy(oldElements, 0, elements, 0, size); } } }

Para testla, escrevemos um programa que cria duas pilhas e transfere objetosdeumaparaaoutra:
BadStack res = new BadStack(1000); BadStack src = new BadStack(1000); for (int i = 0; i < 1000; i++) src.push(new Character((char)((Math.random()*26) + 'A')));

23

Seacontecerbugnamquinavirtual,oquenoresponsabilidadedoprogramador.

24Fonte:JoshuaBloch,EffectiveJava,Item5.

78

2005HelderdaRocha

ArgoNavisJ281

GernciadememriaemJava

System.out.println("ANTES"); // imprime src.size(), res.size() try { while(true) { char c = Character.toLowerCase( (Character)source.pop()); res.push(new Character(c)); } } catch (EmptyStackException e) {} System.out.println("DEPOIS"); // Imprime mesmas informaes

OprogramaimprimeosdadosdeANTESeDEPOIS:
ANTES src.size(): 1000 res.size(): 0 DEPOIS src.size(): 0 res.size(): 1000

(a) Figura54Situaoaparentedosarrayssourceeresults.

(b)

Aparentementeoprogramafuncionacorretamente,comomostramosdados eafigura54.Dopontodevistadousurio,umapilhafoiesvaziadaeaoutrafoi preenchida.Masnoqueserefereaocoletordelixo,os1000objetosdapilhaque foi esvaziada (src) continuam accessveis. Como a varivel est encapsulada, o usurio no consegue vla. Se imprimssemos tambm a contagem de objetos emsrc,teramos:
ANTES Instancias em src: 1000 Instancias em res: 0 DEPOIS Instancias em src: 1000 Instancias em res: 1000

Everamosquenaverdade,oresultadofinal,naverdade,odafigura55.

Figura55Situaorealdosarrayssourceeresults.

2005HelderdaRocha

79

ArgoNavisJ281

GernciadememriaemJava

Terminamos de usar o objeto, no entanto, ainda h 1000 instncias que podemseralcanadas!Elasnoterosuamemrialiberadapelocoletordelixo. Do ponto de vista funcional, porm, o programa est correto. Foi necessrio quebraroencapsulamentoparaobteressesdados. Paraconsertarovazamentotemosqueeliminarasrefernciasobsoletaspara objetos que o programa mantm. O vazamento poderia ser ainda maior se os objetos da pilha tivessem referncias para outros objetos, e assim por diante. PoderiaocorrerOutOfMemoryErroremumaexecuocurta. A forma mais simples de resolver o problema, eliminar a referncia, declarandoanull.
public Object pop() { if (size == 0) throw new EmptyStackException(); Object result = elements[--size]; elements[size] = null; return result; }

Como achar e consertar vazamentos?


Analise o cdigo. Procure os lugares mais provveis: colees, listeners, singletons,objetosatreladosacamposestticos.Desconfiedeobjetoscomlongo ciclodevidaemgeral. Teste,eforceacoletadelixoentretestcasesrepetidos.Exerciteumsegmento decdigoparaexaminaroheapedescobrirseeleestcrescendoirregularmente. Usegrafosderefernciadeobjetos. Use um profiler para achar objetos alcanveis que no deviam ser alcanveis: alguns usam cores para mostrar objetos muito usados e outros menosusadospresteatenotambmnosobjetospoucoutilizados. Finalmente,useferramentasdemonitorao.Ojconsole),porexemplo,traa grficosdoheapedesuasregies.Oconsumomdiodememriadevemanter seconstanteatravsdotempo,comomostraafigura56.

Figura56Programasemmemoryleaks.

2005HelderdaRocha

80

ArgoNavisJ281

GernciadememriaemJava

Se acontecer do grfico de consumo de memria crescer linearmente descontandoseascoletasdelixo,humvazamentodememria(figura57):

Figura57Programacommemoryleaks.

Para consertar o vazamento no adianta chamar System.gc(). Esse mtodo almdeterimpactonegativonaperformance(executaumacoletaemtodasas geraes)irobterseacoletaapenasdosobjetosinalcanveis,masmemoryleaks soobjetosalcanveis. preciso eliminar todas as referncias para o objeto. Procureas usando ferramentas,senecessrio.Alternativasparaeliminaoderefernciasincluem declarararefernciacomonullquandonoformaisusada.Masnoabusedessa alternativa.Oidealmanterasrefernciasnomenorescopopossvel(oescopo mnimodeveserodemtodo),oureutilizarareferncia. Uma outra soluo utilizar objetos de referncia para criar referncias fracas.Istoserdiscutidonaseoseguinte.

2005HelderdaRocha

81

ArgoNavisJ281

GernciadememriaemJava

13. Referncias fracas


Refernciasfracassoponteiroscujaligaocomoobjetoaoqualsereferem fraca:podeserperdidaaqualquermomento.Elaspermitemqueumprograma aponteparaumobjetosemimpedirsuaeventualcoleta,casosejanecessrio. O coletor de lixo considera os objetos que so alcanveis apenas via referncias fracas como objetos que podem ser removidos. A API de reference objects(java.lang.ref)ouobjetosderefernciapermitequeumprogramamantenha refernciasfracasparaquaisquerobjetos. Tpicasaplicaesparaessetipoderefernciaso: Programas que mantm muitosobjetos na memria, e no precisaria t lostodosdisponveisaqualquermomento; Programasqueusammuitosobjetosporumcurtoperodo; Programas que precisam realizar operaes de finalizao nos objetos e outrosobjetosassociadosantesdaliberao.

API dos objetos de referncia


Objetos de referncia so descendentes da classe java.lang.ref.Reference. A figura58ilustrasuahierarquia.

Figura58Hierarquiadosobjetosdereferncia.

A classe ReferenceQueue, como diz o nome, uma fila. Quando usada com WeakReference ou SoftReference possibilita o tratamento de eventos durante a mudana da alcanabilidade. Pode ser usada para realizar prfinalizao. Usada com PhantomReference para guardar objetos j finalizados para a realizaodetarefaspsfinalizao. SoftReference serve para implementar caches sensveis memria, que so esvaziadosapenasquandoamemriaestmuitoescassa.Refernciasdessetipo sobrevivemavriascoletasmassoperdidasquandoamquinavirtualprecisar demaismemriadoheap. WeakReferenceusadaparaimplementarmapasnosquaischavesouvalores podemserremovidosdoheapaqualquermomento.Refernciasdessetipono sobrevivemaumacoletadelixo. A classe PhantomReference representa objetos j finalizados que ainda no foram recolhidos. Serve para implementar aes de finalizao de uma forma mais flexvel que o mecanismo de finalizao automtico do Java, ou para realizartarefasadicionaisdepoisdafinalizao.

2005HelderdaRocha

82

ArgoNavisJ281

GernciadememriaemJava

Todasasclassesaceitamparmetrosdetipodesdeaverso5.0doJava,que encapsulaotipodoobjetoparaoqualmantmarefernciafraca.Esseobjeto chamado de objeto referente (referent). Todos os objetos de referncia possuem duasoperaesbsicas,quesoherdadasdaclasseReference<T>,ondeTotipo doreferente. Tget():retornaoobjetoreferente.Estemtodosobrepostoemtodasas subclassesparaproverocomportamentodistintodecadatipodeobjeto dereferncia. void clear() : elimina o objeto referente. Se o mtodo get() for chamado depoisdeumclear(),retornarnull. Almdasoperaesbsicas,hdoisoutrosmtodosusadospelocoletorde lixo para gerenciar filas de objetos de referncia. Esses mtodos requerem que umobjetoderefernciarecebaumReferenceQueuenomomentodacriao. boolean enqueue(): acrescenta este objeto de referncia fila no qual est registrado,setiversidoregistradoemumafilanomomentodacriao. booleanisEnqueued():retornatrueseesteobjetoestiversidoenfileiradona aoqualfoiregistrado.Ocoletordelixoautomaticamenteacrescentaum objetonasuafilaquandoclear()chamado.

Como usar objetos de referncia


A figura 59 ilustra como um objeto de referncia mantm uma referncia fracaparaumobjeto.

Figura59Usotpicodeumobjetodereferncia.

Inicialmente, o objeto deve ser criado da forma usual, atravs de uma referncia forte, chamada de temp na figura 59. Aps a criao do objeto, um objeto SoftReference criado (poderia ser WeakReference tambm) recebendo no momentodacriaoarefernciafortetempparaoobjetoreferente.
Objeto temp = new Objeto(); SoftReference<Objeto> forte = new SoftReference<Objeto>(temp);

Emseguida,eliminamostodasasrefernciasfortesquereferemseaoobjeto diretamente:
temp = null;

2005HelderdaRocha

83

ArgoNavisJ281

GernciadememriaemJava

Agora s temos uma referncia forte, e ela aponta para um objeto SoftReference.Nohmaisrefernciasfortesqueapontemdiretamenteaoobjeto criado.Anicaformadeobterainstncia quecriamosoobjetoreferente atravs da referncia forte para o objeto SoftReference, que est ligado a ele atravsdeumarefernciafraca. Para obter o e poder usar a instncia do objeto referente, utilizamos o mtodoget()25:
Objeto temp = forte.get();

Seoobjetojtiversidocoletado,ouseomtodoclear()tiversidochamado, get()retornarnull. Uma vez criada, uma referncia fraca imutvel. No pode apontar para outro objeto. Pode ser esvaziada chamando o mtodo clear() mas no pode ser reutilizada.

Alcanabilidade fraca e forte


Referncias fracas redefinem estados de alcanabilidade. Um objeto fortemente alcanvel (strongly reachable) quando, a partir do conjunto raiz de referncias,elealcanvelatravsdeumacorrentederefernciascomuns. Se a nicaforma de alcanar um objeto envolver a passagem por pelomenos uma referncia fraca, ele chamado informalmente de fracamente alcanvel (weakly reachable), como mostra a figura 60. Um objeto fracamente alcanvel umobjetoquepodetornarseinalcanvelaqualquermomento.

Figura60Objetosalcanveisapenasviaobjetosderefernciasofracamentealcanveis.

Casonoseutilizegenricos,necessriofazerocastparaconverterarefernciadevolvida pelomtodoget(),quedotipoObject.
25

2005HelderdaRocha

84

ArgoNavisJ281

GernciadememriaemJava

O termo fracamentealcanvel um termogenrico para qualquer referncia criadaatravsdassubclassesdeReference.Formalmente,aAPIdefinetrsnveis defora para a alcanabilidade fraca com base no uso das classes SoftReference, WeakReference,ouPhantomReference.

Fora da alcanabilidade
Objetospodemserclassificadosquantoforadasuaalcanabilidadeem Strongly reachable (fortemente alcanvel): objetos que tm referncias normaisequenoestoelegveiscoletadelixo; Softlyreachable (levemente alcanvel): objetos que so acessveis atravs de uma SoftReference e podem ser finalizados e coletados quando o coletordelixoprecisarliberarmemria; Weaklyreachable(fracamentealcanvel):objetosqueacessveisatravsde uma WeakReference e podem ser finalizados e coletados a qualquer momento(assimqueocorrerumacoletamenor). Phantomly reachable (alcanvel aps a finalizao): objetos acessveis atravsdeumaPhantomReference;soobjetosjfinalizadosqueesperam autorizaoparaqueoespaoqueocupamsejarecicladopelocoletorde lixo.OreferentedeumPhantomReferencenomaisutilizvel. Unreachable (inalcanvel): so objetos que no tm mais referncia algumaparaeles,equeserocoletados. Comobjetosdereferncia,odiagramadetransiodeestadosmostradona figura 53 precisa ser redesenhado para levar em conta os novos estados intermedirioscriadospelasrefernciasfracas.Essediagramaestmostradona figura61.

Figura61Transiodeestadoscomobjetosdereferncia.Comparecomafigura53.

2005HelderdaRocha

85

ArgoNavisJ281

GernciadememriaemJava

SoftReference e WeakReference
Essas duas classes so estratgias muito similares. Elas diferem apenas na forma do tratamento recebido pelo coletor de lixo. O coletor de lixo sempre coleta objetos fracamente acessveis via WeakReference, mas s coleta objetos fracamente acessveis via SoftReference quando no houver mais como alocar memria sem removlo. Em ambos os casos, os objetos mais antigos so removidos primeiro, embora isto no faa diferena no caso dos objetos referenciadosviaWeakReference. Atabela4comparaasduasestratgias. WeakReference SoftReference

Mantm referncia para objetos ativos Mantm referncia para objetos ativos desde somente enquanto estiverem em uso que haja memria suficiente, mesmo que no (alcanveis, tendo uma referncia forte). estejam em uso. O coletor de lixo poder liberar objetos que s O coletor de lixo s ter que liberar objetos que tenham referncias desse tipo a qualquer s tenham referncias desse tipo antes de momento (sempre que executar.) lanar um OutOfMemoryError. O coletor de lixo no toma decises antes de O algoritmo do coletor de lixo obedece a uma liberar a memria usada por seus referentes. poltica de liberao de de seus referentes. Se o coletor rodar e houver WeakReferences, O coletor de lixo s remove SoftReferences se seus referentes sero removidos. no tiver outra opo. Use para objetos que tm vida curta: cliente Use quando existir a possibilidade do cliente decide reaver objeto logo ou no volta mais. voltar e tentar reaver objeto aps algum tempo.
Tabela4ComparaoentreSoftReferenceeWeakReference

PodeseajustarapolticadeliberaodamemriaocupadaporSoftReferences quandoa memriaestivernofim,atravsdeopesdisponveisemmquinas virtuaisHotSpot,daSunapartirdaverso5.0.Aopo


-XX:SoftRefLRUPolicyMSPerMB=taxa

Ataxaovaloremmilissegundospormegabytedoheapnaqualamquina virtual remove referentes acessveis via SoftReference quando necessrio. A HotSpot Client VM considera o valor relativo ao tamanho atual (utilizado) do heap, e a HotSpot Server VM considera o valor relativo ao heap mximo (parmetroXmx).Porexemplo,achamada:
java -XX:SoftRefLRUPolicyMSPerMB=1000 ...

configura a mquina virtual para que referentes fracamente acessveis via SoftReference, usados h mais tempo (LRU = Least Recently Used) durem pelo menosumsegundoparacadamegabytelivre.Sehouver60megabyteslivres,a liberaoseradiadaumminuto. O exemplo abaixo mostra uma pilha cujos objetos so guardados em WeakReferences.Amanutenodasrefernciasderesponsabilidadedocliente, uma vez que na primeira coleta de lixo os dados guardados no estaro mais

2005HelderdaRocha

86

ArgoNavisJ281

GernciadememriaemJava

disponveis.Ouseja,depoisqueasrefernciasdoclienteforemperdidas(depois dopush),existeapossibilidadedeperdadedados.
public class VolatileStack { // no thread-safe! private Reference[] elements; private int size = 0; public VolatileStack(int initialCapacity) { this.elements = new Reference[initialCapacity]; } public void push(Object e) { ensureCapacity(); elements[size++] = new WeakReference(e); } public Object pop() { if (size == 0) throw new EmptyStackException(); Reference ref = elements[--size]; return ref.get(); // pode retornar null!! } public int size() { return size; } private void ensureCapacity() { ... } }

Uma implementao mais segura seria usando SoftReferences. Com eles, objetos duram muito mais, embora ainda dependam do cliente e do coletor de lixo.Nestecaso,mesmoqueoclientepercaasreferncias,oselementosssero coletadossefaltarmemria,eosmaisnovosseroosltimos.
public class LessVolatileStack { // no thread-safe! private Reference[] elements; private int size = 0; public LessVolatileStack(int initialCapacity) { this.elements = new Reference[initialCapacity]; } public void push(Object e) { ensureCapacity(); elements[size++] = new SoftReference(e); } public Object pop() { if (size == 0) throw new EmptyStackException(); Reference ref = elements[--size]; return ref.get(); } public int size() { return size; } private void ensureCapacity() { ... } }

SoftReferencessoaescolhaidealparacachespoismanteroumobjetoativoo mximo de tempo possvel. O exemplo abaixo ilustra a implementao de um cache que guarda os dados de arquivos lidos. Se o objeto no estiver mais disponvel,elesernovamentecarregadododisco.

2005HelderdaRocha

87

ArgoNavisJ281

GernciadememriaemJava

public class FileDataCache { private Map map = new HashMap();//<String, SoftReference<Object>> private Object getFromDisk (String fileName) { Object data = null; try { data = readFile(fileName); } catch (IOException e) { ... } map.put(fileName, new SoftReference(data)); return data; } public Object getFromCache(String fileName) { Reference ref = map.get(name); if (ref.get() == null) return getFromDisk(fileName); else return ref.get(); } private Object readFile(String fileName) throws IOException { ... } ... }

ReferenceQueue
A classe ReferenceQueue pode ser usada para responder a eventos causados pelacoletadeobjetosreferentes.ReferenceQueueimplementaumafiladeobjetos de referncia normalmente preenchida pelo coletor de lixo. A fila recebe uma refernciaweakousoftalgumtempodepoisdoreferentetornarseinalcanvel. Referncias phantom so adicionadas fila depois que o objeto referente foi finalizado. ReferenceQueuepodeserusadacomomecanismodenotificao,edeprou psfinalizao.semprepassadanacriaodoobjeto.
ReferenceQueue q = new ReferenceQueue(); Reference ref = new SoftReference(referent, q);

A classe ReferenceQueue<T> possui trs mtodos que fazem a mesma coisa: removemobjetosdafila.TodosretornamReference<T>. remove() e remove(long timeout): bloqueiam o thread no qual executam enquanto no houver elementos para retirar. Podem ser interrompidos (InterruptedException)atravsdeThread.interrupt(). poll(): retorna null enquanto no houver objetos na fila. Quando um referenteforcoletado,seuobjetoderefernciaaparecernafilaepoder serremovidoatravsdestemtodo. Os mtodos de ReferenceQueue no servem para recuperar o referente, pois quandoumobjetoderefernciacainafila,seureferentejfoicoletado,portanto umachamadaaomtodoget()emumobjetoderefernciaretiradodafilasempre retornanull. ReferenceQueue funciona de forma semelhante com WeakReference e SoftReference, mas bastante diferente se for usado com PhantomReference. As figuras62e63ilustramasdiferenas.

2005HelderdaRocha

88

ArgoNavisJ281

GernciadememriaemJava

Figura 62 Funcionamento de ReferenceQueue: com referncias Weak e Soft chamar clear(), coloca objetonafiladepoisdealgumtempo.

Figura 63 Funcionamento de ReferenceQueue: com referncias Phantom, o objeto nasce na fila; chamarclear()sobreoobjeto,tiraodafila.

O prximo exemplo usa ReferenceQueue para saber quando um objeto foi coletado em um mapa onde as chaves so Strings e os valores so objetos Reference. O thread remove entradas de um Map quando suas referncias weak tornamse inalcanveis. Se um objeto foi coletado, seu objeto Reference ser colocadonafila,ativandoomtodoremove()queretornaoReference.Oobjeto localizadonomapaeusadoparaacharsuachave,queremovida.
Map map = new HashMap(); // <String, Reference<Object>> ReferenceQueue queue = new ReferenceQueue(); Runnable queueThread = new Runnable() { public void run() { while(!done) { Reference ref = null; try { ref = queue.remove(); // blocks } catch (InterruptedException e) {done = true;} Set entries = map.entrySet(); for (Map.Entry entry: entries) { if(entry.getValue() == ref) { String key = entry.getKey(); key = null; map.remove(key); } // if } // for } // while } // run() }; new Thread(queueThread).start();

Finalizao com referencias fracas


Objetos de referncia podem ser usados como uma alternativa ou complemento finalizao atravs da captura de eventos de alcanabilidade usandoReferenceQueue.Duasalternativassopossveis:

2005HelderdaRocha

89

ArgoNavisJ281

GernciadememriaemJava

Prfinalizao, realizada quando a referncia do objeto estiver perdida, que pode ocorrer quando a memria estiver no limite (softreference) ou quandoocoletordelixoexecutar(weakreference); Psfinalizao, realizada depois que objeto estiver finalizado (phantom reference). Para implementar, a soluo padro criar um thread que use poll() ou remove()paradescobrirquandoumobjetoperdeusuarefernciafraca.Otrecho de cdigo abaixo cria um thread que chama um finalizador explcito quando o objetoobj(ouqualqueroutroqueestivernafila)forcoletado.
Runnable finalizer = new Runnable() { public void run() { while(q.poll() == null) { // espera que objeto aparea try {Thread.sleep(32);} catch(...) {} } close(); // finalizao } }; new Thread(finalizer).start(); ReferenceQueue q = new ReferenceQueue(); Reference ref = new WeakReference(obj, q);

Podesetambmtercontroleadicionalsobrealiberaode memria usando referncias encadeadas e suas regras de precedncia. Por exemplo, a figura 64 ilustra um objeto com dois caminhos passando por referncias fracas: #ref2 uma WeakReferencee#ref3,umaSoftReference. Enquantoexistir#ref3,oobjetosertratadocomolevemente (softly) acessvel e s ser removido se faltar memria. Mas se #ref3 for perdida, o nico caminho para Objeto1 fracamente acessvelvia#ref2,podendoserremovidoaqualquermomento. Em um nico caminho, contendo uma srie de referncias interligadas,arefernciamaisfracadeterminaaalcanabilidade do objeto. Se houver vrios caminhos paralelos de referncias Figura64 encadeadas em srie para um objeto, sua alcanabilidade determinadapelocaminhomaisfortequehouver.Istoilustradonafigura65. Nafigura,comoObjeto2possuiapenasumcaminho:via#ref1,areferncia maisfracaqueirdeterminarsuaalcanabilidade,quephantomlyreachable. J o Objeto1 possui dois caminhos: um passando por uma Weak Reference (#ref2), e outro passando por uma Soft Reference (#ref3). Prevalece o caminho maisforte(#ref3)eoobjetosoftlyreachable. Finalmente o Objeto3 fortemente acessvel pois dois seus dois caminhos, umdeles(#ref4)nopassapornenhumobjetodereferncia.Se#ref4forperdida, oobjetoaindaserfracamenteacessvelatravsdareferncia#ref5.

2005HelderdaRocha

90

ArgoNavisJ281

GernciadememriaemJava

Emaplicaestpicas,refernciasfracassousadasde forma bem mais simples. No comum encontrar programas usando vrias referncias de tipos diferentes encadeadas. O processamento do objeto durante uma coleta de lixo realizado sempre pelo caminho mais forte e acontecenaordemabaixo: 1. 2. 3. 4. 5. Softreferences Weakreferences Finalizaodeobjetos Phantomreferences Liberaodememria

Nohgarantiadequandooprocessamentoemcada Figura65 etapa ir ocorrer, j que tanto a liberao de memria quanto a finalizao de objetos dependem de agendamento prprio do algoritmo de coleta de lixo, cuja ocorrncia e comportamento no so controlveisatravsdeprogramao.

Referncias fantasma
Objetos acessveis atravs de referncias do tipo PhantomReference j foram finalizados(seumtodofinalize()jfoichamado,seexistir)masaindanoforam liberados. Esto mortos. No podem mais ser usados e nem ressuscitados! Permitem,porm,dispararaarealizaodeoperaespsmorte,poispodemser identificadosatravsdesuasrefernciasfracas. Todo PhantomReference tem um ReferenceQueue. No h como criar um PhantomReference sem passar seu ReferenceQueue na construo. Fantasmas so colocadosnoseuReferenceQueuelogoquesetornamphantomlyreachable.Podese, ento,pesquisarafila,retirarosobjetosderefernciaqueforemseacumulando eatravsdelesidentificarosreferentesjmortos. PhantomReferencesnaverdadesequersoreferncias.Soapenasvestgios deumobjetofinado.Porm,precisoeliminaressesfantasmasdepoisqueno forem mais teis. Chamar clear() em um PhantomReference necessrio para retirao da fila e permitir que ele seja finalizado (o prprio fantasma, no o referentequejfinado).Omtodoclear()dePhantomReferencefazocontrrio declear()emWeakReferenceouSoftReference.Nosltimos,chamadoparapora referncianafilaenquantoqueemPhantomReferenceservepararetirladafila. A figura 63 ilustra este comportamento. Se clear() no for chamado, o PhantomReferencenuncaserretiradodafilaesuamemrianuncaserliberada, oquerepresentaummemoryleak. PhantomReferences podem ser usados como alternativa finalizao automtica, mas no h garantia uslos seja muito mais confivel que simplesmente usar finalize(), j que ainda dependem da finalizao e agendamentodeliberaodeobjetospelocoletordelixo.
2005HelderdaRocha 91

ArgoNavisJ281

GernciadememriaemJava

O trecho de cdigo abaixo mostra como poderia ser implementado um mecanismodefinalizaoautomticacomPhantomReferences:


ReferenceQueue q = new ReferenceQueue(); Reference ref = new PhantomReference(obj, q); Runnable finalizer = new Runnable() { public void run() { Reference ref = null; while( (ref = q.poll()) == null) { try {Thread.sleep(32);} catch(...) {} } ref.clear(); // libere o fantasma! close(); // finalize o objeto } }; new Thread(finalizer).start();

Depoisqueoobjetoreferenteobjestiverfinalizado,eleiraparecernafilaqe ser retornado pelo mtodo poll(). A linha ref.clear() necessrio para liberar a memria ocupada pelo fantasma. Em seguida, o mtodo de finalizao chamado. Neste outro exemplo26, retornamos casa malassombrada do captulo 11 e reescrevemosofinalizadorparaqueeleguardeumacpiaserializadadoobjeto morto para uma possvel ressurreio psfinalizao (uma mmia!). Assim, o morto, mesmo que no mais possa ressuscitar aps duas mortes, pode ser trazido de volta vida, quem sabe, uma terceira vez, na forma de uma cpia, duranteapsfinalizao. Primeiro, reescrevemos o finalizador (veja o original no captulo 11), que gravaumacpiadoobjetoem/tmp/mummy:
public class RessurectableGuest extends Guest { ... protected void finalize() ... { try { ObjectOutputStream mummy = new ObjectOutputStream( new FileOutputStream("/tmp/mummy")); mummy.writeObject(this); mummy.close(); } finally { super.finalize(); } } }

Depois, em uma aplicao usando PhantomReference, pesquisamos sua fila queueeesperamosqueofantasmaapareadepoisqudeoobjetoforfinalizado. Como a finalizao garantida antes que um PhantomReference aparea na fila, sabemos que ele deve ter sido serializado, ento procuramos o arquivo e criamosumanovacpiadoobjeto,quemaisumavezvoltavida.
26

Estemaisumexemplomeramenteeducativoparaexplicarofuncionamentodasreferncias fantasma.Notentefazeralgoparecidoemaplicaessrias.

2005HelderdaRocha

92

ArgoNavisJ281

GernciadememriaemJava

Reference found = queue.remove(); if (found != null) { // uma Reference foi encontrada! try { ObjectInputStream openMummy = new ObjectInputStream( new FileInputStream("/tmp/mummy")); Guest ressurected = (Guest)openMummy.readObject(); // objeto criado! hauntedHouse.addGuest(ressurrected); // volta casa! } catch (Exception e) {...}

WeakHashMap
Aclassejava.util.WeakHashMapaimplementaodeumjava.util.Maponde oparchave/valorumaWeakReference.umaclasseutilitriaqueimplementao uso mais comum de WeakReferences. A figura 66 ilustra a estrutura da classe WeakHashMap.

Figura66Hierarquiadeclassesassociadasclassejava.util.WeakHashMap.

Depois que o objeto referenciado pela chave fraca tornase fracamente alcanvel, o coletor de lixo pode limpar a referncia interna. A chave e seu valorassociadotornamseelegveisfinalizao. WeakHashMap a escolha ideal para mapas onde objetos podem ficar obsoletos rapidamente. Pode ser usado para implementar caches sensveis memria, listas de event handlers, etc. uma forma de evitar os memoryleaks mais comuns, porm h risco de perda de dados. Como usa WeakReferences, o coletor de lixo pode liberar sua memria a qualquer momento. Se houver um grande consumo de memria em outra parte da aplicao e isto causar coletas de lixo freqentes, as chaves do WeakHashMap sero continuamente perdidas. Devese considerar a construo de um SoftHashMap 27 se volatilidade do WeakHashMapforumproblema.
27

NoexisteSoftHashMapnaAPI.

2005HelderdaRocha

93

ArgoNavisJ281

GernciadememriaemJava

WeakHashMappodeserusadaemqualquerlugarqueseusaumHashMap.A aplicao abaixo, por exemplo, possui um memory leak. Ela no pra de acrescentar novos objetos em um HashMap, o que ir, eventualmente levar a ocorrnciadeumOutOfMemoryError.
public class MemoryLeak { public static void main(String[] args) { Map<Integer, String> map = new HashMap<Integer, String>(); int i = 0; while( true ) { String objeto = new String("ABCDEFGHIJKLMNOQRSTUVQWXYZ"); System.out.print("."); try {Thread.sleep(100);} catch (InterruptedException e) {} map.put(++i, objeto); } } }

fcil corrigir o memory leak. Simplesmente mudando o HashMap para WeakHashMap podese garantese que a memria no acabar por excesso de elementosnoHashMap.Adesvantagemqueseoutrosprocessoscausaremuma coleta de lixo, os objetos tambm sero perdidos (ser preciso incluir um mecanismoparagerenciaresserisco.)
public class FixedMemoryLeak { public static void main(String[] args) { WeakHashMap<Integer, String> map = new WeakHashMap<Integer, String>(); int i = 0; while( true ) { String objeto = new String("ABCDEFGHIJKLMNOQRSTUVQWXYZ"); System.out.print("."); try {Thread.sleep(100);} catch (InterruptedException e) {} map.put(++i, objeto); } } }

Concluses
AfinalizaoedestruiodeobjetosemJavacontroladaporalgoritmosde coletadelixo.possvelterumcontrolelimitadosobreocoletordelixousando finalizadores automticos, chamadas explcitas (System.gc) e objetos de referncia.Dastrsopes,objetosderefernciasoaqueoferecemaiscontrole. Htrsdiferentestiposdeobjetosdereferncia:WeakReference,queofereceuma ligao que se perde na primeira coleta de lixo, SoftReference, que dura pelo menosatqueamemriaacabe,ePhantomReference,quenoestmaisligadoao objetomaspermitearealizaodetarefasligadassuadestruio.Ostrstipos deobjetosderefernciapermitemconstruiraplicaesquegerenciamumpouco o uso de memria ao flexibilizar a ligao de objetos com suas referncias, e permitiracapturadeeventosligadosliberaodememriaefinalizao.

2005HelderdaRocha

94

ArgoNavisJ281

GernciadememriaemJava

Referncias

[Collins60]G.Collins.AMethodforOverlappingandErasureofLists,IBM,CACM,1960. Algoritmodecontagemdereferncias. [McCarthy 60] J. McCarthy. Recursive Functions of Symbolic Expressions and Their ComputationbyMachine,PartI,MIT,CACM,1960.ArtigooriginaldoMarkSweep algorithm(emLisp). [Edwards] D.J. Edwards. Lisp II Garbage Collector. MIT. AI Memo 19. ftp://publications.ai.mit.edu/aipublications/0499/AIM019.ps.MarkCompact. [Cheney70]C.J.Cheney.ANonrecursiveListCompactingAlgorithm.CACM,Nov1970. Artigooriginaldocopyingalgorithm. [Baker78]H.G.Baker.Listprocessinginrealtimeonaserialcomputer.CACM,Apr1978. Umaversoconcorrentedocopyingalgorithm. [LiebermanHewitt83]H.Lieberman,C.Hewitt.ARealTimeGarbageCollectorBasedon theLifetimesofObjects.CACM,June1983.ArtigoprincipaldoGenerationalGC. [Dijkstra76]E.W.Dijkstra,L.Lamport,etal.OntheflyGarbageCollection:AnExercisein Cooperation. Lecture Notes in Computer Science, Vol. 46. 1976. Tricolor marking (citadoem[Jones&Lins95]). [Bobrow 80] D. Bobrow. Managingreentrantstructuresusingreferencecounts.ACM/PLS, Jul1984.Contagemderefernciascomcoletadeciclos. [Ungar 84] David Ungar. Generation Scavenging: A Nondisruptlve High Performance StorageReclamationAlgorithm.ACM,1984.UmdosartigosdoGenerationalGC. [Hudson & Moss 92] R. Hudson, J.E.B. Moss. Incremental Collection of Mature Objects, ACM/IWMM,Sep1992.ArtigodoTrainalgorithm. [Domani00]T.Domanietal.AGenerationalOnTheFlyGarbageCollectorforJava,IBM2000. [Printezis 00] Tony Printezis and David Detlefs. A Generational Mostlyconcurrent GarbageCollector,2000.AlgoritmousadonoHotSpot. [Flood et al 02] Christine Flood et al. Parallel Garbage Collection for Shared Memory Multiprocessors.SunMicrosystems.Usenix,2001.AlgoritmosusadosnoHotSpot. [BaconRajan 01] D. Bacon, V. T. Rajan. ConcurrentCycleCollectioninReferenceCounted Systems.IBM,2001. [LevanoniPetrank01]Y.Levanoni,E.Petrank.AnOntheflyReferenceCountingGarbage CollectorforJava,IBM,2001. [Azatchi 03] H. Azatchi et al. AnOntheFlyMarkandSweepGarbageCollectorBasedon SlidingViews.OOPSLA03,ACM,2003. [Paz05]H.Pazetal.EfficientOntheFlyCycleCollection.IBM(Haifa),2005. [PazPetrankBlackburn 05] H. Paz, E. Petrank, S. Blackburn. AgeOriented Concurrent GarbageCollection,2005. [Memory]TheMemoryManagementReference.http://www.memorymanagement.org/.Vrias refernciasetextossobregernciadememriaemgeral. [JVMS] T. Lindholm, F. Yellin. TheJavaVirtualMachineSpecification,secondedition, Sun Microsystems,1999.Formatodememria,pilha,heap,registradoresnaJVM. [Sun 05] Sun Microsystems. Tuning Garbage Collection with the 5.0 Java[tm] Virtual Machine.2005.GenerationalGCeestratgiasparalelasnoHotSpot. [HotSpot]SunMicrosystems.TheJavaHotSpotVirtualMachine,v1.4.1,TechnicalWhite Paper.Sept.2002.AlgoritmosusadosnoHotSpot.

2005HelderdaRocha

95

ArgoNavisJ281

GernciadememriaemJava

[SDK]DocumentaodoJ2SDK5.0.SunMicrosystems,2005. [Apple04]JavaDevelopmentGuideforMacOSX.Apple,2004 [Printezis 05] Tony Printezis. Garbage Collection in the Java HotSpot Virtual Machine. http://www.devx.com/Java/Article/21977,DevX,2005. [Jones & Lins 96] R. Jones, R.Lins. GarbageCollection:AlgorithmsforAutomaticDynamic MemoryManagement.Wiley1996.VriasestratgiasdeGCexplicadas. [Venners] Bill Venners, Inside the Virtual Machine. Applet Heap of Fish: http://www.artima.com/insidejvm/applets/HeapOfFish.html [Gotry 02] K. Gottry. Pickupperformancewithgenerationalgarbagecollection. JavaWorld www.javaworld.com.Jan2002 [Gupta 02] A. Gupta, M. Doyle. Turbocharging Java HotSpot Virtual Machine, v1.4 to Improve the Performance and Scalability of Application Servers. Sun, 2002. http://java.sun.com/developer/technicalArticles/Programming/turbo [Nagarajayya02]N.Nagarajayya,J.S.Mayer.ImprovingJavaApplicationPerformanceand ScalabilitybyReducingGarbageCollectionTimesandSizingMemoryUsingJDK1.4.1. SunMicrosystems.Nov2002 [Holling03]G.Holling.J2SE1.4.1boostsgarbagecollection.JavaWorld.Mar2003. [Goetz 03] B. Goetz. Javatheoryandpractice:GarbagecollectionintheHotSpotJVM. IBM Developerworks.Nov2003. [Pawlan98]MonicaPawlan,ReferenceObjectsandGarbageCollection,SunMicrosystems, JDC, August 1998. Um tutorial abrangente sobre objetos de referncia. http://developer.java.sun.com/developer/technicalArticles/ALT/RefObj/ [Tate 02] [BJ] Bruce Tate, Bitter Java, Manning, 2002. Contm discusso interessante sobrememoryleaks. [Bloch 01] [EJ] Joshua Bloch, Effective Java, AddisonWesley, 2001. Contm padro finalizerguardian,discussosobrefinalizeememoryleaks. [Friesen 02] Trash Talk part 2: Reference Objects. JavaWorld, Jan 2002. http://www.javaworld.com/javaworld/jw012002/jw0104java101.html

www.argonavis.com.br

2005HelderdaRocha

96

Você também pode gostar