Escolar Documentos
Profissional Documentos
Cultura Documentos
Tutorial Geren CIA Memoria Java
Tutorial Geren CIA Memoria Java
Tutorial
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
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)
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
Tutorial
ArgoNavisJ281
GernciadememriaemJava
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
2005HelderdaRocha
ArgoNavisJ281
GernciadememriaemJava
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.
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
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.
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
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
Figura16Objetosativosmarcadosporumalgoritmoderastreamento.
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.
2005HelderdaRocha
20
ArgoNavisJ281
GernciadememriaemJava
Oalgoritmoconsistededuasfases.Aprimeiraidnticaaomarksweep,que marca os objetos alcanveis. A fase seguinte move os objetos alcanveis sobreviventesparafrenteatqueamemriaqueelesocupamsejacontgua.O funcionamentodoalgoritmomarkcompactestilustradonafigura18apartirda compactaodoheap.
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.
2005HelderdaRocha
23
ArgoNavisJ281
GernciadememriaemJava
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.)
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
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.
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
Mecanismoquepodeserusadopeloprogramadorparainfluenciaracoletadelixo.
2005HelderdaRocha
34
ArgoNavisJ281
GernciadememriaemJava
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
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
2005HelderdaRocha
36
ArgoNavisJ281
GernciadememriaemJava
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
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.
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 ...
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]
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 ...
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
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.
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
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)
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
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].
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.
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
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]
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
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.
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
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
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
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.
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.
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
2005HelderdaRocha
64
ArgoNavisJ281
GernciadememriaemJava
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
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.
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
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 }
2005HelderdaRocha
75
ArgoNavisJ281
GernciadememriaemJava
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
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
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; }
Figura56Programasemmemoryleaks.
2005HelderdaRocha
80
ArgoNavisJ281
GernciadememriaemJava
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
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.
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.
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
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();
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
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