Memory Leak em Java?



Documentos relacionados
ARRAYS. Um array é um OBJETO que referencia (aponta) mais de um objeto ou armazena mais de um dado primitivo.

SUMÁRIO 1. AULA 6 ENDEREÇAMENTO IP:... 2

Implementando uma Classe e Criando Objetos a partir dela

PROGRAMAÇÃO ESTRUTURADA. CC 2º Período

Engenharia de Software III

Introdução a Java. Hélder Nunes

Análise e Desenvolvimento de Sistemas ADS Programação Orientada a Obejeto POO 3º Semestre AULA 03 - INTRODUÇÃO À PROGRAMAÇÃO ORIENTADA A OBJETO (POO)

PROGRAMAÇÃO ORIENTADA A OBJETOS -TRATAMENTO DE EXCEÇÕES. Prof. Angelo Augusto Frozza, M.Sc. frozza@ifc-camboriu.edu.br

INTRODUÇÃO ÀS LINGUAGENS DE PROGRAMAÇÃO

DAS5102 Fundamentos da Estrutura da Informação

Para criar uma animação precisamos de uma imagem e que ela contenha alguns frames. O número de frames é uma escolha sua.

Vamos fazer um mundo melhor?

Orientação a Objetos

Tabela de Símbolos. Análise Semântica A Tabela de Símbolos. Principais Operações. Estrutura da Tabela de Símbolos. Declarações 11/6/2008

Java 2 Standard Edition Como criar classes e objetos

CURSO DE PROGRAMAÇÃO EM JAVA

Bem- Vindo ao manual de instruções do ECO Editor de COnteúdo.

Especialização em desenvolvimento para web com interfaces ricas. Tratamento de exceções em Java Prof. Fabrízzio A. A. M. N. Soares

Desenvolvendo Websites com PHP

Persistência de Dados

INSTITUTO FEDERAL DE EDUCAÇÃO, CIÊNCIA E TECNOLOGIA DE ALAGOAS CURSO TECNICO EM INFORMATICA DISCIPLINA:

Tutorial de Active Directory Parte 3

Unidade IV: Ponteiros, Referências e Arrays

Manual do Ambiente Moodle para Professores

CONSIDERAÇÕES SOBRE USO DO SOFTWARE EDUCACIONAL FALANDO SOBRE... HISTÓRIA DO BRASIL EM AULA MINISTRADA EM LABORATÓRIO DE INFORMÁTICA

Coleções. Conceitos e Utilização Básica. c Professores de ALPRO I 05/2012. Faculdade de Informática PUCRS

ABCEducatio entrevista Sílvio Bock

Processos e Threads (partes I e II)

COMO INVESTIR PARA GANHAR DINHEIRO

Programação Orientada a Objetos Herança Técnico em Informática. Prof. Marcos André Pisching, M.Sc.

REGISTRANDO DOMÍNIOS, COMO PUBLICAR UM SITE? DIRECIONANDO O DNS. Professor Carlos Muniz

Curso: Desenvolvendo Jogos 2d Com C# E Microsoft XNA. Mostrar como funciona a programação orientada a objetos

PROGRAMAÇÃO ESTRUTURADA. CC 2º Período

2 echo "PHP e outros.";

Trabalho 7 Fila de prioridade usando heap para simulação de atendimento

Computadores XXI: Busca e execução Final

Pedro e Lucas estão sendo tratados com. Profilaxia

Excel Planilhas Eletrônicas

Prototype, um Design Patterns de Criação

EXERCÍCIOS SOBRE ORIENTAÇÃO A OBJETOS

Ebook Gratuito. 3 Ferramentas para Descobrir seu Verdadeiro Potencial

Linguagem de Programação III

Introdução à Linguagem Java

Web Design Aula 11: Site na Web

Você sabia. As garrafas de PET são 100% recicláveis. Associação Brasileira da Indústria do PET

UML Aspectos de projetos em Diagramas de classes

DESOCUPAÇÃO DE IMÓVEIS ARREMATADOS EM LEILÃO

Programação para Dispositivos Móveis

OCOMON PRIMEIROS PASSOS

Memória Virtual. Prof. Dr. José Luís Zem Prof. Dr. Renato Kraide Soffner Prof. Ms. Rossano Pablo Pinto

Arquitetura de Rede de Computadores

Plano de Aulas AutoCAD 2011

Universidade da Beira Interior. Sistemas Distribuídos

Dadas a base e a altura de um triangulo, determinar sua área.

INF1013 MODELAGEM DE SOFTWARE

Lazarus pelo SVN Linux/Windows

Programas operam sobre dados. Dados são relacionados e possuem estrutura. Como representar e manipular dados em um computador

NOKIA. Em destaque LEE FEINBERG

Imagens Mentais Por Alexandre Afonso

Entendendo como funciona o NAT

Chantilly, 17 de outubro de 2020.

1. Quem somos nós? A AGI Soluções nasceu em Belo Horizonte (BH), com a simples missão de entregar serviços de TI de forma rápida e com alta qualidade.

Programação por Objectos. Java

Tomada de Decisão uma arte a ser estudada Por: Arthur Diniz

Configurar o Furbot no Eclipse

Cadastramento de Computadores. Manual do Usuário

OI CONTA EMPRESA MANUAL DO USUÁRIO (exceto Administradores de Conta)

NO ABRIR DA MINHA BOCA (EFÉSIOS 6:19) USO DO POWERPOINT

Algoritmos. Objetivo principal: explicar que a mesma ação pode ser realizada de várias maneiras, e que às vezes umas são melhores que outras.

UNIVERSIDADE FEDERAL DO RIO GRANDE DO SUL INSTITUTO DE INFORMÁTICA INFORMÁTICA APLICADA

AULA 5 Sistemas Operacionais

V1.1 SITE EM UM SITE 11/2015 MINUTOS APRENDA A PROGRAMAR IMAGINE FAZER O SEU PRIMEIRO PROGRAMA EM 180 SEGUNDOS

Na tela dele, clique no sinal de + ao lado do nome do seu computador, para expandi-lo. A seguir, expanda também o item "Sites da web".

Manual Arkos Administrador

ALGORITMOS PARTE 01. Fabricio de Sousa Pinto

SISTEMA DE INFORMAÇÕES ACADÊMICAS SIA

Itinerários de Ônibus Relatório Final

Manual Administrador - Mídia System

- Versão 1.0 Página 1

Programação Orientada a Objetos Prof. Rone Ilídio UFSJ/CAP

O Guia Passo-a-Passo para IMPLANTAR. Em seu próprio Projeto

Governança de TI. ITIL v.2&3 parte 2

GUIA MUDANÇA E FORMATAÇÃO DE SERVIDOR - SLIM

DEFINIÇÃO DE MÉTODOS

Barra de ferramentas padrão. Barra de formatação. Barra de desenho Painel de Tarefas

10 Regras Para Ter Sucesso Com Negócios Digitais

GUIA MUDANÇA E FORMATAÇÃO DE SERVIDOR - MILLENNIUM

Curso de Instalação e Gestão de Redes Informáticas

CAPÍTULO 3 - TIPOS DE DADOS E IDENTIFICADORES

W W W. G U I A I N V E S T. C O M. B R

THREADS EM JAVA. George Gomes Cabral

OI CONTA EMPRESA MANUAL DO USUÁRIO

Transcrição:

1 Memory Leak em Java? Saiba como memory leaks se manifestam em Java e como evitá-los Sobre o Autor Carlos Eduardo G. Tosin (carlos@tosin.com.br) é formado em Ciência da Computação pela PUC-PR, pós-graduado em Desenvolvimento de Jogos de Computador pela Universidade Positivo e mestrando em Informática na área de Sistemas Distribuídos, também pela PUC-PR. Tem experiência de 5 anos em Java, tendo obtido as certificações SCJP, SCWCD, SCBCD e SCEA. Também possui as certificações SOA Certified (da IBM) e ITIL. Atualmente trabalha na IBM com desenvolvimento de sistemas em Java usados pela IBM no mundo todo. 1. Introdução Ao contrário do que muitas pessoas pensam, uma aplicação escrita em Java pode sim apresentar problemas de vazamento de memória, termo comumente conhecido por memory leak. Infelizmente, um grande número de programadores Java acha que memory leak é coisa de C/C++ e que o garbage collector do Java resolve esse problema completamente. Neste artigo pretendo mostrar que o garbage collector, apesar de ser funcionar muito bem, não é capaz de fazer mágica. 2. O que é Memory Leak Memory leak significa exatamente o que o seu nome diz: vazamento de memória. Ele pode ser de dois tipos: 1) Blocos de memória estão alocados e disponíveis para serem usados pela aplicação, mas não são acessíveis porque a aplicação não tem nenhum ponteiro 1 apontando para essa área de memória. Logo, estes blocos de memória não podem nem ser usados nem pela aplicação e nem por outros processos. 2) Blocos de memória possuem dados que poderiam ser liberados por serem inacessíveis e que, por esquecimento, ainda são referenciados no código mesmo sem estarem sendo usados, não podendo ser liberados. A situação 1 é muito comum em C/C++. Aloca-se uma quantidade de memória usando a função malloc 2, por exemplo, e na seqüência o programador faz com que o ponteiro para essa área de memória 1 Um ponteiro é uma variável que aponta para um endereço de memória. É um termo bastante comum em C/C++ e engana-se quem acha que Java não possui ponteiros. Quando um objeto é criado usando new, a variável que recebe o objeto é, na verdade, um ponteiro que aponta para um endereço de memória que contém o objeto. 2 A função malloc() faz parte da API do C. Sua função é alocar a quantidade de memória desejada (fornecida como parâmetro). O retorno desta função é um ponteiro para a área de memória recém criada.

2 passe a apontar para outro local, perdendo a referência inicial. Em Java este tipo de memory leak não ocorre, pois o garbage collector é capaz de detectar blocos de memória alocados e não referenciados e liberá-los para uso posterior. É na situação 2 que mora o problema. Mas antes de explicar como esse problema pode ocorrer e como evitá-lo, vamos entender um pouco mais como funciona o garbage collector do Java. 3. O Papel do Garbage Collector Uma das grandes vantagens do Java sobre linguagens de programação de mais baixo nível é a presença do garbage collector (coletor de lixo). A função do dele é vasculhar a memória atrás de blocos alocados que não tenham mais como ser referenciados pela aplicação. Quando o garbage collector se depara com uma situação desse tipo, ele desaloca a memória, tornando-a disponível para ser usada novamente pela aplicação. Ver o garbage collector funcionando no Java é muito fácil. Observe este código: public static void main(string[] args) throws Exception { int[] array = null; while(true) { array = new int[1000]; System.out.println("Bytes livres: "+ Runtime.getRuntime().freeMemory()); Thread.sleep(200); Este código fica executando em um loop infinito. A cada iteração do loop, um array de 1000 posições de inteiros é criado. Cada vez que o loop é executado, é mostrada a quantidade de bytes livres. Num primeiro momento você pode pensar: esta aplicação vai acabar com a memória da JVM. Mas na verdade não é isso que acontece. Ao executar o programa, em determinado momento você vai observar a seguinte saída: Bytes livres: 1526504 Bytes livres: 1522488 Bytes livres: 1518472 Bytes livres: 1514456 Bytes livres: 1510440 Bytes livres: 1912792 Bytes livres: 1912792 Bytes livres: 1908776 Bytes livres: 1904760 Bytes livres: 1900744 Bytes livres: 1896728 Bytes livres: 1892712 A memória estava acabando e, repentinamente, ela aumentou. A explicação disso é simples. Quando o loop é executado, é criado o array. Na próxima iteração do loop, o array criado na iteração

3 anterior não é referenciado por mais ninguém (perceba que a variável array deixou de apontar para o array antigo e passou a apontar para o novo array, fazendo com que o array antigo ficasse inacessível). Em determinado momento, a JVM percebe a queda da memória disponível e coloca o garbage collector em execução. O garbage collector então descobre que essa memória que foi sendo alocada no decorrer dos loops está inacessível e a libera. É neste momento que podemos perceber que a memória disponível aumenta. Depois de ver este código rodando, você deve estar se perguntando: como eu sei quando o garbage collector vai ser executado?. Não é possível saber. O controle da execução do garbage collector é da JVM. Quando a JVM decidir que é hora de executá-lo, ele será executado. Note que executar o garbage collector toda hora não seria recomendável, já que ele ocupa recursos computacionais. Outro ponto importante a respeito do garbage collector é que, como ele é controlado pela JVM, não é possível forçar a sua execução via programação. O máximo que pode ser feito é a chamada do método System.gc() (ou Runtime.getRuntime().gc()). Este método notifica a JVM que a aplicação gostaria que o garbage collector fosse executado, mas não garante que ele realmente será executado no momento desejado. O método finalize() A classe Object do Java possui um método chamado finalize(), que pode ser sobrescrito pelas classes que herdam de Object (isto é, qualquer classe). Quando o garbage collector decide que determinado objeto será destruído por não ser mais referenciado, ele chama o método finalize() no objeto logo antes de destruí-lo. Apesar do método finalize() ser uma chance que o programador tem para liberar recursos associados ao objeto no momento em que ele será destruído, sobrescrever o finalize() não é recomendado em nenhuma situação. O motivo é simples: como não existe garantia que o objeto será destruído, também não existe garantia que o finalize() será executado. A própria Sun não recomenda sobrescrever o método finalize(). A liberação de recursos pode ser feita de outras formas, como utilização de blocos try/catch/finally e/ou criação de métodos específicos para este fim (método close(), por exemplo). Para mais informações sobre este tópico, consulte: http://java.sun.com/developer/techtips/2000/tt0124.html. 4. Causando um Memory Leak em Java Após o entendimento do que é um memory Leak e como funciona o garbage collector do Java, vamos agora mostrar como causar um memory leak em Java e o que fazer para evitá-lo. Primeiramente, gostaria de reforçar que memory leaks são difíceis de descobrir (às vezes é preciso recorrer a ferramentas externas) e sempre são causados por erro de programação. Normalmente os programadores não se preocupam muito com eles, até o momento em que começam a consumir uma quantidade excessiva de memória ou até derrubar a JVM (quando a memória acaba, a JVM lança um java.lang.outofmemoryerror e termina).

4 Comentei na seção 3 que o garbage collector é capaz de detectar objetos não-referenciados e destruí-los, liberando a memória. Para criar um memory leak basta manter a referência a um ou mais objetos no código, mesmo sem utilizá-la depois. Dessa forma o garbage collector nunca poderá destruir os objetos, e eles continuarão existindo na memória mesmo não sendo mais acessíveis. Observe este exemplo simples de implementação de uma pilha: public class Pilha { private List pilha = new ArrayList(); int count = 0; public void push(object obj) { pilha.add(count++, obj); public Object pop() { if(count == 0) { return null; return pilha.get(--count); Cada vez que um elemento é colocado ou removido da pilha, um contador controla a posição do último elemento. Este é um caso visível de memory leak. A pilha tem referências cadastradas para todos os objetos contidos nela. No entanto, por mais que os objetos sejam todos removidos da pilha, a pilha continuará referenciando os objetos removidos, o que impossibilitará o gargabe collector de recuperar esta memória. Para resolver a situação nesse caso, basta eliminar a referência ao objeto quando ele for removido da pilha: public class Pilha { private List pilha = new ArrayList(); int count = 0; public void push(object obj) { pilha.add(count++, obj); public Object pop() { if(count == 0) { return null; Object obj = pilha.get(--count); pilha.set(count, null); return obj; Atribuir a referência do objeto para null fará com que a pilha não mais referencie o objeto, possibilitando ao garbage collector a destruição do mesmo.

5 Este exemplo tem por objetivo mostrar como memory leak em Java é possível. É difícil alguém implementar uma pilha desta forma (ainda mais que Java já possui uma classe Stack para esta finalidade). De qualquer forma, imagine uma situação semelhante a essa onde milhares ou até milhões de objetos fiquem inacessíveis e ainda assim referenciados. Numa aplicação rodando sem parar num servidor de aplicação, por exemplo, isso pode acarretar o término da JVM por falta de memória após alguns dias de memory leaks acumulados. Numa situação como essa, encontrar o erro pode ser uma tarefa extremamente complicada e trabalhosa. 5. Recomendações para evitar memory leaks Acredite: seguir algumas recomendações para evitar os memory leaks é muito mais fácil do que detectá-los após o código ter sido finalizado. Como o garbage collector facilita bastante o trabalho do programador, basta prestar atenção em alguns pontos principais que são causas comuns de memory leaks: Cuidado com coleções de objetos (arrays, listas, maps, vectors, etc.). Às vezes elas podem guardar referências de objetos que não são mais necessários. Ainda relacionado às coleções de objetos, se as mesmas forem static ou durarem todo o tempo de vida da aplicação, o cuidado deve ser redobrado. Ao programar situações onde seja necessário registrar objetos como event listeners, tome o cuidado de remover os registros desses objetos caso não sejam mais necessários. Resumindo: elimine todas as referências a objetos desnecessários. Fazendo isso, o garbage collector terá condições de fazer o seu trabalho completamente e você estará livre dos memory leaks em suas aplicações. 6. Conclusão Este artigo procurou demonstrar que memory leaks existem em Java, ao contrário do que muitas pessoas pensam. Foi mostrado como criar uma situação de memory leak e como cuidar para que situações desse tipo sejam evitadas, a fim de não prejudicarem as aplicações.