350 likes | 472 Views
Coleta de resíduos. Sumário. Resíduos Coleta de resíduos Contador de referências Marcação e varredura Parada e cópia Marcação e compactação Gerenciamento dinâmico de memória. Resíduo . Um objeto é uma instância de uma classe ou de um array
E N D
Sumário • Resíduos • Coleta de resíduos • Contador de referências • Marcação e varredura • Parada e cópia • Marcação e compactação • Gerenciamento dinâmico de memória
Resíduo • Um objeto é uma instância de uma classe ou de um array • Heap – região de memória onde os objetos são alocados dinamicamente (não é o heap árvore) • A memória alocada a cada objeto contém espaço para administração da memória
Resíduos • Programas contém objetos e referencias a objetos • Quando existem referencias a objetos que não mais existem ocorre um vazamento de memória • Objetos que não são mais referenciados são chamados de resíduos • O procedimento de Coleta de resíduos é invocado quando o total de memória alocada atinge determinado patamar • Usualmente o programa é suspenso enquanto se faz a coleta de resíduos • Para facilitar a coleta de resíduos deve-se atribuir null a toda variável referenciando objetos não mais necessários
Métodos de coleta de resíduos • Contador de referências • Marcação e varredura • Parada e cópia • Marcação e compactação
Método do Contador de Referências • Cada objeto possui um campo contador que armazena o número de ponteiros (internos e externos) que apontam para este objeto • Toda vez que o ponteiro para um objeto é atualizado os contadores de referências dos objetos para os quais o ponteiro apontava e passou a apontar são atualizados • Toda vez que o contador de referências de um objeto se torna nulo este objeto pode ser devolvido à coleção de objetos livres
Contador de referências Object p = new Integer (57); Object q = p; Object p = new Integer (57); Object q = new Integer (99); p=q;
Contador de referências • Implementações do contador de referências para p = q; if (p != q) { if (p != null) --p.refCount; p = q; if (p != null) ++p.refCount; } ou if (p != q) { if (p != null) if (--p.refCount == 0) heap.release (p); p = q; if (p != null) ++p.refCount; }
Contador de referências • Na referência a objetos que referenciam outros objetos o problema se complica • Quando o primeiro objeto receber valor null os objetos referenciados permanecerão como resíduos até o coletor de resíduos recolher o primeiro objeto
Contador de referências Object p = new Association (new Integer (57), new Integer (99));
Contador de referências • Referência circulares • Anula-se a lista mas os objetos permanecem referenciados
Método de Marcação e Varredura • Objetos não referenciados são marcados • A coleta de resíduos é feita posteriormente • Objetos referenciados diretamente por variáveis do programa são chamados de raízes (roots) • Objetos acessíveis indiretamente são ditos vivos • Demais objetos são resíduos • A marcação de objetos requer um atributo booleano marked
Método de Marcação e Varredura Algoritmo for each root variable r mark (r); sweep (); void mark (Object p) if (!p.marked) p.marked = true; for each Object q referenced by p mark (q); void sweep () for each Object p in the heap if (p.marked) p.marked = false else heap.release (p);
Método de Marcação e Varredura • Objetos são criados com marked false • O processo de marcação atribui true a marked para objetos acessívies ou vivos • O processo de varredura coleta os objetos com marked false e atribui false a marked dos objetos que permaneceram acessíveis
Método de Parada e Cópia • Fragmentação • A alocação e deslocação de memória, ou seja, a atribuição de trechos de memória a processos é feita em blocos de memória de tamanhos requisitados pelos respectivos processos • A natureza dinâmica dessas ocorrências faz com que, em geral a memória fique fragmentada intercalando blocos alocados e blocos livres • A fragmentação pode provocar a impossibilidade do atendimento de uma solicitação pela inexistência de um bloco livre no tamanho desejado muito embora o somatório das áreas livres fragmentadas supere o tamanho solicitado
Método de Parada e Cópia • No método de Parada e Cópia o heap é dividido em duas regiões • activeHeap • inactiveHeap • Considera-se disponível o espaço inactiveHeap entre o final do último bloco de memória alocado e o final da memória • Sempre que uma solicitação de memória ultrapassa o espaço disponível: • Interrompe-se o processamento • Objetos vivos são copiados da região ativa para a inativa • As regiões ativa e inativa trocam seus papéis • Verifica-se então a possibilidade de atendimento da solicitação
Método de Parada e Cópia • Algoritmo básico for each root variable r r = copy (r, inactiveHeap); swap (activeHeap, inactiveHeap);
Método de Parada e Cópia void Object copy (Object p, Heap destination) if (p == null) return null; if (p.forward == null) q = destination.newInstance (p.class); p.forward = q; for each field f in p if (f is a primitive type) q.f = p.f; else q.f = copy (p.f, destination); q.forward = null; return p.forward;
Método de Marcação e Compactação • A referência a objetos pode ser implementada por meio de manipuladores (“handles”) • Cada objeto tem seu handle • Handle contém • Referência a uma instância da classe do objeto • Ponteiro para região do heap aonde o objeto reside • Flag marked • Quando a posição do objeto no heap modifica é necessário apenas atualizar o ponteiro do handle pois todas as referências ao objeto são feitas ao handle
Método de Marcação e Compactação • Algoritmo básico for each root variable r mark (r); compact ();
Método de Marcação e Compactação • Algoritmos void mark (Object p) if (!handle[p].marked) handle[p].marked = true; for each Object q referenced by p mark (q); void compact () long offset = 0; for each Object p in the heap if (handle[p].marked) handle[p].object = heap.move (p, offset); handle[p].marked = false; offset += sizeof (p);
Gerenciamento dinâmico de memória • O processo de alocação de blocos de memória pode ser feito de diversas maneiras, tais como: • Primeiro ajuste • Melhor ajuste • Pior ajuste
Primeiro ajuste • A lista de blocos livres é percorrida seqüencialmente até encontrar o primeiro bloco livre cujo tamanho seja maior ou igual do que a quantidade de memória requisitada
Melhor ajuste • O método busca o menor bloco livre cujo tamanho seja maior do que ou igual à quantidade de memória requisitada
Pior ajuste • O método consiste na alocação de uma porção do maior bloco livre constante da lista de blocos livres • Usando um pequeno número de grandes blocos para satisfazer a maioria das requisições muitos blocos de tamanho moderado permanecem sem fragmentação • A não ser no caso da maioria de requisições de memória em grandes blocos, o método do pior ajuste satisfaz a um maior número de requisições do que os outros métodos
Primeiro exemplo • 1) Considere-se a situação na qual existem blocos livres com tamanhos 200, 300 e 100 unidades de memória. • Deseja-se alocar blocos de memória com os tamanhos 150, 100, 125, 10 e 100 unidades. A seqüência de alocação, pelos diversos processos é a seguinte.
Segundo exemplo • 2) Considere-se a situação na qual existem blocos livres com tamanhos 110 e 54 unidades de memória. • Deseja-se alocar blocos de memória com os tamanhos 25, 70 e 50 unidades. A seqüência de alocação, pelos diversos processos é a seguinte.
Gerenciamento dinâmico de memória • O método do primeiro ajuste é mais eficiente se a lista de blocos disponíveis for mantida em ordem crescente de endereços de memória. Caso a lista seja mantida em ordem crescente de tamanho de bloco a busca por melhor ajuste se torna mais eficiente. Caso a lista seja mantida em ordem decrescente de tamanho de bloco o método do pior ajuste é o mais eficiente. • Todavia não é prático manter a lista de blocos disponíveis classificada por tamanho. Na ausência de outras considerações ou especificações é usual se dar preferência ao método do primeiro ajuste.