FACULDADE BOA VIAGEM Carlos Eduardo Arruda Chaves ANÁLISE COMPARATIVA DO CONSUMO DE MEMÓRIA E TEMPO DE EXECUÇÃO NA PLATAFORMA ANDROID: UM ESTUDO DE CASO Recife 2014 Carlos Eduardo Arruda Chaves ANÁLISE COMPARATIVA DO CONSUMO DE MEMÓRIA E TEMPO DE EXECUÇÃO NA PLATAFORMA ANDROID: UM ESTUDO DE CASO Monografia apresentada como requisito para conclusão do Curso de Ciência da Computação da Faculdade Boa Viagem (FBV). Orientador: Felipe Silva Ferraz Recife 2014 Catalogação na fonte Biblioteca da Faculdade Boa Viagem, Recife/PE C111a Chaves, Carlos Eduardo Arruda. Análise comparativa do consumo de memória e tempo de execução na plataforma android: um estudo de caso / Carlos Eduardo Arruda Chaves. -- Recife : FBV | Devry, 2014. 65 f. : il. Orientador(a) : Felipe Silva Ferraz. Trabalho de Conclusão de Curso (Computação) -- Faculdade Boa Viagem | Devry. Inclui apêndice. 1. Dispositivos Móveis. 2. Android. 3. Java. I. Título. CDU 004[14.1] Ficha catalográfica elaborada pelo bibliotecário: Jadinilson Afonso CRB-4/1367 Carlos Eduardo Arruda Chaves ANÁLISE COMPARATIVA DO CONSUMO DE MEMÓRIA E TEMPO DE EXECUÇÃO NA PLATAFORMA ANDROID: UM ESTUDO DE CASO Monografia apresentada como pré-requisito para conclusão do Curso de Ciência da Computação da Faculdade Boa Viagem (FBV). Aprovada em: Recife, 18 de junho de 2014 Banca Examinadora _________________________________________________________ Felipe Silva Ferraz (Orientador) (Mestre em Ciências da Computação, Universidade Federal de Pernambuco) ________________________________________________________ Maria Carolina da Silva (1o Examinador) (Mestre em Ciências da Computação, Universidade Federal de Pernambuco) _______________________________________________________ Filipe Carlos Albuquerque Calegario (2 o Examinador) (Mestre em Ciências da Computação, Universidade Federal de Pernambuco) Dedico a Deus, a todas as pessoas que contribuíram diretamente ou indiretamente durante a minha formação acadêmica, a toda minha família e principalmente aos meus pais, por terem acreditado em mim, fornecendo todo o carinho e a melhor educação possível, e por serem exemplos de boas pessoas. Em especial, dedico a Isis Vilaça, que é uma pessoa muito especial em minha vida e que sempre esteve ao meu lado me apoiando em todos os momentos. AGRADECIMENTOS Agradeço primeiramente aos meus pais e à minha família por terem acreditado em mim, fornecendo todo carinho e apoio necessário para que eu chegasse até aqui. Em segundo lugar, agradeço a todos os professores que fizeram parte da minha formação acadêmica, em especial Antônio Luiz Cavalcanti, Danilo Araújo, Euclides Arcoverde, Felipe Ferraz, João Marcelo, Marconi Souza, Paulo Pereira, Renata Freire, Tayanna Sotero, Tse Min Lin e Walter Galão, pois sem eles não teria o conhecimento que possuo hoje. Agradeço também meus amigos de graduação Célio Alves e Amélia Pessoa que estiveram ao meu lado durante esta longa caminhada. Por fim, mas não com menor mérito, agradeço à minha namorada Isis Vilaça que sempre me apoiou e superou todos os estresses vivenciados durante o curso de Ciências da Computação, principalmente nas semanas de provas e de entregas de projetos. “Science never solves a problem without creating ten more.” (George Bernard Shaw) RESUMO Os smartphones estão tornando-se cada vez mais presentes no dia a dia das pessoas. Em 2013, a venda destes aparelhos superou a de celulares tradicionais e os dispositivos mais vendidos foram aqueles de menor custo. Os melhores smartphones que estão sendo comercializados, ainda possuem uma quantidade limitada de memória RAM. Com isso, esse trabalho tem o objetivo de comparar algumas técnicas de programação já existentes da linguagem Java, identificar quais podem auxiliar na economia de memória RAM e quais podem ser executadas no menor período de tempo na plataforma de desenvolvimento Android. Palavras-chave: dispositivos móveis, Android, Java, smartphone, memória RAM, tempo de execução, memória heap, técnicas de programação, vazamento de memória. ABSTRACT The smartphones are becoming increasingly present in the daily life of people. In 2013, the sale of these devices surpassed traditional mobile phones and more devices sold were those of lower cost. The best smartphones being sold still have a limited amount of RAM. With this, this work have the objective to compare some existing techniques of the Java programming language, and identify which could help RAM economy and which can be performed in the shortest period of time in the Android development platform. Keywords: mobile devices, Android, Java, Smartphone, memory RAM, execution time, heap memory, programming techniques, memory leak. LISTA DE ILUSTRAÇÕES Figura 1 - Vendas de telefone celular e smartphone no Brasil ......................... 13 Figura 2 - Quantitativo de vendas de smartphones em 2013 no mundo .......... 14 Figura 3 - Declaração de uma String................................................................ 18 Figura 4 - Utilização do operador de concatenação ......................................... 18 Figura 5 - Declaração de StringBuilder ............................................................ 19 Figura 6 - Utilização do método append ........................................................... 19 Figura 7 - Utilização do método insert .............................................................. 19 Figura 8 - Declaração de variável em Java ...................................................... 20 Figura 9 - Algumas implementações da interface List ...................................... 21 Figura 10 – Utilização de List ........................................................................... 21 Figura 11 - Herdando a classe Thread ............................................................. 23 Figura 12 - Diagrama de estado do ciclo de vida de uma thread ..................... 24 Figura 13 - Anatomia de um Integer ................................................................. 25 Figura 14 - Diagrama que representa a arquitetura Android ............................ 27 Figura 15 - Componentes de uma aplicação Android ...................................... 28 Figura 16 - Eclipse MAT ................................................................................... 31 Figura 17 – Configuração da máquina de desenvolvimento e coleta de dados 33 Figura 18 - Configurações do emulador Android .............................................. 34 Figura 19 - Tempo de execução das classes String e StringBuilder ................ 38 Figura 20 - Consumo de memória das classes String e StringBuilder ............. 38 Figura 21 - Tempo de execução dos tipos primitivos adequados e inadequados ......................................................................................................................... 42 Figura 22 - Consumo de memória dos tipos primitivos adequados e inadequados ......................................................................................................................... 42 Figura 23 - Tempo de execução do procedimento utilizando ArrayList e LinkedList ......................................................................................................... 46 Figura 24 – Consumo de memória do procedimento utilizando ArrayList e LinkedList ......................................................................................................... 46 Figura 25 - Tempo de execução do procedimento utilizando int e Integer ....... 49 Figura 26 – Consumo de memória do procedimento utilizando int e Integer ... 49 Figura 27 - Tempo de execução do procedimento utilizando long e Long ....... 51 Figura 28 - Consumo de memória do procedimento utilizando long e Long .... 51 Figura 29 - Consumo de memória do procedimento utilizando threads ........... 56 Figura 30 – Quantidade de threads executadas paralelamente ....................... 56 Figura 31 - Utilizando uma classe de thread privada e estática que estende a classe Thread com política de cancelamento................................................... 64 Figura 32 – Utilizando uma classe de thread anônima..................................... 65 Figura 33 - Utilizando uma classe de thread privada e estática que estende a classe Thread ................................................................................................... 65 LISTA DE TABELAS Tabela 1 – Resumo das configurações dos principais aparelhos..................... 15 Tabela 2 - Tipos primitivos em Java ................................................................. 20 Tabela 3 - Wrappers de tipo primitivo ............................................................... 24 Tabela 4 – Resultado da execução do processamento com String.................. 36 Tabela 5 - Resultado da execução do processamento com StringBuilder ....... 37 Tabela 6 - Dados cadastrais de uma pessoa ................................................... 39 Tabela 7 - Atributos da classe PessoaSOK.java .............................................. 40 Tabela 8 - Atributos da classe PessoaNOK.java .............................................. 40 Tabela 9 – Resultado da execução utilizando os tipos de dados primitivos adequadamente ............................................................................................... 41 Tabela 10 – Resultado da execução utilizando os tipos de dados primitivos inadequadamente............................................................................................. 42 Tabela 11 – Resultado da execução utilizando LinkedList ............................... 44 Tabela 12 – Resultado da execução utilizando ArrayList ................................. 45 Tabela 13 – Resultado da execução utilizando o tipo primitivo int ................... 48 Tabela 14 – Resultado da execução utilizando a classe wrapper Integer ........ 49 Tabela 15 - Resultado da execução utilizando o tipo primitivo long ................. 50 Tabela 16 - Resultado da execução utilizando a classe wrapper Long ............ 51 Tabela 17 - Resultado da execução utilizando uma classe de thread anônima54 Tabela 18 - Resultado da execução utilizando uma classe de thread privada e estática que estendia a classe Thread ............................................................. 55 Tabela 19 - Resultado da execução utilizando uma classe de thread privada e estática que estendia a classe Thread com política de cancelamento ............. 56 LISTA DE ABREVIATURAS E SIGLAS 3D Terceira Dimensão ABINEE Associação Brasileira da Industria Elétrica e Eletrônica API Interface de Programação de Aplicativos GC Garbage Colector GB GigaByte DDR Double Data Rate EE Enterprise Edition HTC High Tech Computer Corporation IBM International Business Machines IDC International Data Corporation IDE Ambiente de Desenvolvimento Integrado JVM Máquina Virtual Java MB MegaByte LG Lucky Goldstar MAT Memory Analyzer Tools OHA Open Handset Aliance RAM Memória de Acesso Aleatório SO Sistema Operacional SSD Disco de Estado Sólido XML Linguagem de Marcação Extensível SUMÁRIO 1. 2. INTRODUÇÃO .......................................................................................... 13 1.1 Descrição do problema ....................................................................... 15 1.2 Objetivo geral ...................................................................................... 15 1.3 Objetivos específicos .......................................................................... 16 REFERENCIAL TEÓRICO ....................................................................... 17 2.1 2.1.1. String................................................................................................ 17 2.1.2. StringBuilder .................................................................................... 18 2.2 Tipo de dados primitivos ..................................................................... 19 2.3 Listas ................................................................................................... 20 2.3.1. LinkedList ......................................................................................... 22 2.3.2. ArrayList ........................................................................................... 22 2.4 2.4.1. Threads ............................................................................................... 22 Ciclo de vida de uma thread ............................................................ 23 2.5 Classes wrappers ................................................................................ 24 2.6 Open Handset Aliance (OHA) ............................................................. 25 2.7 Android ................................................................................................ 26 2.7.1. Arquitetura Android .......................................................................... 26 2.7.2. Componentes de uma aplicação Android ........................................ 28 2.8 3. String e StringBuilder .......................................................................... 17 Vazamento de memória (Memory Leak) ............................................. 29 METODOLOGIA ....................................................................................... 30 3.1 Tipo de pesquisa ................................................................................. 30 3.2 Instrumento de coleta de dados .......................................................... 30 3.3 Classificação dos dados...................................................................... 31 3.4 Cenário................................................................................................ 32 4. ANÁLISE DE DADOS............................................................................... 35 4.1 4.1.1. Cenário ............................................................................................ 35 4.1.2. Resultado da avaliação .................................................................... 36 4.2 Utilização dos tipos de dados primitivos.............................................. 38 4.2.1. Cenário ............................................................................................ 38 4.2.2. Resultado da avaliação .................................................................... 40 4.3 Uso de Listas ...................................................................................... 43 4.3.1. Cenário ............................................................................................ 43 4.3.2. Resultado da avaliação .................................................................... 44 4.4 Utilização de tipos primitivos e classe wrappers ................................. 46 4.4.1. Cenário ............................................................................................ 47 4.4.2. Resultado da avaliação .................................................................... 47 4.4.2.1. Uso de Integer e int ...................................................................... 48 4.4.2.2. Uso de long e Long....................................................................... 50 4.5 5. Uso das classes String e StringBuilder ............................................... 35 Uso de threads .................................................................................... 52 4.5.1. Cenário ............................................................................................ 52 4.5.2. Resultado da avaliação .................................................................... 53 CONCLUSÕES ......................................................................................... 58 REFERÊNCIAS ................................................................................................ 60 APÊNDICES .................................................................................................... 64 13 1. INTRODUÇÃO O crescimento da classe média e o aumento do acesso ao crédito no Brasil popularizou o uso de dispositivos móveis, tornando-os cada vez mais presentes no dia a dia dos brasileiros. Os dados presentes na Figura 1, foram coletados pela Associação Brasileira da Industria Elétrica e Eletrônica (ABINEE) e International Data Corporation (IDC) [1]. Eles correspondem aos resultados anuais de comparações entre o uso de celulares tradicionais e smartphones ( são celulares não só capazes de entrar na internet, mas que podem acessar lojas de aplicativos, rodam um sistema operacional que possa executar funções mais complexas e tem capacidade de processamento mais potente [2]) no Brasil. Figura 1 - Vendas de telefone celular e smartphone no Brasil 70 60 58 67,1 Milhões 50 59,5 43,5 40 29,1 32 30 20 10 0 Celulares Tradicionais Smartphones Total 61,1 16 9,1 2011 2012 2013 58 9,1 67,1 43,5 16 59,5 29,1 32 61,1 Ano Fonte: Adaptado de TELECO, 2014 [1] É possível identificar que no ano de 2013 a venda de smartphones no Brasil superou a de celulares tradicionais. Segundo Bruno Freitas [2], gerente de pesquisas da IDC, a ultrapassagem ocorreu mais precisamente do mês de abril para maio. Mundialmente foram vendidos 1,0096 bilhão de smartphones [3]. 14 A Figura 2 mostra a quantidade de unidades vendidas em milhões de cada sistema operacional (SO). Figura 2 - Quantitativo de vendas de smartphones em 2013 no mundo BlackBerry; 19,2; 2% Windows Phone; 33,4; 3% Outros; 10; 1% iOS; 153,4; 15% Android; 793,6; 79% Fonte: Adaptado de IDC Worldwide Mobile Phone Tracker, Fevereiro, 2014 [3] Pode-se verificar que os aparelhos com o SO Android foram os mais vendidos de 2013, seguidos dos aparelhos com iOS (sistema operacional para dispositivos móveis da Apple), Windows Phone (sistema operacional móvel da Microsoft) e BlackBerry, respectivamente. Em complemento, 45,56% dos dispositivos comprados custaram menos de 200 dólares [4]. Pesquisa realizada por Gareth Beavis [5] mostra os dez melhores smartphones do mundo. A Tabela 1 lista os aparelhos e as principais configurações de cada smartphone analisado. 15 Tabela 1 – Resumo das configurações dos principais aparelhos Aparelho Processador Samsung Galaxy S4 Quad-core 1.9 GHz Motorola Moto G Quad-core 1.2 GHz HTC One Quad-core 1.7 GHz Sony Xperia Z1 Compact Quad-core 2.2 GHz Google Nexus 5 Quad-core 2.26 GHz LG G2 Quad-core 2.3 GHz Samsung Galaxy S5 Quad-core 2.5 GHz Sony Xperia Z2 Quad-core 2.3 GHz HTC One M8 Quad-core 2.3 GHz Média Fonte: Autoria própria Memória RAM (GB) 2 1 2 2 2 2 2 3 2 2 Pode-se verificar que o smathphone que possui a maior quantidade de Memória de Acesso Aleatório (RAM) é o Sony Xperia Z2 com 3 Gigabytes (GB). O Motorola Moto G é o que possui a menor quantidade de memória física com 1GB, os demais parelhos possuem 2 GB. Dado este cenário, verifica-se que os smartphones, mesmo os mais potentes ainda possuem um poder de processamento limitado pela memória RAM. 1.1 Descrição do problema Por mais que os dispositivos móveis estejam a cada dia mais desenvolvidos, verifica-se que a memória RAM ainda é um recurso escasso. Conforme visto na Tabela 1 a média de memória física existente entres os aparelhos é de 2,0 GB. Sabendo desta limitação, evidencia-se a seguinte problemática: entre as técnicas de programação já existentes, quais poderão minimizar o consumo de memória RAM na plataforma Android? 1.2 Objetivo geral O objetivo desta pesquisa é analisar as técnicas já existentes, na linguagem de programação Java e identificar quais podem ser executadas com maior velocidade e as que podem evitar o desperdício de memória RAM, utilizando essa linguagem no desenvolvimento de aplicativos para a plataforma Android. 16 1.3 Objetivos específicos Com o propósito de obter o objetivo geral estabelecido, este trabalho elucida como objetivos específicos os itens abaixo: • Estudar o gerenciamento de memória da plataforma Android; • Desenvolver aplicativos Android, utilizando a linguagem de programação Java; • Comparar práticas de programação e identificar quais podem evitar o desperdício de memória e quais podem ser mais eficientes; • 1 Analisar a memória heap1 dos aplicativos desenvolvidos.[6] Heap: Local onde a Máquina Virtual Java (JVM) armazena todos os objetos criados pelo aplicativo Java [6]. 17 2. REFERENCIAL TEÓRICO Este capítulo abordará os fundamentos teóricos, conceituando e exemplificando cada técnica de programação analisada nesta pesquisa, foram elas: String, StringBuilder, tipo de dados primitivos, ArrayList, LinkedList, classes wrappers e threads. Também será explicado os principais componentes da plataforma Android e o conceito de vazamento de memória. 2.1 String e StringBuilder Nesta seção serão apresentados os conceitos teóricos e exemplos de utilização das classes String e StringBuilder. 2.1.1. String Segundo a Oracle [7], String é uma classe que faz parte do pacote java.lang e é filha da classe Object que é a raiz da hierarquia de classes, toda as classes em Java são filhas dela e todos os objetos, incluindo arrays implementam métodos desta classe [8]. String Também implementa as interfaces Serializable, CharSequence e Comparable. A Primeira interface permite que um objeto seja serializado, ou seja, este objeto será transformado em um array de bytes e poderá ser armazenado em disco ou transmitido por um stream [9]. A segunda interface é uma sequência de caracteres, ela fornece acesso de apenas leitura para muitos tipos diferentes de sequência de caracteres [10]. E a última interface permite que um objeto seja comparado com outro objeto e, nesta comparação o resultado poderá ser igual ou primeiro objeto maior ou segundo objeto maior [11]. Em Java, a classe String é caracterizada por um conjunto de caracteres, seus valores são constantes e não podem ser modificados após sua inicialização. Strings são imutáveis e, por esta razão, podem ser compartilhadas. As representações de textos em programas Java são implementadas como instâncias desta classe e sempre devem estar entre aspas duplas. A Figura 3 mostra um exemplo de uma String na linguagem de programação mencionada anteriormente: 18 Figura 3 - Declaração de uma String Fonte: Autoria própria String fornece vários métodos nativos como uppercase, lowercase e substring. O primeiro método converte todas as letras de uma String para caracteres maiúsculos, o segundo converte todas as letras de uma String para caracteres minúsculos e o ultimo retorna parte de uma String. Java fornece um suporte especial para o operador de concatenação (+). A Figura 4 mostra um exemplo de utilização do mesmo: Figura 4 - Utilização do operador de concatenação Fonte: Autoria própria O valor contemplado na String resultado será “AB”. 2.1.2. StringBuilder Segundo a Oracle [12], StringBuilder é uma classe que faz parte do pacote java.lang, assim como String, é filha da classe Object e implementa as interfaces Serializable e CharSequence. Diferente da classe String, StringBuilder implementa a interface Appendable, esta permite que uma sequência de caracteres seja adicionada em um objeto que implementa esta interface [13]. Em Java, StringBuilder caracteriza-se por uma sequência de caracteres e seus valores podem ser modificados após sua inicialização. Por esta razão, pode-se dizer que StringBuilder é mutável, mas sem garantia de sincronização. A Figura 5 mostra um exemplo de uma StringBuilder na linguagem de programação mencionada anteriormente: 19 Figura 5 - Declaração de StringBuilder Fonte: Autoria própria As principais operações desta classe são append e insert. O primeiro método sempre adiciona os caracteres no final dos caracteres já existentes. O segundo método insere os caracteres em um ponto especifico. A Figura 6 mostra um exemplo de utilização do método append: se Z é uma StringBuilder e contém o texto “java”, ao utilizar o método append(“se”), o resultado de Z será “javase”. Figura 6 - Utilização do método append Fonte: Autoria própria A Figura 7 mostra um exemplo de utilização do método insert: Figura 7 - Utilização do método insert Fonte: Autoria própria Se Z é uma StringBuilder e contém o texto “java”, ao utilizar o método insert(0, “se”), o resultado de Z será “sejava”. 2.2 Tipo de dados primitivos Segundo Kathy Sierra [14] e a Oracle [15], os tipos de dados primitivos contém valores básicos que incluem inteiros, booleanos e números de ponto flutuante. Todas as declarações de variáveis em Java devem ter tipo e nome. A Figura 8 mostra como se declara uma variável nesta linguagem de programação, sendo int o tipo da variável e número é o nome. 20 Figura 8 - Declaração de variável em Java Fonte: Autoria própria A Tabela 2 apresenta resumidamente os tipos de dados primitivos da linguagem de programação Java. Tabela 2 - Tipos primitivos em Java Tipo Quantidade de bits boolean 1 char 16 byte short 8 16 Pode assumir os valores verdadeiro ou falso. É uma implementação especifica da JVM. Caractere em notação Unicode de 16bits. Serve para armazenar dados alfa numéricos. Número inteiro de oito bits. Número inteiro de 16 bits int 32 Número inteiro de 32 bits long 64 float 32 Número inteiro de 64 bits Representa números reais simples. double 64 Descrição Valores de precisão Representa números reais de precisão dupla. Verdadeiro ou falso 0 a 65.535 -128 a 127 -32.768 a 32.767 - 2.147.483.648 a 2.147.483.647 -2^63 a 2^63 – 1 Possui 32 bits de precisão. Possui 64 bits de precisão. Fonte: Autoria própria É possível verificar que cada tipo de dado possui tamanho e alcance diferentes. 2.3 Listas Segundo Caelum [16], lista é uma coleção que permite elementos duplicados e mantém uma ordenação específica entre os elementos. 21 Figura 9 - Algumas implementações da interface List Fonte: Adaptado de CAELUM [16] A Figura 9 mostra que as classes LinkedList e ArrayList são implementações da interface List. Figura 10 – Utilização de List Fonte: Autoria própria A figura Figura 10 mostra um exemplo genérico de utilização de listas, para instanciar uma LinkedList ou um ArrayList, basta trocar o texto “Implementacao” pelo nome da implementação desejada. Após instanciar a classe e utilizar o método add, os elementos 1 e 2 foram inseridos na lista. 22 2.3.1. LinkedList Esta implementação faz parte do pacote java.util e, segundo a International Business Machines (IBM) [17], é uma implementação da interface List. Permite elementos duplicados, possui tamanho preciso e não necessita ser redimensionada. A Figura 10 mostra um exemplo de utilização desta implementação. 2.3.2. ArrayList Esta implementação faz parte do pacote java.util e, segundo Ronaldo Lanhellas [18], é a implementação da interface List mais utilizada. Esse tipo de lista é dimensionado dinamicamente, ou seja, quando necessário o seu tamanho aumenta em 50%. Isso significa dizer que se existir uma lista de tamanho 10 e ela ficar cheia, seu tamanho aumentará para 15 automaticamente. A Figura 10 mostra um exemplo de utilização desta implementação. 2.4 Threads Existem situações nas quais é preciso executar duas ou mais tarefas ao mesmo tempo, como por exemplo, em um computador, escutar músicas e escrever um documento. Em Java, quando o assunto é processamento paralelo fala-se de Threads [19]. Segundo a Oracle [20], Thread é uma classe que faz parte do pacote java.lang, filha da classe Object e implementa a interface Runnable. Uma maneira de criar uma thread é herdando a classe Thread. A Figuras 11, exemplifica essa maneira. 23 Figura 11 - Herdando a classe Thread Fonte: Autoria própria Segundo Caelum [21], ao estender a classe Thread, vários métodos são herdados, porém apenas o método run é realmente utilizado. 2.4.1. Ciclo de vida de uma thread Segundo Deitel [22], uma thread inicia o seu ciclo de vida no estado novo e permanece neste estado até que o programa a inicie. Após isso, a thread estará no estado executável, ou seja, executando sua tarefa. Enquanto a thread está sendo executada, ela pode entrar no estado de espera para aguardar que uma outra thread execute uma tarefa. A thread só voltará ao estado executável quando for sinalizada que pode retomar sua execução. Uma thread no estado executável pode entrar no estado de espera sincronizada por um intervalo específico de tempo. A thread retornará ao estado executável quando o intervalo sincronizado expirar ou for notificado por outra thread. Uma thread entra no estado terminado quando completa sua tarefa. A Figura 12 ilustra os possíveis estados de uma thread. 24 Figura 12 - Diagrama de estado do ciclo de vida de uma thread Fonte: DEITEL, 2005 [22] 2.5 Classes wrappers Segundo Lanhellas [23], Java possui diversos wrappers que adicionam funcionalidades a outras classes ou tipos primitivos. Um exemplo é o Integer, que é a classe wrapper do tipo primitivo int. A Tabela 3 mostra os wrappers de tipos primitivos. Tabela 3 - Wrappers de tipo primitivo Tipo primitivo Classe wrapper boolean Boolean char Character byte Byte short Short int Integer long Long float Float double Double Fonte: Autoria própria 25 Segundo Bailey [17], a classe wrapper Integer tem uma sobrecarga adicional de metadados2. A quantidade destes pode variar de acordo com a JVM, sendo composta por: a) Class: Um ponteiro para as informações sobre a classe, que descreve o tipo de objeto. Neste caso é um ponteiro para a classe java.lang.Integer. b) Flags: Uma coleção de sinalizadores que descreve o estado do objeto, incluindo o código hash para o objeto, se houver um, e a forma do objeto (ou seja, se o objeto é um array ou não). c) Lock: As informações de sincronização para o objeto — ou seja, se o objeto está sincronizado atualmente. Figura 13 - Anatomia de um Integer Fonte: Adaptado de IBM, 2012 [17] A Figura 13 mostra que um Integer utiliza 128 bits, sendo 32 bits utilizados para armazenar o dado e 96 bits para metadados. 2.6 Open Handset Aliance (OHA) Segundo Lecheta [24], a plataforma Android foi desenvolvida por um grupo de empresas líderes em tecnologia móvel. O objetivo desta aliança era padronizar uma plataforma de código aberto e livre para celulares, visando atender as expectativas e tendências do mercado. Este grupo de empresas intitula-se OHA. 2 Metadados: São dados que descrevem dados. Eles provêm uma descrição concisa a respeito dos dados. Os dados podem ser documentos, coleção de documentos, gráficos, tabelas, imagens, vídeos entre outros tantos.[38] 26 “A Open Handset Alliance é um grupo formado por gigantes do mercado de telefonia de celulares liderados pelo Google. Entre alguns integrantes do grupo estão nomes consagrados como a HTC, LG, Motorola, Samsung, Sony Ericsson, Toshiba,Sprint Nextel, China Mobile, T-Mobile, ASUS, Intel, Garmin e muitas mais.[...] Assim o objetivo do grupo é definir uma plataforma única e aberta para celulares para deixar os consumidores mais satisfeitos com o produto final. Outro objetivo principal dessa aliança é criar uma plataforma moderna e flexível para o desenvolvimento de aplicações coorporativas. O resultado dessa união, como pode ser visto, foi o nascimento do Android. [...] Todos acabam se beneficiando dessa união: os fabricantes de celulares, os usuários comuns e, é claro, os desenvolvedores de aplicações. LECHETA, 2010. 2.7 Android Segundo Lecheta [24], a plataforma Android é livre e de código aberto. O sistema operacional desta plataforma é baseado no kernel Linux 2.6 e possui uma interface visual rica. É uma nova plataforma de desenvolvimento para aplicativos móveis como smartphones e fornece um ambiente de desenvolvimento poderoso, inovador e flexível. Para desenvolver aplicativos para esta plataforma pode-se utilizar a linguagem de programação Java. 2.7.1. Arquitetura Android De acordo com Lecheta [24], a arquitetura Android é flexível, pois você pode integrar aplicações nativas com aplicações desenvolvida por você ou até mesmo substituir qualquer aplicação nativa por uma que você mesmo criou. Segundo Tosin [25], a arquitetura Android é composta por várias camadas e componentes que serão explicadas posteriormente. A Figura 14 mostra um diagrama que representa a arquitetura da plataforma Android. 27 Figura 14 - Diagrama que representa a arquitetura Android Fonte: SOFTBLUE, 2011 [25] a) Linux Kernel: É responsável por gerenciar memória, processos, threads e a segurança dos arquivos e pastas, além de redes e drivers. b) Libraries: Contempla as bibliotecas nativas escritas em C/C++ que fazem parte da plataforma. Exemplos: APIs que estão nesta camada OpenGL que é responsável pela renderização 3D, SQLite gerenciador de banco de dados e o Midia Framework que fornece suporte a vários formatos de áudio e vídeo. c) Android Runtime: Fornece condições para que as aplicações baseadas na plataforma sejam executadas. d) Application Framework: Contempla as APIs Android que são utilizadas pelas aplicações que executam sobre a plataforma. e) Applications: Representa as aplicações que executam sobre a plataforma. Estas podem ser nativas como gerenciador de contatos, navegador, calendário ou aplicações criadas por terceiros. Esta é a característica que garante um alto grau de flexibilidade e extensibilidade da plataforma. 28 2.7.2. Componentes de uma aplicação Android De acordo com Tosin [25], a plataforma Android disponibiliza um grupo de componentes que possibilita o desenvolvimento de aplicativos para sua plataforma. A Figura 15 ilustra esses componentes. Figura 15 - Componentes de uma aplicação Android Fonte: SOFTBLUE, 2011 [25] a) Activities: São as representantes de telas da aplicação. Uma acitivity geralmente possui view, que define como será feita a exibição visual para os usuários. As activities são responsáveis por gerenciar os eventos da tela e também coordenam o fluxo da aplicação. b) Services: São processos que executam em segundo plano, ou seja, sem que o usuário perceba e normalmente são utilizados para tarefas de longa duração, como: sincronização de dados. c) Content Providers: São provedores de conteúdo. É a maneira utilizada para compartilhar dados entre as aplicações que estão sendo executadas no diposistivo. d) Broadcast Receivers: São componentes que ficam “ouvindo” a ocorrência de determinados eventos, sendo que estes podem ser nativos ou de outros aplicativos. 29 Junto a esses componentes, existe o arquivo de manifesto AndroidManifest.xml. Ele é obrigatório a todos aplicativos Android e único para cada aplicação. Neste arquivo são efetuadas as configurações gerais da aplicação e dos componentes que fazem parte dela. 2.8 Vazamento de memória (Memory Leak) Segundo Tosin [26], o vazamento de memória, termo comumente conhecido por memory leak, não ocorre somente em C/C++, também acontece em Java. O vazamento de memória pode ser de dois tipos: a) Blocos de memória estão alocados e disponíveis para serem utilizados pela aplicação, mas não estão acessíveis porque a aplicação não tem nenhum ponteiro apontando para esta área de memória. Logo, esses blocos de memória não podem ser utilizados nem pela aplicação e nem por outros processos. b) Blocos de memória possuem dados que poderiam ser liberados por serem inacessíveis e que, por negligencia do programador ainda são referenciados no código, mesmo sem estarem sendo utilizados, impedindo de serem liberados. Em Java o primeiro tipo não ocorre, pois o Garbage Collector (GC) é capaz de detectar blocos de memória alocados e não referenciados e libera-los para uso posterior. O segundo tipo pode ocorrer nesta linguagem de programação, para isso basta manter a referência de um ou mais objetos no código, mesmo sem utilizála depois. Desta forma o GC não poderá destruir os objetos, e eles continuarão existindo na memória mesmo não sendo mais acessíveis. Quando os blocos de memória disponibilizados para a aplicação acabarem a JVM lançará um erro do tipo java.lang.OutOfMemoryError. 30 3. METODOLOGIA Neste capítulo, serão esclarecidos os procedimentos metodológicos utilizados para atingir o objetivo geral desta pesquisa, os quais envolverão a criação de aplicativos Android e a análise do consumo de memória dos mesmos, tempo de execução e número de threads. 3.1 Tipo de pesquisa Este trabalho apresenta uma pesquisa de abordagem quantitativa com procedimentos técnicos de estudo de caso e objetivo exploratório. Segundo Freitas [27], pesquisa quantitativa é tudo pode ser quantificável, o que significa traduzir em números, opiniões e informações para classificá-las e analisá-las. De acordo com Schramm [28], a essência do estudo de caso é tentar esclarecer uma decisão, ou um conjunto de decisões, seus motivos, implementações e resultados. Segundo Gil [29], a pesquisa exploratória tem como objetivo principal o aprimoramento de ideias ou descobertas de intuições. 3.2 Instrumento de coleta de dados Para alcançar o objetivo desta pesquisa, a amostra foi investigada por meio da observação sistemática e individual. De acordo com Gil [29], esta forma de coleta de dados é realizada por um único indivíduo e tem como planejamento responder aos propósitos preestabelecidos. A coleta dos dados foi realizada com a ferramenta Eclipse Memory Analyzer Tools (MAT) que analisa a heap do Java e contém recursos que ajudam a encontrar vazamentos de memória e reduzir o consumo de memória [30]. A Figura 16 mostra a tela inicial do Eclipse MAT. Nela podemos verificar o tamanho da heap, a quantidade de classes e objetos bem como os objetos que consomem mais memória. 31 Figura 16 - Eclipse MAT Fonte: Autoria própria 3.3 Classificação dos dados Para alcançar o objetivo desta pesquisa, analisou-se os dados obtidos pelo instrumento de coleta de dados explicado na seção anterior. Os dados obtidos foram consumo de memória, tempo de execução e número de threads. a) Consumo de memória: Ao iniciar cada aplicativo e ao término de cada procedimento foi feita uma cópia e análise da memória heap dos aplicativos utilizando o Eclipse MAT. 32 b) Tempo de execução: O tempo de execução de cada procedimento foi medido em segundos. Para coletar o tempo gasto em cada procedimento foi coletada a hora de início e fim do mesmo. Após isso foi efetuada uma subtração entre as horas coletadas para obter o tempo gasto em segundos. c) Número de threads: A cada thread iniciada um contador era incrementado e a cada thread finalizada o contador era decrementado. Ao termino do procedimento o número de threads que estavam sendo executadas paralelamente era exibido. 3.4 Cenário Nesta seção, serão descritas as configurações e softwares e hardware utilizados para implementar os aplicados e coletar os dados dos mesmos. Os softwares utilizados no desenvolvimento dos aplicativos e para fazer a coleta dos dados estão descritos a seguir: • Eclipse Java Enterprise Edition (EE) IDE for Web Developers, versão: Kepler Service Release 1; • Eclipse Memory Analyzer - API feature, versão: Chart feature, versão: 1.3.1.201401071412; • Eclipse Memory Analyzer - 1.3.1.201401071412; • Android Development Toolkit, versão 22.2.1.v201309180102833290. As configurações da máquina utilizada para o desenvolvimento dos aplicativos e para realizar a coleta de dados estão descritas a seguir: • Modelo: Samsung 530U3C-AD5BR [31]; • Processador: Intel® Core™ i7 3517U (1.90 GHz, 4 MB L3 Cache); • Memoria: 8 GB DDR3; • Disco rígido: 500 GB S-ATA + 24 GB iSSD Express Cache; • Sistema Operacional: Ubuntu 13.04. A Figura 17 mostra as configurações da máquina e o sistema operacional utilizado durante essa pesquisa. 33 Figura 17 – Configuração da máquina de desenvolvimento e coleta de dados Fonte: Autoria própria Para efetuar a coleta de dados, foi utilizado um emulador Android com as características descritas a seguir: • Dispositivo: 2.7” QVGA (240 X 320: ldpi); • Versão Android: 4.3 Jelly Bean – Level da API 18; • Memória RAM: 512 MB; • Tamanho da heap 16 MB; • Processador cortex-a8; • Memória interna: 200 MB; • Cartão de memória: 200 MB. A Figura 18 mostra as configurações do emulador Android utilizado durante a coleta dos dados. 34 Figura 18 - Configurações do emulador Android Fonte: Autoria própria 35 4. ANÁLISE DE DADOS Neste capítulo, serão apresentados os resultados obtidos a partir da realização desta pesquisa no emulador Android, cujas características foram expostas no capítulo 3. Para isso, foram coletadas as cópias da memória heap dos aplicativos antes e depois da execução, bem como o tempo de execução de cada procedimento. Os dados foram coletados e organizados em gráficos e tabelas, de maneira a possibilitar a análise e comparação entre as técnicas de programação analisadas. 4.1 Uso das classes String e StringBuilder Nesta sessão será analisado o uso das classes String e StringBuilder, estudos [32] [33] exibem que ao utilizar a classe StringBuilder é possível evitar o trashing (situação na qual é utilizando uma grande quantidade de recurso para fazer um trabalho mínimo) de memória e obter ganhos de performance. A primeira classe é caracterizada por uma sequência de caracteres, cujos valores não podem ser alterados após sua inicialização. A segunda classe assim como String é caracterizada por um conjunto de caracteres, porem pode ser modificada após sua criação. 4.1.1. Cenário Para realizar as medições, foi desenvolvido um aplicativo Android que continha pacotes, AndroidManifest.xml, MainActivity.java, StringActivity.java, StringbuilderActivity.java e activity_main.xml, sendo detalhados a seguir: • AndroidManifest.xml: Contemplava as declarações das três activities; • MainActivity.java: Principal activity com dois botões (String e StringBuilder). O primeiro botão inicia a “StringActivity.java”, já o segundo inicializa a “StringbuilderActivity.java”; • StringActivity.java: Possui uma repetição que concatena todos os números de 0 (zero) à 4999 (quatro mil novecentos e noventa e nove) em uma String utilizando o operador (+); 36 • StringbuilderActivity.java: Contém uma iteração que encadeia todos os números de 0 (zero) à 4999 (quatro mil novecentos e noventa e nove) em uma StringBuilder utilizando o operador append; • activity_main.xml: Arquivo de layout que possui um LinearLayout com orientação vertical e dois botões. 4.1.2. Resultado da avaliação Para esse cenário, a MainActivity.java foi executada no emulador e, ao concluir seu carregamento, o botão com o texto “String” foi pressionado. Este procedimento efetua a medição da memória heap antes e depois da execução do laço mencionado anteriormente. Para a primeira execução, o resultado obtido foi 1,9 MB de memória antes da execução do laço e 2,0 MB de memória após realização do mesmo. Esse procedimento foi executado mais quatro vezes e os resultados obtidos estão listados na Tabela 4. Tabela 4 – Resultado da execução do processamento com String Ciclo Memória antes da execução (MB) Memória depois da execução (MB) (%) Tempo de execução (s) 1 1,9 2,0 5,26 11,128 2 1,9 2,0 5,26 11,774 3 1,9 2,0 5,26 11,024 4 1,9 2,0 5,26 11,722 5 1,9 2,0 5,26 10,859 Conclusão Aumento do consumo de memória RAM em 5,26%. Aumento do consumo de memória RAM em 5,26%. Aumento do consumo de memória RAM em 5,26%. Aumento do consumo de memória RAM em 5,26%. Aumento do consumo de memória RAM em 5,26%. Fonte: Autoria própria É possível verificar que houve um aumento no consumo de memória de 5,26% em média. Desta forma, pode-se concluir que após pressionar o botão com o texto “String” houve um acréscimo no consumo da heap. Em complemento, pode-se verificar que o tempo de execução foi de 11,301 segundos em média. 37 Depois desta execução, o mesmo processo foi realizado, desta vez, pressionando o botão com o texto “Stringbuilder”. Este procedimento da mesma forma que o anterior, realiza a medição da memória heap antes e depois da execução do laço. Na primeira execução, o resultado obtido foi 1,9 MB de memória antes da execução do laço e 2,0 MB de memória após realização do mesmo. Esse procedimento, foi executado mais 4 vezes e os resultados obtidos estão listados na Tabela 5. Tabela 5 - Resultado da execução do processamento com StringBuilder Ciclo Memória antes da execução (MB) Memória depois da execução (MB) % Tempo de execução (s) 1 1,9 2,0 5,26 0,159 2 1,9 2,0 5,26 0,142 3 1,9 2,0 5,26 0,174 4 1,9 2,0 5,26 0,150 5 1,9 2,0 5,26 0,154 Conclusão Aumento do consumo de memória RAM em 5,26%. Aumento do consumo de memória RAM em 5,26%. Aumento do consumo de memória RAM em 5,26%. Aumento do consumo de memória RAM em 5,26%. Aumento do consumo de memória RAM em 5,26%. Fonte: Autoria própria É possível verificar que houve um aumento no consumo memória de 5,26% em média. Desta forma, pode se concluir que após pressionar o botão com o texto “Stringbuilder” houve um acréscimo no consumo da heap. Em adição, pode-se verificar que o tempo de execução foi de 0,156 segundos em média. As Figuras 19 e 20 mostram o tempo de execução e o consumo de memória após a execução do procedimento, respectivamente. 38 Figura 19 - Tempo de execução das classes String e StringBuilder Figura 20 - Consumo de memória das classes String e StringBuilder 11,301 12,000 2,0 2,0 2,0 8,000 MB Segundos 10,000 6,000 1,0 4,000 2,000 0,156 0,000 0,0 Tempo de execução String Consumo de memória StringBuilder String Fonte: Autoria própria StringBuilder Fonte: Autoria própria É possível identificar que o consumo de memória foi semelhante. Em contrapartida, o tempo de execução da classe StringBuilder foi, em média, 98,62% mais rápida que a sua concorrente, a classe String. 4.2 Utilização dos tipos de dados primitivos Nesta seção será abordado o uso dos tipos de dados primitivos em Java que podem ser byte, short, int, long, float, double, boolean ou char. Esta linguagem de programação é fortemente tipada, ou seja, em todas as declarações de variáveis deve-se informar o tipo de dados da mesma. De acordo com Marcio Junior [34], os tipos primitivos determinam o tipo e o tamanho da informação que será armazenada em uma variável. Utilizando os tipos de dados primitivos de maneira correta pode-se evitar o desperdício de memória. Diante disto, será efetuada uma análise focada em quantificar este desperdício. 4.2.1. Cenário Para realizar as medições, foi construído um aplicativo Android que continha pacotes, AndroidManifest.xml, InicioActivity.java, InadequadoActivity.java, 39 AdequadoActivity.java, PessoaNOK.java, PessoaSOK.java e activity_main.xml, sendo detalhados a seguir: • AndroidManifest.xml: Contempla as declarações das três activities; • InicioActivity.java: Principal activity com dois botões (Adequado e Inadequado). O primeiro botão inicia a “AdequadoActivity.java” já o segundo inicializa a “InadequadoActivity.java”; • AdequadoActivity.java: Possuía uma repetição de 0 (zero) à 9999 (nove mil novecentos e noventa e nove) para cada iteração, foi adicionada uma pessoa, que foi representada pela classe PessoaSOK da Tabela 7, em uma lista. Os dados cadastrais de cada pessoa estão na Tabela 6. No final do processo, a lista contemplou 10000 (dez mil) pessoas cadastradas; • InadequadoActivity.java: Possuía uma repetição de 0 (zero) à 9999 (nove mil novecentos e noventa e nove) em cada iteração, foi adicionada uma pessoa, que foi representada pela classe PessoaNOK da Tabela 8, em uma lista. Os dados cadastrais de cada pessoa estão na Tabela 6. No final do processo a lista contemplou 10000 (dez mil) pessoas cadastradas; Tabela 6 - Dados cadastrais de uma pessoa Nome atributo Valor Idade 20 Sexo M identidade 9999999 cpf 99999999999 Fonte: Autoria própria • PessoaSOK.java: classe que representava uma pessoa no mundo orientado a objetos. A definição dos tipos de dados e o nome dos atributos estão definidos na Tabela 7; 40 Tabela 7 - Atributos da classe PessoaSOK.java Tipo de dados Nome do atributo byte idade char sexo int identidade long cpf Fonte: Autoria própria • PessoaNOK.java: Classe que representava uma pessoa no mundo orientado a objetos. Diferente da classe PessoaSOK.java os atributos idade e identidade são dos tipos de dados int e long, respectivamente. Não existe a necessidade do primeiro atributo ser um int, pois a idade de uma pessoa pode ser representada por um byte. Já a segundo atributo pode ser representado por um int. A definição dos tipos de dados e o nome dos atributos estão definidos na Tabela 8; Tabela 8 - Atributos da classe PessoaNOK.java Tipo de dado Nome do atributo int idade char sexo long identidade long cpf Fonte: Autoria própria • activity_main.xml: Arquivo de layout que possui um LinearLayout com orientação vertical e dois botões. 4.2.2. Resultado da avaliação Para esse cenário, a InicioActivity.java foi executada no emulador e, ao concluir seu carregamento, o botão com o texto “Adequado” foi pressionado. Este procedimento efetuou a medição da memória heap antes e depois da execução do laço mencionado anteriormente. Para a primeira execução, o resultado obtido foi 1,9 MB de memória antes da execução do laço e 2,2 MB memória após a realização do mesmo. 41 Esse procedimento foi executado mais quatro vezes e os resultados obtidos estão listados na Tabela 9. Tabela 9 – Resultado da execução utilizando os tipos de dados primitivos adequadamente Ciclo Memória antes da execução (MB) Memória depois da execução (MB) % Tempo de execução (s) 1 1,9 2,2 15,79 1,630 2 1,9 2,2 15,79 1,790 3 1,9 2,2 15,79 1,726 4 1,9 2,2 15,79 1,602 5 1,9 2,2 15,79 1,581 Conclusão Aumento do consumo de memória RAM de 15,79%. Aumento do consumo de memória RAM de 15,79%. Aumento do consumo de memória RAM de 15,79%. Aumento do consumo de memória RAM de 15,79%. Aumento do consumo de memória RAM de 15,79%. Fonte: Autoria própria É possível verificar que houve um aumento no consumo de memória de, em média, 15,79%. Desta forma, pode-se concluir que após pressionar o botão com o texto “Adequado”, houve um acréscimo no consumo da heap. Em adição, pode-se verificar que o tempo de execução foi, em média, 1,666 segundos. Depois desta execução, o mesmo processo foi realizado, desta vez, pressionando o botão com o texto “Inadequado”. Este procedimento, da mesma forma que o anterior, realizou a medição da memória heap antes e depois da execução do laço. Na primeira execução, o resultado obtido foi 1,9 MB de memória antes da execução do laço e 2,3 MB de memória após realização do mesmo. Esse procedimento foi executado mais 4 vezes e os resultados obtidos estão listados na Tabela 10. 42 Tabela 10 – Resultado da execução utilizando os tipos de dados primitivos inadequadamente Ciclo Memória antes da execução (MB) Memória depois da execução (MB) % Tempo de execução (s) 1 1,9 2,3 21,05 1,447 2 1,9 2,3 21,05 1,515 3 1,9 2,3 21,05 1,583 4 1,9 2,3 21,05 1,437 5 1,9 2,3 21,05 1,500 Conclusão Aumento do consumo memória de 21,05%. Aumento do consumo memória de 21,05%. Aumento do consumo memória de 21,05%. Aumento do consumo memória de 21,05%. Aumento do consumo memória de 21,05%. de de de de de Fonte: Autoria própria É possível verificar que houve um aumento no consumo de memória de, em média, 21,05%. Desta forma, pode-se concluir que após pressionar o botão com o texto “Inadequado”, houve um acréscimo no consumo da heap. Em adição, pode-se verificar que o tempo de execução foi, em média, 1,496 segundos. As Figuras 21 e 22 mostram o tempo de execução e o consumo de memória após a execução do procedimento, respectivamente. Figura 21 - Tempo de execução dos tipos primitivos adequados e inadequados Figura 22 - Consumo de memória dos tipos primitivos adequados e inadequados 2,000 2,5 1,666 2,3 2,0 1,5 MB Segundos 1,496 2,2 1,000 1,0 0,5 0,000 0,0 Tempo de execução Adequado Inadequado Fonte: Autoria própria Consumo de memória Adequado Inadequado Fonte: Autoria própria É possível identificar que o consumo de memória do uso adequado dos tipos primitivos foi, em média, 4,35% inferior ao dos tipos de dados inadequados. Em 43 contrapartida, o tempo de execução da primeira implementação foi, em média, 11,36% superior a segunda forma. 4.3 Uso de Listas Nesta seção será abordado o uso das classes LinkedList e ArrayList, pois estudos [17] [35] mostram que o desempenho dessas implementações são diferentes dependendo da operação utilizada, porém não medem a quantidade de memória RAM que pode ser economizada. Ambas são implementações da interface List, permitem entradas duplicadas e seus elementos podem ser acessados por meio de índice (posição da lista). A primeira classe redimensionada. possui tamanho preciso, Já segunda implementação a ou seja, não não é precisa ser precisamente redimensionada e o tamanho por entrada do ArrayList é menor do que no LikendList. 4.3.1. Cenário Para realizar as medições, foi implementado um aplicativo Android que continha pacotes, AndroidManifest.xml, ArrayListActivity2.java, InicioActivity.java, LinkedListActivity.java e ArrayListActivity1.java, activity_main.xml, sendo detalhados a seguir: • AndroidManifest.xml: Contemplava a declaração de três activities; • InicioActivity.java: Principal activity com dois botões (LinkedList e ArrayList1). O primeiro botão iniciava a “LinkedListActivity.java” e o segundo inicializava a “ArrayList1Activity.java”; • LinkedListActvity.java: Possuía uma repetição que adicionava todos os números de 0 (zero) à 49999 (quarenta e nove mil novecentos e noventa e nove) em uma LinkedList utilizando o método (add); • ArrayList1Activity.java: Continha uma iteração que acrescentava todos os números de 0 (zero) à 49999 (quarenta e nove mil novecentos e noventa e nove) em um ArrayList utilizando o método (add); 44 • activity_main.xml: Arquivo de layout que possuía um LinearLayout com orientação vertical e dois botões. 4.3.2. Resultado da avaliação Para esse cenário, a InicoActivity.java foi inicializada no emulador e, ao concluir seu carregamento, o botão com o texto “LinkedList” foi pressionado. Este procedimento, efetuou a medição da memória heap antes e depois da execução do laço mencionado anteriormente. Para a primeira execução, o resultado obtido foi 1,9 MB de memória antes da execução do laço e 3,8 MB de memória após realização do mesmo. Esse procedimento foi executado mais quatro vezes e os resultados obtidos estão listados na Tabela 11: Tabela 11 – Resultado da execução utilizando LinkedList Ciclo Memória antes da execução (MB) Memória depois da execução (MB) % Tempo de execução (s) 1 1,9 3,8 100 6,137 2 1,9 3,8 100 6,268 3 1,9 3,8 100 6,127 4 1,9 3,8 100 6,159 5 1,9 3,8 100 6,093 Conclusão Aumento do consumo de memória RAM em 100%. Aumento do consumo de memória RAM em 100%. Aumento do consumo de memória RAM em 100%. Aumento do consumo de memória RAM em 100%. Aumento do consumo de memória RAM em 100%. Fonte: Autoria própria É possível verificar que houve um aumento no consumo memória de, em média, 100%. Desta forma, pode-se concluir que após executar o procedimento citado anteriormente houve um acréscimo no consumo da heap. Em adição, pode-se verificar que o tempo de execução ficou em média de 6,157 segundos. Depois desta execução, o mesmo processo foi realizado, desta vez, pressionando o botão com o texto “ArrayList1”. Este procedimento da mesma forma que o anterior, realizou a medição da memória heap antes e depois da execução do laço. Na primeira execução o resultado obtido foi 1.9 MB de 45 memória antes da execução do laço e 2.9 MB de memória após realização do mesmo. Esse procedimento, foi executado mais 4 vezes e os resultados obtidos estão listados na Tabela 12. Tabela 12 – Resultado da execução utilizando ArrayList Ciclo Memória antes da execução (MB) Memória depois da execução (MB) % Tempo de execução (s) 1 1,9 2,9 52,63 3,294 2 1,9 2,9 52,63 3,134 3 1,9 2,9 52,63 3,479 4 1,9 2,9 52,63 3,228 5 1,9 2,9 52,63 3,440 Conclusão Aumento do consumo memória em 52,63%. Aumento do consumo memória em 52,63%. Aumento do consumo memória em 52,63%. Aumento do consumo memória em 52,63%. Aumento do consumo memória em 52,63%. de de de de de Fonte: Autoria própria É possível verificar que houve um aumento no consumo memória de, em média, 52,63%. Desta forma, pode-se concluir que após executar o procedimento citado anteriormente houve um acréscimo no consumo da heap. Em adição, pode-se verificar que o tempo de execução foi, em média, 3,315 segundos. As Figuras 23 e 24 mostram o tempo de execução e o consumo de memória após a execução do procedimento, respectivamente. 46 Figura 23 - Tempo de execução do procedimento utilizando ArrayList e LinkedList 7,000 Figura 24 – Consumo de memória do procedimento utilizando ArrayList e LinkedList 3,8 4,0 6,157 6,000 4,000 3,315 3,000 2,000 MB Segundos 2,9 3,0 5,000 2,0 1,0 1,000 0,000 0,0 Tempo de execução LinkedList Consumo de memória ArrayList Fonte: Autoria própria LinkedLis ArrayList Fonte: Autoria própria É possível identificar que o consumo de memória da classe ArrayList foi, em média, 23,68% inferior ao uso da classe LinkedList. Em adição, o tempo de execução da classe ArrayList foi, em média, 46,16% mais rápida que a classe LinkedList. 4.4 Utilização de tipos primitivos e classe wrappers Nesta seção será abordado o uso dos tipos primitivos e classes wrappers. Pesquisas [17] [23] mostram que as classes wrappers são mais lentas e consumem mais memória, devido à sobrecarga adicional de metadados (Class, Flags e Lock) utilizados pela JVM para descrever o objeto Java. No entanto esses estudos não mostram a quantidade de memória RAM e tempo de execução que são desperdiçados. O primeiro não representa uma classe, mas sim valores básicos. Os tipos primitivos em Java são byte, short, int, long, float, double, char ou boolean e ficam armazenados na stack. Já o segundo é armazenado na heap e é utilizado para referenciar um objeto, esta referência pode ser nula. 47 4.4.1. Cenário Para realizar as medições, foi desenvolvido um aplicativo Android que continha pacotes, AndroidManifest.xml, InicioActivity.java, PrimitivoIntActivity.java, PrimitivoLongActivity.java, ObjetoIntegerActivity.java, ObjetoIntegerActivity.java e activity_main.xml, sendo detalhados a seguir: • AndroidManifest.xml: Contempla a declaração de cinco activities; • InicioActivity.java: Principal activity com quatro botões (int, Integer, long e Long). O primeiro botão inicia a “PrimitivoIntActvity.java”, o segundo inicializa a “PrimitivoIntegerActvity.java”, “PrimitivoLongActivity.java” e o o último terceiro direciona chama para “ObjetoLongActivity.java”; • PrimitivoIntActvity.java: Possuía uma repetição que atribuía em cada posição de um vetor de int todos os números de 0 (zero) à 24999 (vinte e quatro mil novecentos e noventa e nove); • PrimitivoIntegerActvity.java: Continha uma iteração que atribuía em cada posição de um vetor de Integer todos os números de 0 (zero) à 24999 (vinte e quatro mil novecentos e noventa e nove); • PrimitivoLongActivity.java: Continha uma repetição que atribuía em cada posição de um vetor de long todos os números de 0 (zero) à 24999 (vinte e quatro mil novecentos e noventa e nove); • ObjetoLongActivity.java: Possuía uma iteração que atribuía em cada posição de um vetor de Long todos os números de 0 (zero) à 24999 (vinte e quatro mil novecentos e noventa e nove); • activity_main.xml: Arquivo de layout que possuía um LinearLayout com orientação vertical e quatro botões. 4.4.2. Resultado da avaliação Esta seção irá efetuar a coleta de dados dos tipos primitivos (int e long) e dos tipos por referência (Integer e Long). 48 4.4.2.1. Uso de Integer e int Para esse cenário, a InicioActivity.java foi executada no emulador e, ao concluir seu carregamento o botão com o texto “int” foi pressionado. Esta análise efetua a medição da memória heap antes e depois da execução do laço mencionado anteriormente. Para a primeira execução o resultado obtido foi 1,9 MB de memória antes da execução do laço e 2,0 MB de memória após realização do mesmo. Esse procedimento foi executado mais quatro vezes e os resultados obtidos estão listados na Tabela 13. Tabela 13 – Resultado da execução utilizando o tipo primitivo int Ciclo Memória antes da execução (MB) Memória depois da execução (MB) % Tempo de execução (s) 1 1,9 2,0 5,26 0,028 2 1,9 2,0 5,26 0,016 3 1,9 2,0 5,26 0,014 4 1,9 2,0 5,26 0,018 5 1,9 2,0 5,26 0,015 Conclusão Aumento do consumo de memória RAM de 5,26%. Aumento do consumo de memória RAM de 5,26% Aumento do consumo de memória RAM de 5,26% Aumento do consumo de memória RAM de 5,26% Aumento do consumo de memória RAM de 5,26% Fonte: Autoria própria É possível verificar que houve um aumento no consumo memória de, em média, 5,26%. Desta forma, pode-se concluir que após pressionar o botão com o texto “int” houve um acréscimo no consumo da heap. Em adição, pode-se verificar que o tempo de execução foi, em média, 0.018 segundos. Depois desta execução, o mesmo processo foi realizado, desta vez, pressionando o botão com o texto “Integer”. Este procedimento da mesma forma que o anterior, realizou a medição da memória heap antes e depois da execução do laço. Na primeira execução, o resultado obtido foi 1.9 MB de memória antes da execução do laço e 2,4 MB de memória após realização do mesmo. Esse procedimento, foi executado mais 4 vezes e os resultados obtidos estão listados na Tabela 14. 49 Tabela 14 – Resultado da execução utilizando a classe wrapper Integer Ciclo Memória antes da execução (MB) Memória depois da execução (MB) % Tempo de execução (s) 1 1,9 2,4 26,32 2,617 2 1,9 2,4 26,32 2,422 3 1,9 2,4 26,32 2,533 4 1,9 2,4 26,32 2,396 5 1,9 2,4 26,32 2,457 Conclusão Aumento do consumo de memória RAM de 26,32%. Aumento do consumo de memória RAM de 26,32%. Aumento do consumo de memória RAM de 26,32%. Aumento do consumo de memória RAM de 26,32%. Aumento do consumo de memória RAM de 26,32%. Fonte: Autoria própria É possível verificar que houve um aumento no consumo memória de, em média, 26,32%. Desta forma, pode-se concluir que após pressionar o botão com o texto “Integer” houve um acréscimo no consumo da heap. Em adição, pode-se verificar que o tempo de execução foi, em média, 2,485 segundos. As Figuras 25 e 26 mostram o tempo de execução e o consumo de memória após a execução do procedimento, respectivamente. Figura 25 - Tempo de execução do procedimento utilizando int e Integer Figura 26 – Consumo de memória do procedimento utilizando int e Integer 3,000 2,4 2,5 2,485 2,0 2,0 2,000 MB Segundos 2,500 1,500 1,5 1,0 1,000 0,5 0,500 0,018 0,000 0,0 Tempo de execução int Integer Fonte: Autoria própria Consumo de memória int Integer Fonte: Autoria própria É possível identificar que o consumo de memória do tipo primitivo int foi, em média, 16,67% inferior ao uso da classe wrapper Integer. Em complemento, o 50 tempo de execução do primeiro método foi, em média, 99,28% mais rápido que o segundo método. 4.4.2.2. Uso de long e Long Para esse cenário, a InicioActivity.java foi executada no emulador e, ao concluir seu carregamento o botão com o texto “long” foi pressionado. Esta análise efetua a medição da memória heap antes e depois da execução do laço mencionado anteriormente. Para a primeira execução o resultado obtido foi 1.9 MB de memória antes da execução do laço e 2.1 MB de memória após realização do mesmo. Esse procedimento foi executado mais quatro vezes e os resultados obtidos estão listados na Tabela 15. Tabela 15 - Resultado da execução utilizando o tipo primitivo long Ciclo Memória antes da execução (MB) Memória depois da execução (MB) % Tempo de execução (s) 1 1,9 2,1 10,53 0,021 2 1,9 2,1 10,53 0,017 3 1,9 2,1 10,53 0,020 4 1,9 2,1 10,53 0,015 5 1,9 2,1 10,53 0,017 Conclusão Aumento do consumo de memória RAM de 10,53%. Aumento do consumo de memória RAM de 10,53%. Aumento do consumo de memória RAM de 10,53%. Aumento do consumo de memória RAM de 10,53%. Aumento do consumo de memória RAM de 10,53%. Fonte: Autoria própria É possível verificar que houve um aumento no consumo de memória de, em média, 10,53%. Desta forma, pode-se concluir que após pressionar o botão com o texto “long” houve um acréscimo no consumo da heap. Em adição, pode-se verificar que o tempo de execução foi, em média, 0,018 segundos. Depois desta execução, o mesmo processo foi realizado, desta vez, pressionando o botão com o texto “Long”. Este procedimento da mesma forma que o anterior, realizou a medição da memória heap antes e depois da execução 51 laço. Na primeira execução o resultado obtido foi 1.9 MB de memória antes da execução do laço e 2.4 MB de memória após realização do mesmo. Esse procedimento, foi executado mais 4 vezes e os resultados obtidos estão listados na Tabela 16. Tabela 16 - Resultado da execução utilizando a classe wrapper Long Ciclo Memória antes da execução (MB) Memória depois da execução (MB) % Tempo de execução (s) 1 1,9 2,4 26,32 2,075 2 1,9 2,4 26,32 1,793 3 1,9 2,4 26,32 1,964 4 1,9 2,4 26,32 2,066 5 1,9 2,4 26,32 2,107 Conclusão Aumento do consumo de memória RAM de 26,32%. Aumento do consumo de memória RAM de 26,32%. Aumento do consumo de memória RAM de 26,32%. Aumento do consumo de memória RAM de 26,32%. Aumento do consumo de memória RAM de 26,32%. Fonte: Autoria própria É possível verificar que houve um aumento no consumo memória de, em média, 26,32%. Desta forma, pode-se concluir que após pressionar o botão com o texto “Long” houve um acréscimo no consumo da heap. Em adição, pode-se verificar que o tempo de execução foi, em média, 2,001 segundos. As Figuras 27 e 28 mostram o tempo de execução e o consumo de memória após a execução do procedimento, respectivamente. Figura 27 - Tempo de execução do procedimento utilizando long e Long Figura 28 - Consumo de memória do procedimento utilizando long e Long 2,001 2,5 2,4 2,1 2,0 1,500 MB Segundos 2,000 1,000 0,500 0,018 0,000 1,5 1,0 0,5 0,0 Tempo de execução long Long Fonte: Autoria própria Consumo de memória long Long Fonte: Autoria própria 52 É possível identificar que o consumo de memória do tipo primitivo long foi, em média, 12,5% inferior ao uso da classe wrapper Long. Em complemento, o tempo de execução da do primeiro método foi, em média, 99,10% mais rápido que o segundo método. 4.5 Uso de threads Existem situações nas quais é preciso executar duas ou mais tarefas ao mesmo tempo, como por exemplo, em um computador, escutar músicas e escrever um documento. Em Java, quando o assunto é processamento paralelo fala-se de Threads [19]. Estudos [36] [37] mostram que o uso inadequado de threads pode causar vazamento de memória e redução de desempenho. 4.5.1. Cenário Para realizar as medições, foi desenvolvido um aplicativo Android que continha pacotes, AndroidManifest.xml, InicioActivity.java, Thread1Activity.java, Thread2Activity.java, Thread3Activity.java e activity_main.xml, sendo detalhados a seguir: • AndroidManifest.xml: Contemplava a declaração de quatro activities; • InicioActivity.java: Principal activity com três botões (Thread1, Thread2 e Thread3). O primeiro botão iniciava a “Thread1Actvity.java”, o segundo inicializava a “Thread2Actvity.java” e o ultimo chamava “Thread3Actvity.java”; • Thread1Actvity.java: Na criação da activity era instanciada uma nova thread de longa duração; • Thread2Actvity.java: Possuía a declaração de uma classe interna, privada e estática que estendia a classe Thread. Na criação da activity o método start era invocado; • Thread3Actvity.java: Possuía a declaração de uma classe interna, privada e estática que estendia a classe thread. Na criação da activity 53 o método start era invocado. O método onDestroy foi sobrescrito, implementando uma política para o cancelamento de thread; • activity_main.xml: Arquivo de layout que possuía um LinearLayout com orientação vertical e tres botões. A implementação das classes (Thread1Actvity.java, Thread2Actvity.java e Thread3Actvity.java) podem ser observadas com mais detalhes no APÊNDICE A. 4.5.2. Resultado da avaliação Para esse cenário, a InicioActivity.java foi executada no emulador e, ao concluir seu carregamento o botão com o texto “Thread1” foi pressionado, neste momento uma thread de longa duração foi iniciada, e depois foram efetuadas 10 (dez) rotações de tela, ao efetuar a rotação de tela, a activity atual e destruída e recriada, porém o Android não irá limpar a memória associada a esta activity, causando um vazamento de memória e uma redução de desempenho [36]. Quando a política de cancelamento de threads está implementada, não ocorre o problema mencionado anteriormente. Esta análise efetua a medição da memória heap antes e depois do processo mencionado anteriormente. Para a primeira execução o resultado obtido foi: 1,9 MB de memória antes da execução e 2.4 MB de memória após realização do procedimento. Esse processo foi executado mais quatro vezes e os resultados obtidos estão listados na Tabela 17. 54 Tabela 17 - Resultado da execução utilizando uma classe de thread anônima Ciclo Memória antes da execução (MB) Memória depois da execução (MB) % Número de threads 1 1,9 2,4 26,32 11 2 1,9 2,4 26,32 11 3 1,9 2,4 26,32 11 4 1,9 2,4 26,32 11 5 1,9 2,4 26,32 11 Conclusão Aumento do consumo de memória RAM de 26,32%. Aumento do consumo de memória RAM de 26,32%. Aumento do consumo de memória RAM de 26,32%. Aumento do consumo de memória RAM de 26,32%. Aumento do consumo de memória RAM de 26,32%. Fonte: Autoria própria É possível verificar que houve um aumento no consumo memória de, em média, 26,32%. Desta forma, pode-se concluir que após pressionar o botão com o texto “Thread1” e rotacionar a tela 10 (dez) vezes houve um acréscimo no consumo da heap. Depois desta análise, o mesmo processo foi realizado, desta vez, pressionando o botão com o texto “Thread2”, neste momento uma classe interna, privada e estática que estendia a classe Thread era instanciada e invocava o método start. Esta análise da mesma forma que a anterior, realizou a medição da memória heap antes e depois do procedimento mencionado anteriormente. Na primeira execução o resultado obtido foi 1,9 MB de memória antes da execução e 2,2 MB de memória após realização do procedimento. Esse processo, foi executado mais 4 vezes e os resultados obtidos estão listados na Tabela 18. 55 Tabela 18 - Resultado da execução utilizando uma classe de thread privada e estática que estendia a classe Thread Ciclo Memória antes da execução (MB) Memória depois da execução (MB) % Número de threads 1 1,9 2,2 15,79 11 2 1,9 2,2 15,79 11 3 1,9 2,2 15,79 11 4 1,9 2,2 15,79 11 5 1,9 2,2 15,79 11 Conclusão Aumento do consumo de memória RAM de 15,79%. Aumento do consumo de memória RAM de 15,79%. Aumento do consumo de memória RAM de 15,79%. Aumento do consumo de memória RAM de 15,79%. Aumento do consumo de memória RAM de 15,79%. Fonte: Autoria própria É possível verificar que houve um aumento no consumo de memória de, em média, 15,79%. Desta forma, pode-se concluir que após pressionar o botão com o texto “Thread2” e rotacionar a tela (10) dez vezes houve um acréscimo no consumo da heap. Depois desta análise, o mesmo processo foi realizado, desta vez, pressionando o botão com o texto “Thread3”, neste momento uma classe interna, privada e estática que estendia a classe Thread era instanciada e invocava o método start. Esta análise da mesma forma que a anterior, realizou a medição da memória heap antes e depois do procedimento mencionado anteriormente. Na primeira execução o resultado obtido foi 1,9 MB de memória antes da execução e 2,2 MB de memória após realização do procedimento. Esse processo, foi executado mais 4 vezes e os resultados obtidos estão mencionado na Tabela 19. 56 Tabela 19 - Resultado da execução utilizando uma classe de thread privada e estática que estendia a classe Thread com política de cancelamento Ciclo Memória antes da execução (MB) Memória depois da execução (MB) % Número de threads 1 1,9 2,2 15,79 1 2 1,9 2,2 15,79 1 3 1,9 2,2 15,79 1 4 1,9 2,2 15,79 1 5 1,9 2,2 15,79 1 Conclusão Aumento do consumo de memória RAM de 15,79%. Aumento do consumo de memória RAM de 15,79%. Aumento do consumo de memória RAM de 15,79%. Aumento do consumo de memória RAM de 15,79%. Aumento do consumo de memória RAM de 15,79%. Fonte: Autoria própria É possível verificar que houve um aumento no consumo memória de, em média, 15,79%. Desta forma pode se concluir que após pressionar o botão com o texto “Thread3” e rotacionar a tela (10) vez houve um acréscimo no consumo da heap. As Figuras 29 e 30 mostram o consumo de memória e quantidade de threads que foram executadas paralelamente após a execução dos procedimentos, respectivamente. Figura 29 - Consumo de memória do procedimento utilizando threads Figura 30 – Quantidade de threads executadas paralelamente 3,0 2,4 2,5 2,2 2,2 Thread MB 2,0 1,5 1,0 0,5 0,0 Consumo de memória Modo 1 Modo 2 Modo 3 Fonte: Autoria própria 11 11 10 9 8 7 6 5 4 3 2 1 0 11 1 Quantidade de Threads Modo 1 Modo 2 Modo 3 Fonte: Autoria própria É possível identificar que o consumo de memória do modo 1 foi superior 9,09% em média ao consumo de memória dos modos 2 e 3 que foram 57 semelhantes. Em adição, a quantidade de threads do modo 3 foi, em média, 90,91% inferior aos modos 1 e 2 que foram semelhantes. 58 5. CONCLUSÕES No decorrer deste trabalho, verificou-se que o uso de smartphones estão crescendo e que 78,6% destes aparelhos utilizam a plataforma Android. Foi evidenciado que estes dispositivos ainda possuem uma quantidade limitada de memória física. Devido a este fato, objetivou-se comparar algumas técnicas de programação já existentes na linguagem Java, a fim de identificar quais poderiam ser executadas em um menor período de tempo e quais poderiam evitar o consumo desnecessário de memória RAM. Dessa forma, foram desenvolvidos aplicativos para a plataforma Android e efetuada a coleta da memória heap dos aplicativos através da ferramenta Eclipse MAT. Também foi medido o tempo de execução de cada procedimento e o número de threads que estavam sendo executadas paralelamente, quando aplicável. Os resultados obtidos após a realização a análise de dados foram: a) String X StringBuilder: O consumo de memória RAM das duas classes foi o mesmo. Em contrapartida, o tempo de execução da segunda classe foi, em média, 98,62% mais rápido que a primeira classe na concatenação de textos. b) Uso de tipos de dados primitivos (adequado e inadequado): A utilização adequada dos tipos de dados primitivos economizou, em média, 4,35% de memória RAM, porém o tempo de execução foi 10,20% superior em relação ao uso inadequado dos tipos primitivos. c) ArrayList X LinkedList: A utilização da primeira classe economizou 23,68% de memória RAM e foi 46,16% mais rápida na inserção de elementos que a segunda implementação. d) Classes wrappers (Integer e Long) X Tipo primitivo (int e long): Evidenciou que a utilização dos tipos dados primitivos (int e long) evitaram o desperdício de memória RAM de, em média, 16,67% e 12,5% respectivamente. Em adição o tempo de execução foi mais rápido, em média, 99,28% e 99,10% respectivamente. e) Uso de threads: Foi mostrado que ao utilizar uma thread privada, estática e com uma política de cancelamento foi possível evitar o desperdício de 9,09% de memória RAM e diminuir, em média, 90,91% a quantidade de threads que estavam sendo executadas paralelamente. 59 Conclui-se que o consumo de memória RAM e o tempo de execução não estão diretamente relacionados e que é possível escrever códigos que utilizam recursos diferentes, mas que fazem o mesmo efeito. Dependendo da técnica de programação utilizada, pode-se evitar o consumo desnecessário de memória RAM e/ou executar um procedimento em um menor período de execução. Desta forma, propõe-se algumas sugestões e desafios a serem abordados por trabalhos futuros: a) Identificar as vantagens e desvantagens de utilizar técnicas de programação no desenvolvimento, manutenção e usabilidade de aplicativos na plataforma Android que podem evitar o consumo desnecessário de memória RAM e que podem executar suas atividades mais rapidamente, ou seja, em um menor período de tempo. b) Analisar e comparar outras técnicas de programação já existentes na linguagem Java e identificar quais poderão consumir menos memória RAM e serem executadas em um período menor de tempo. c) Analisar a relação consumo de memória RAM X consumo de energia. 60 REFERÊNCIAS [1] “Vendas de Telefone Celular e Smartphone no Brasil (IDC e Abinee),” Teleco, 2014. [Online]. Disponível em: http://www.teleco.com.br/celprod.asp. [2] H. Gomes, “Venda de smartphone supera a de celular tradicional pela 1o vez no Brasil,” Globo, 2013. [Online]. Disponível em: http://g1.globo.com/tecnologia/noticia/2013/08/venda-de-smartphonesupera-de-celular-tradicional-pela-1-vez-no-brasil.html. [Acesso em: 19Apr-2014]. [3] “Android and iOS Continue to Dominate the Worldwide Smartphone Market with Android Shipments Just Shy of 800 Million in 2013, According to IDC,” IDC, 2014. [Online]. Disponível em: http://www.idc.com/getdoc.jsp?containerId=prUS24676414. [Acesso em: 19-Apr-2014]. [4] V. Caputo, “Android e iPhone foram 93,8% dos aparelhos vendidos em 2013,” Exame, 2014. [Online]. Disponível em: http://exame.abril.com.br/tecnologia/noticias/android-e-iphone-foram-938-dos-aparelhos-vendidos-em-2013. [5] G. Beavis, “10 best mobile phones in the world today,” Techradar, 2014. [Online]. Disponível em: http://www.techradar.com/news/phone-andcommunications/mobile-phones/20-best-mobile-phones-in-the-worldtoday-645440#articleContent. [Acesso em: 20-Apr-2014]. [6] L. Vogel, “Eclipse Memory Analyzer (MAT) - Tutorial,” vogella, 2013. [Online]. Disponível em: http://www.vogella.com/tutorials/EclipseMemoryAnalyzer/article.html#me mory_heap. [Acesso em: 27-Apr-2014]. [7] Oracle, “String (Java Platform SE 6),” Oracle. [Online]. Disponível em: http://docs.oracle.com/javase/6/docs/api/java/lang/String.html. [Acesso em: 02-Apr-2014]. [8] Oralce, “Object (Java Platform SE 6),” Oracle. [Online]. Disponível em: http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html. [Acesso em: 27-Apr-2014]. [9] G. Guerra, “Introdução a serialização de objetos,” Devmedia. [Online]. Disponível em: http://www.devmedia.com.br/introducao-a-serializacao-deobjetos/3050. [Acesso em: 27-Apr-2014]. [10] Oracle, “CharSequence (Java Platform SE 6),” Oracle. [Online]. Disponível em: 61 http://docs.oracle.com/javase/6/docs/api/java/lang/CharSequence.html. [Acesso em: 27-Apr-2014]. [11] Oracle, “Comparable (Java Platform SE 6),” Oracle. [Online]. Disponível em: http://docs.oracle.com/javase/6/docs/api/java/lang/Comparable.html. [Acesso em: 27-Apr-2014]. [12] Oracle, “StringBuilder (Java Platform SE 6),” Oracle. [Online]. Disponível em: http://docs.oracle.com/javase/6/docs/api/java/lang/StringBuilder.html. [Acesso em: 02-Apr-2014]. [13] Oracle, “Appendable (Java Platform SE 6),” Oracle. [Online]. Disponível em: http://docs.oracle.com/javase/6/docs/api/java/lang/Appendable.html. [Acesso em: 27-Apr-2014]. [14] K. Sierra and B. Bates, Use a cabeça! Java, 2nd ed. Rio de Janeiro: Alta Books, 2005, p. 484. [15] Oracle, “Primitive Data Types,” Oracle. [Online]. Disponível em: http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html. [Acesso em: 06-Apr-2014]. [16] “Collections framework,” Caelum. [Online]. Disponível em: http://www.caelum.com.br/apostila-java-orientacao-objetos/collectionsframework/#16-2-listas-java-util-list. [Acesso em: 05-Apr-2014]. [17] C. Bailey, “Do Código Java ao Heap Java,” IBM, 2012. [Online]. Disponível em: http://www.ibm.com/developerworks/br/library/jcodetoheap/. [Acesso em: 05-Jan-2014]. [18] R. Lanhellas, “Diferença entre ArrayList, Vector e LinkedList em Java,” Devmedia. [Online]. Disponível em: http://www.devmedia.com.br/diferenca-entre-arraylist-vector-e-linkedlistem-java/29162. [Acesso em: 05-Apr-104AD]. [19] M. Palheta, “Threads,” Gloogle, 2011. [Online]. Disponível em: https://sites.google.com/site/marciopalheta/treinamentosjava/treinamentos-jse/14.Threads.pdf?attredirects=0&d=1. [Acesso em: 06-Apr-2014]. [20] Oracle, “Thread (Java Platform SE 6),” Oracle. [Online]. Disponível em: http://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html. [Acesso em: 06-Apr-2014]. [21] Caelum, “Programação Concorrente e Threads,” Caelum. [Online]. Disponível em: http://www.caelum.com.br/apostila-java-orientacaoobjetos/programacao-concorrente-e-threads/#17-1-threads. [Acesso em: 06-Apr-2014]. [22] Deitel, Java - Como Programas. Pearson, 2005, p. 1152. 62 [23] R. Lanhellas, “Introdução aos Wrappers em Java,” Devmedia. [Online]. Disponível em: http://www.devmedia.com.br/introducao-aos-wrappersem-java/28605. [Acesso em: 06-Apr-2014]. [24] R. Lecheta, Google Android, 2nd ed. São Paulo: Novatec, 2010, p. 608. [25] C. E. Tosin, “Conhecendo o Android,” 2011. [Online]. Disponível em: http://www.softblue.com.br/blog/home/postid/11/CONHECENDO+O+AND ROID. [Acesso em: 13-Apr-2014]. [26] C. E. Tosin, “Memory Leak em Java ?,” 2008. [27] C. C. Prodanov and F. C. De, Metodologia da pesquisa e elaboração de dissertação, 4th ed. Florianópolis: UFSC, 2013, p. 277. [28] R. K. Yin, Estudo de caso: planejamento e métodos, 2nd ed. Porto Alegre: Book-man, 2001. [29] A. C. Gil, Como Elaborar Projetos de Pesquisa, 4th ed. São Paulo: Atlas, p. 176. [30] “Eclipse Memory Analyzer Open Source Project,” Eclipse. [Online]. Disponível em: https://www.eclipse.org/mat/. [Acesso em: 15-Jan-2014]. [31] “Série 5 - 530U3C-AD5 - GERAL | SAMSUNG,” Samsung. [Online]. Disponível em: http://www.samsung.com/br/consumer/itproducts/notebooks-netbooks/ultra-portable/NP530U3C-AD5BR. [Acesso em: 16-Jan-2014]. [32] C. Vinicius, “Java: Diferenças entre as classes String, StringBuffer e StringBuilder,” Oficina da NET. [Online]. Disponível em: http://www.oficinadanet.com.br/post/2124java_diferencas_entre_as_classes_string_stringbuffer_e_stringbuilder. [Acesso em: 05-Apr-2014]. [33] P. Silveira, “Revisitando a concatenação de Strings: StringBuilder e StringBuffer,” Caelum, 2010. [Online]. Disponível em: http://blog.caelum.com.br/revisitando-a-concatenacao-de-stringsstringbuilder-e-stringbuffer/. [Acesso em: 01-Apr-2014]. [34] M. Junior, “Tipos Primitivos - Java,” Java com café. [Online]. Disponível em: http://www.javacomcafe.com/2010/07/tipos-primitivos-java.html. [35] X Wang, “ArrayList vs. LinkedList vs. Vector,” Programcreek. [Online]. Disponível em: http://www.programcreek.com/2013/03/arraylist-vslinkedlist-vs-vector/. [Acesso em: 05-Jan-2014]. [36] A. Lockwood, “Activitys, Threads, & Memory Leaks,” Androiddesignpatterns, 2013. [Online]. Disponível em: 63 http://www.androiddesignpatterns.com/2013/04/activitys-threads-memoryleaks.html. [Acesso em: 20-Mar-2014]. [37] M. Brylski, “Leaking Thread,” Modelrefactoring, 2013. [Online]. Disponível em: http://www.modelrefactoring.org/smell_catalog/smells/leaking_thread.html . [Acesso em: 21-Mar-2014]. [38] M. S. Vaz, “Introdução a Metadados,” Devmedia. [Online]. Disponível em: http://www.devmedia.com.br/introducao-a-metadados/1883. 64 APÊNDICES APÊNDICE A – Modos de threads analisados no experimento Figura 31 - Utilizando uma classe de thread privada e estática que estende a classe Thread com política de cancelamento Fonte: Autoria própria 65 Figura 32 – Utilizando uma classe de thread anônima Fonte: Autoria própria Figura 33 - Utilizando uma classe de thread privada e estática que estende a classe Thread Fonte: Autoria própria