Imergindo Na Jvm

June 4, 2018 | Author: Jean Lopes | Category: Data Type, Class (Computer Programming), Thread (Computing), Pointer (Computer Programming), Java (Programming Language)
Report this link


Description

Imergindo na JVM Tabela de conteúdos 1. Introduction 2. Crédito 3. Sobre o Autor 4. Falando um pouco sobre JVM 5. Se queres prever o futuro, estuda o passado i. Histórico da JVM i. JDK Alpha e Beta (1995) ii. JDK 1.1 (19 de fevereiro de 1997) iii. J2SE 1.2 (8 de dezembro de 1998) iv. J2SE 1.3 (8 de maio de 2000) v. J2SE 1.4 (6 de fevereiro de 2002) vi. J2SE 5.0 (30 de setembro de 2004) vii. Java SE 6 (11 de dezembro de 2006) viii. Java SE 7 (28 de julho de 2011) ix. Java SE 8 (18 de março de 2014) 6. Funcionamento básico da JVM 7. Registradores da JVM i. Program Counter ii. Java Stack (Java virtual machine stack) i. Stack Frame) i. Stack variables ii. Stack Operand iii. Frame Data iii. Native Method Stacks iv. Method Area v. Heap Space vi. Cache de código i. Just In Time (JIT) Compilation vii. Recapitulando 8. ByteCodes i. Carregar e salvar informações ii. Operações aritméticas iii. Conversão de valores iv. Criação e manipulação de objetos v. Instruções condicionais vi. Chamada de métodos e retorno de valores vii. Classes após compilação 9. Ciclo de vida de uma classe 10. Garbage Collector i. Implementação Serial ii. Implementação Paralelo iii. Implementação Concurrent iv. Implementação Incremental Concurrent v. Implementação Garbage First 11. Interface Nativa Java 12. O projeto OpenJDK 2 Imergindo na JVM Imergindo na JVM Certamente o Java é atualmente uma das linguagens mais usadas e uma das mais populares no mundo, sendo que o seu maior diferencial não está na linguagem e sim na JVM (Máquina virtual Java). Conheça um pouco mais sobre esse motor, seu funcionamento e sua arquitetura para tirar melhor proveito dela em suas aplicações, além de conhecer um pouco sobre a implementação de referência e open source da JVM, o OpenJDK. O conteúdo desse E-book falará sobre: Os registradores da JVM A interface do Java com código nativo, JNI, presente em diversos pontos do JVM, dentre eles, o NIO e Gargabe Collector, O funcionamento básico do Garbage Collector Como compilar o OpenJDK ByteCode e o seu funcionamento E muito mais! Introduction 3 onde atua na área de wiki. movimento DevOps e coordenador do grupo FTD (friendstechday. Tem as motos como paixão e Muay Thai como esporte.com) Crédito 4 . Revisão do texto Weslley Andrade Servo de Jesus. criação de artigos e tradução. artwork.Imergindo na JVM Arte da capa do Ebook Raul Libório é do openSUSE Project. adepto do desenvolvimento poliglota. amante da arte de programar. Quando sobra tempo. principalmente na SE em que contribui diretamente para o projeto OpenJDK. coordenador do SouJava além de auxiliar em diversos JUGs ao redor do mundo. Presente nos maiores eventos Java e desenvolvimento de software do mundo. além de ser membro atuante do JCP. livros e ajudar revisão técnica de diversos materiais no mundo Java. inclusive ganhando um outstanding member award e Java Champion pelos seus feitos. Praticante da filosofia ágil e do desenvolvimento poliglota na Bahia. Sobre o Autor 5 . desenvolve e realiza manutenções nos principais projetos Java da Apache Foundation na qual atualmente é commiter. Open Source Instituite. Leva a sério o termo “Make the future Java” presente como membro do Java Expert Group em diversas especificações Java nas plataformas SE. Contribuiu para diversos projetos Open Source também é membro da OSI. um dos fomentadores do grupo LinguÁgil. JUG Leader do JavaBahia.Imergindo na JVM Autor Otavio Santana Um Desenvolvedor apaixonado pelo que faz. escreve artigos. ME e EE. mas principalmente com a grande ajuda da comunidade. gerar stream para dentro da JVM (Naturalmente na memória principal) e executá-lo o tornando em código nativo. a linguagem da Máquina virtual. evangelizando sobre o OpenJDK. assim nascem e morrem com a sua respectiva Thread. AMD. fazendo a devida separação entre linguagem. esse é o papel do Garbage Collector. A JVM open source e . fará a distinção básica entre o Java linguagem e da máquina virtual. RedHat. Intel. se tornou a implementação de referência. Conheça um pouco mais sobre as implementações e em quais situações elas são mais aconselhadas. O bytecode. Para facilitar o entendimento do leitor esse trabalho foi dividido em seis partes: A primeira falará um pouco sobre o Java. mas são graças aos seus opcodes que a JVM é multiplataforma. Falando um pouco sobre JVM 6 . Google. plataforma e máquina virtual além de falar um pouco sobre a história do Java e da sua evolução junto com as versões. Será o alvo dessa terceira parte do trabalho. A JVM consiste em um processo básico de pegar a informação da classe. caso essa classe tenha um pai ou implemente interfaces elas serão carregadas antes dessa classe X. só é carregada a classe X no momento em que ela for chamada. Toda classe possui um ciclo de vida e conheça um pouco mais sobre este ciclo na parte número cinco. já que a última precisa ser compilada para que a linguagem seja multiplataforma. identificando e corrigindo bugs). Com esse objetivo estou criando esse pequeno texto.a partir da versão 7. dentre as mais populares está a HotSpot (também conhecida como a JVM da Oracle). Um grande diferencial da JVM é o recurso de gerenciamento automático da memória. Para finalizar será demonstrada uma visão prática do JNI e do projeto OpenJDK além dos conceitos de compilar a JVM. Ao contrário do que muitas pessoas imaginam. além da estrutura que a classe adquire após o processo de compilação. Em seguida se falará sobre o funcionamento básico da JVM. esse processo de carregar uma classe é feita em tempo de execução. o ciclo de vida da JVM e dos processos em paralelo que nascem com uma aplicação Java. o bytecode. A JVM vem sendo alvo de muitos estudos e pesquisas. esse processo consistem em matar e recuperar memória de objetos que não estão mais sendo utilizados. afinal conhecer bem a JVM vai garantir ao desenvolvedor Java. que dentre as diversas frentes de trabalho que existem podemos destacar o Adote o OpenJDK que visa a evolução da plataforma e do Java Livre (ajudando na refatoração. pouco é explicado sobre ela. ou seja. Esse material é fruto dos meus trabalhos junto com o OpenJDK. Saberá quais registradores serão compartilhados por todas as Threads e aqueles que não serão. sendo que o seu maior diferencial não está na linguagem e sim na JVM. existem milhões de máquinas virtuais. máquina virtual Java. Saber aonde fica cada informação dentro da JVM e o nome dos seus respectivos registradores. maneiras para tirar o melhor proveito da linguagem e da plataforma além de programar de maneira mais eficiente levando em consideração tudo o que a JVM pode fazer por ele e ajudando a mesma a te ajudar. O OpenJDK é um projeto é vivo com ajuda de muitas empresas (Oracle. ajudar a comunidade brasileira a conhecer a JVM.Imergindo na JVM Falando um pouco sobre JVM Certamente o Java é atualmente uma das linguagens mais usadas e populares no mundo. etc. Nessa parte se verá quão diferente é o seu código em Java e do produto gerado.). não basta estar apenas no import. java virtual machine ou máquina virtual java.class . Essas modificações são gerenciadas pelo JCP ou Java Community Process (o comitê que rege as mudanças da plataforma java com cerca de 30 empresas). que são as instruções da JVM (daí a possibilidade de portar outras linguagens para a JVM. já que ele não roda Java e sim o bytecode). tem sua história inciada em 1992. é orientado a objetos e se tornou popular em conjunto com a web. A JVM não conhece absolutamente nada da linguagem Java. Com o passar do tempo a máquina virtual foi evoluindo e ficando cada vez mais complexa. Se queres prever o futuro. estuda o passado 7 . Do seu início até a presente data o Java teve diversas versões.Imergindo na JVM Se queres prever o futuro. estuda o passado JVM. especificações que fornecem tais modificações e melhorias. que vem no formato . a partir de JSRs (Java Specification Requests). Esse class é o código compilado e representa uma classe ou interface em java. A linguagem Java possui uma sintaxe similar ao C++. O Green Project na época a linguagem era denominada de oak. A documentação da linguagem fica no JSL (Java Language Specification) e a documentação da JVM fica no Java Virtual Machine Specification. apenas o seu bytecode. A JVM funciona como o alicerce da plataforma Java ficando responsável por tratar todas as plataformas e Sistemas Operacionais de modo independente para a linguagem. como linguagem. plataforma e máquina virtual é interessante conhecer um pouco sobre a evolução que o Java vem sofrendo. Histórico da JVM 8 .Imergindo na JVM Histórico da JVM Antes de se falar dos aspectos do Java. O projeto nasceu em 1995 e a partir desta data veio sofrendo constante evolução com ajuda de empresas e da comunidade. 2 - JDK 1. que também foi o primeiro nome da linguagem.1.Imergindo na JVM JDK Alpha e Beta (1995) Nas versões alfas e betas se tiveram uma máquina instável. JDK Alpha e Beta (1995) 9 .2 foi lançado a primeira versão estável.0 (23 de janeiro de 1996) Com o código nome Oak.0. Na versão 1. 1. nenhuma modificação em tempo real era possível. JDK 1.1 (19 de fevereiro de 1997) Grandes melhorias e refatorações nos modelos de evento do AWT Inner class adicionado a linguagem JavaBeans JDBC RMI Reflection que suportava apenas introspecção.Imergindo na JVM JDK 1.1 (19 de fevereiro de 1997) 10 . uma implementação CORBA IDL para interoperabilidade Collections framework J2SE 1.Imergindo na JVM J2SE 1. Essa e as outras versões foram denominadas de Java 2.2 (8 de dezembro de 1998) 11 . Houve modificações significantes nessa versão triplicando o código para 1520 classes em 59 pacotes incluindo: A palavra-chave strictfp A api do Swing foram integrados ao Core Adicionando o JIT compilador Java Plug-in Java IDL. J2SE Java 2 Platform. Standard Edition.2 (8 de dezembro de 1998) Com o codinome Plaground. 3 (8 de maio de 2000) Com o codinome Kestrel.Imergindo na JVM J2SE 1.3 (8 de maio de 2000) 12 . RMI foi modificado para suportar a compatibilidade opcional com CORBA JavaSound Java Naming and Directory Interface (JNDI) incluído em bibliotecas centrais Java Platform Debugger Architecture (ACDP) Sintéticos classes de proxy J2SE 1.2 J2SE JVM). as modificações mais importantes foram: HotSpot JVM incluído (a JVM HotSpot foi lançado em abril de 1999 para os 1. prefs) J2SE 1.util. Suporte ao Protocolo de internet versão 6 (IPv6) Chamadas de IO (chamado de NIO) novos Input/Output (JSR 51) API de loggin (JSR 47) API para ler e escrever imagens in formatos como JPED e PNG Integração com o XML e XSLT (JAXP) na JSR 63 Novas integrações com extensões de segurança e criptografia (JCE. JSSE. Java Web Start incluído (JSR 56). foi a primeira versão para a plataforma desenvolvida pelo JCP como a JSR 59: A palavra-chave assert(JSR 41) Expressões regulares Encadeamento de exceção permite uma exceção de maior nível encapsule uma exceção de menor nível. API de preferências (java.Imergindo na JVM J2SE 1. JAAS).4 (6 de fevereiro de 2002) 13 .4 (6 de fevereiro de 2002) Com o codinome Merlin. Annotations: (JSR 175) Autoboxing/unboxing: Conversão automática entre os tipos primitivos e as classes encapsuladas (JSR 201).0 (30 de setembro de 2004) 14 . Enumerations: (JSR 201.Imergindo na JVM J2SE 5. O Tiger adicionou significantes melhorias para a linguagem: Generics: (JSR14).0 (30 de setembro de 2004) Com o codinome Tiger. teve seu final de vida em 8 de abril de 2008 e o encerramento do suporte dia 3 de novembro de 2009.) Varargs: for each loop Correções para o Java Memory Model(Que define como Threads interagem através da memória). Static imports Geração automática do stub para objetos RMI Novo look and feel para o Swing chamado synth Um pacote utilitário de concorrência (java. foi desenvolvida na JSR 176.concurrent) A classe Scanner para analisar dados de input streams e buffers J2SE 5.util. Suporte a Web Service através do JAX-WS (JSR 224) JDBC 4.0 Melhorias no Annotations (JSR 269) Melhorias no GUI. nessa versão a Sun substitui o nome “J2SE” e removeu o “. Java Compiler API (JSR 199): uma API para permitir chamar compilação programando JAXB 2.Imergindo na JVM Java SE 6 (11 de dezembro de 2006) Com o codinome Mustangue. como SwingWorker. tabela filtrada e ordenada Melhorias na JVM incluindo: sincronização e otimizações do compilador. Essa versão foi desenvolvida na JSR 270. Suporte a linguagem de script JSR 223): Uma API Genérica para integração com linguagens scripts e foi embutido a integração com o Mozilla JavaScript Rhino. Java SE 6 (11 de dezembro de 2006) 15 .0 (JSR 221). Melhorias no algorismo do coletor de lixo.0” do número da versão. Da Vinci Machine: Suporte para linguagens dinâmicas Projeto Coin Strings in switch Automatic resource management in try-statement Diamond Simplified varargs Binary integer literals Numeric literals mult-try Novo pacote utilitário de concorrência: JSR 166 NIO2: novos biblioteca para IO Java SE 7 (28 de julho de 2011) 16 .Imergindo na JVM Java SE 7 (28 de julho de 2011) Com o codinome Dolphin possui o maior número de atualização no Java. Foi lançado no dia 7 de Julho e foi disponibilizado no dia 28 de julho do mesmo ano. Imergindo na JVM Java SE 8 (18 de março de 2014) O Java 8 foi entregue no dia 18 de março de 2014 e nessa versão foi incluída alguns recursos que antes estavam planejados para o Java 7. Os recursos submetidos para essa versão foram baseadas em propostas de melhorias do JDK, os JEPS. Dentre essas melhorias podemos destacar: JSR 223, JEP 174: Projeto Nashorn, um executor runtime de JavaScript, permitindo a execução de código JavaScript dentro da aplicação. Esse projeto teve como objetivo ser o sucessor do Rhino, usando Invoke Dynamic em vez de reflection . JSR 335, JEP 126: Suporte para expressões lambdas JSR 310, JEP 150: Date and Time API JEP 122: Remoção do Permanent generation Java SE 8 (18 de março de 2014) 17 Imergindo na JVM Funcionamento básico da JVM Este capítulo falará um pouco sobre o funcionamento básico da JVM, que é o coração da linguagem java. Esta é responsável pela independência entre as plataformas e roda basicamente dois tipos de processos: Os escrito em java que são gerados bytecodes Os nativos que são escritas em linguagens como o C\C++ e linkadas dinamicamente para uma plataforma específica. Os métodos nativos são muito interessantes para obter informações do SO onde a JVM está em execução, além de utilizar recursos deste. E é em função disso que apesar de a linguagem ser RunAnyWhere a JVM não é, ou seja, para cada plataforma existe uma máquina virtual específica. Isso acontece, por exemplo, para usar recursos específicos da plataforma onde, por exemplo, existem chamadas distintas para trabalhar com diretório e arquivos. O único e principal motivo da JVM é rodar o aplicativo. Quando se inicia uma execução a JVM nasce e quando a aplicação termina ela morre. É criado uma JVM para cada aplicação, ou seja, se executar três vezes o mesmo código em uma mesma máquina serão iniciadas 3 JVMs. Para rodar uma aplicação basta que sua classe possua um método público e estático com o nome main e tenha como parâmetro um vetor de String . Funcionamento básico da JVM 18 Imergindo na JVM Ao iniciar uma JVM existem alguns processos que rodam em paralelos e em backgrouns e executam diversas operações e processos para manter a JVM sempre disponível: Os Timers que são responsáveis pelos eventos que acontecem periodicamente, por exemplo, interrupções, eles são usados para organizar os processos que acontecem continuamente. Os processos do Garbage Collector que é responsável por executar as atividades do coletor de lixo da JVM. Compiladores que são responsáveis por transformar bytecode em código nativo. Os ouvintes, que recebem sinais (informações) e tem como principal objetivo enviar essas informações para o processo correto dentro da JVM. Falando um pouco mais sobre esses processos paralelos ou Thread , a JVM permite que múltiplos processos executem concorrentemente, essa rotina em Java está diretamente relacionada com uma Thread nativa. Tão logo um processo paralelo em Java nasça, os seus primeiros passos são: Alocação de memória Sincronização dos objetos Criação dos registradores específicos para a mesma e a alocação da Thread nativa. Quando essa rotina gera uma exceção a parte nativa envia essa informação para a JVM que a encerra. Quando a Thread termina todos os recursos específicos, tanto para o Java quanto para a parte nativa, são entregues para a JVM. Como na linguagem, a JVM opera em dois tipos de dados: 1. Os primitivos 2. Os valores de referência. A JVM espera que toda a verificação quanto ao tipo tenha sido feito no momento da execução, sendo que os tipos primitivos não precisão de tal verificação ou inspeção já que eles operam com um tipo específico de instrução (por exemplo: iadd, ladd, fadd, e dadd para inteiro, long, float e double respectivamente). A JVM tem suporte para objetos que são ou instância de uma classe alocada dinamicamente ou um array, esses valores são do tipo reference e o seu funcionamento é semelhante ao de linguagens como C/C++. Os tipos primitivos existentes na JVM são: Numéricos Booleano returnAdress Sendo que os tipos numéricos são os valores inteiros e flutuantes. Nome Tamanho variação Valor padrão Tipo byte 8-bit -2⁷ até 2⁷ 0 inteiro short 16-bits -2¹⁵ até 2¹⁵ 0 inteiro integer 32-bits -2³² até 2³¹ 0 inteiro long 64-bits -2⁶³ até 2⁶³ 0 inteiro char 16-bits UFT-8 '\u0000' inteiro float 32-bits 0 flutuante double 64-bits 0 flutuante boolean inteiro false booleano nulo ponteiro returnAddress Funcionamento básico da JVM 19 int. Falando um pouco sobre o tipo de referência. existem basicamente dois tipos de dados: Primitivos e Referência. interfaces O Valor de referência é iniciado como null . as JVM suportam esse formato. Recapitulando. positivo e negativo infinito e não um número (abreviado como Nan é utilizado para representar valores inválidos como divisão por zero). byte. com precisão simples. na verdade eles são compilados para usar os tipos de instruções do int e o array de booleano são manipulados como array de byte . mas pode ser feito cast para qualquer tipo de referência. Funcionamento básico da JVM 20 . o nulo não é um tipo definido. tem seu funcionamento similar a ponteiros e diferentes dos tipos primitivos não podem ser modificados em tempo de execução. char). Nova York). não possui representação na linguagem. Os valores são representados com 1 para verdadeiro e 0 para falso.Imergindo na JVM Os formatos de ponto flutuante são o float . array 3. long. existem três tipos: 1. mas também podem suportar versões estendidas de double e float . e o double . As referências possuem os seus subtipos: classe. Por padrão. inteiros (short. booleano. com dupla precisão. mas zero. Os primitivos possuem returnAdress. O returnAdress é usado apenas pela JVM. não existem instruções para booleano. interface e array. flutuantes (float e double de simples e dupla precisão respectivamente). 7541985. Tantos os valores como as operações seguem o especificado no padrão IEEE para aritmética de ponto flutuante binário (ANSI/ IEEE. Na JVM o tipo booleano possui um suporte bem limitado. classes 2. Esse padrão não inclui apenas valores positivos e negativos. Registradores da JVM 21 . É necessário também que se tenha ciência de onde são armazenadas tais informações. Durante a execução de um programa existem registrados que são compartilhados entre toda a JVM e outros que tem a visibilidade da Thread corrente.Imergindo na JVM Registradores da JVM Falado um pouco sobre os tipos de dados que são armazenados na JVM e o seu tamanho. A JVM usa registradores para armazenar várias coisas sendo que para todo tipo de dado existe um local específico. Stack Frame) 22 . o returnAdress. do contrário. Se o método executado for nativo o PC será um ponteiro e não tem o seu valor definido. é criado tão logo uma Thread é criada. Ponteiros nativos 2.Imergindo na JVM Program Counter O registrador PC. cada Thread possui o seu. Program counter. ou seja. Ele pode armazenar dois tipos de dados: 1. returnAdress Esses dados possuem informações quanto a instrução que está sendo executada pela Thread . ele terá o endereço de instrução. Imergindo na JVM Java Stack (Java virtual machine stack) Assim como o PC. ele é um registrador privado para cada Thread . Ele não modifica as variáveis diretamente somente inserindo e removendo frames do registrador. esse registrador armazena frames (que será visto a frente). quando acaba o método. esse frame é descartado. variáveis locais. Tão logo a corrente Thread chama um método um novo frame é inserindo contado informações como parâmetros. invocações e resultados dos métodos. O Java Stack pode ter tamanho fixo ou determinado dinamicamente. ele serve para armazenar variáveis locais e resultados parciais. ou por interrupção. Seu funcionamento é similar a linguagens clássicas como o C . Java Stack (Java virtual machine stack) 23 . etc. Assim quando o método termina de uma maneira normal. quando ocorre uma exceção dentro do método. na ordem que foram passados. Caso o método seja da instância. Nesse vetor as variáveis double e long ocupam dois elementos do vetor e são armazenados consequentemente. o método seja estático. Variáveis do tipo int e returnAdress ocupam um elemento desse vetor ( byte . Java Stack (Java virtual machine stack) 24 .Imergindo na JVM Stack variables Cada frame contém um vetor para armazenar variáveis locais e os parâmetros e esse tamanho é definido em tempo de execução. assim o primeiro elemento será os parâmetros. short e char são convertidos para int ). não seja estático. Não haverá referência da instância que chama o método. o primeiro elemento desse vetor será ocupado pela instância que está executando esse método e em seguida os parâmetros. Caso o método seja da classe. Nesse exemplo será utilizado a soma de dois inteiros ( 10 e 20 ).10 e 20. seu passo-a-passo segue o mesmo de uma pilha convencional. como o registrador de variáveis locais os valores são armazenados em um vetor mas seus valores recuperados pela remoção do último elemento do vetor em vez de ser pelo índice.Imergindo na JVM Stack Operand Como o nome indica. Como a pilha de operação é composta por unidade de 32 bits. semelhante ao seu “irmão”. sua unidade possui o tamanho de 32 bits. Ele é baseado na estrutura de dados de Pilha (Primeiro a entrar último a sair). Pilha de operação. nesse exemplo são somados dois doubles ( 10. o ultimo que entrar será o primeiro a sair. quando for double ou long ele ocupará as duas unidades seguidas. esse registrador serve para armazenar as instruções que ocorrem dentro do método. O tamanho das variáveis acontecem de maneira semelhante as variáveis locais.20 ) Java Stack (Java virtual machine stack) 25 . Java Stack (Java virtual machine stack) 26 .Imergindo na JVM Frame Data Esse pequeno registrador possui o link da constant pool da classe que o possui o corrente método que está sendo executado. é criado tão logo uma Thread é iniciada e todas as Threads possuem o seu registrador. Native Method Stacks 27 .Imergindo na JVM Native Method Stacks Possui finalidade de armazenar variáveis e valores nativos (métodos escritos em outras linguagens). Method Area 28 . o seu retorno. A lista com os qualifieds das interfaces. o número e tipo dos parâmetros em ordem e o tipo e o seu modificador). Para cada classe carregada no Java é carregada um constant pool.Date ).Class para toda classe carregada).Object ou java. que contém as seguintes informações: O constant pool do tipo (Para cada classe Carregada é criada um pool de constant. por exemplo. essa área é compartilhada entre todas as Threads .lang.util. Informação se é uma classe ou interface. As classes contém as seguintes informações: O qualified da classe (O qualifed é o endereço da sua classe que é definido pelo pacote mais .lang. ele contém o link simbólico para os métodos e para os atributos além das constantes existentes no tipo).lang. Referência da classe (uma instância da java. O qualified da classe pai (menos para as Interfaces e o java. informações dos atributos (o nome do atributo. Por ser parte do Heap ele possui o recolhimento de memória automático.Imergindo na JVM Method Area Esse registrador tem a finalidade de armazenar logicamente o stream da classe. Os modificadores.Object ). informação dos métodos (o nome do método. Referência para o ClassLoader (classe responsável para carregar a classe) Variáveis da classe (variáveis compartilhadas entre todas as classes isso inclui as constantes). o tipo e o seu modificador). java. Garbage Collector. e o nome da Classe. Logicamente faz parte do Heap espace. O objeto de referência é constituído de dois ponteiros menores: Um apontará para o pool de objetos. esse espaço de memória também é compartilhado entre as Threads . O segundo apontará para o seu constant pool (que possui as informações da classe quanto aos atributos. O heap tem seu mecanismo de reclamar memória em tempo de execução além de mover objetos evitando a fragmentação do espaço. Uma lista de referência que apontam para os objetos que estão dentro desse vetor. local aonde estão as informações. mas eles ganham dois campos a mais: 1. etc. que define o tamanho do vetor 2.) que fica localizado no method Area. encapsulamentos. apenas aponta para o local que o possui. Representação de uma variável do tipo de referência dentro do Heap é diferente dos tipos primitivos.Imergindo na JVM Heap Space Tão logo uma instância é criada. Heap Space 29 . O tamanho. métodos. A representação dos vetores se comporta de forma semelhante as variáveis de referência. ele tem o seu mecanismo muito semelhante aos ponteiros do C/C++ já que ele não possui a informação. as informações do seu objeto ficam armazenados aqui. Imergindo na JVM Heap Space 30 . esse registrador é compartilhado por todas as Threads . Cache de código 31 .Imergindo na JVM Cache de código Esse registrador é usado para compilação e armazenamento dos métodos que foram compilados para o modo nativo pelo JIT. seja uma decisão vantajosa. Esse código nativo será armazenado dentro do cache de código em uma região fora da heap. a JVM verifica métodos críticos (regiões que executam constantemente. por exemplo) e compila para o código nativo.Imergindo na JVM Just In Time (JIT) Compilation O bytecode Java interpretado não são tão rápido quanto os códigos nativos. A JVM tenta escolher as regiões mais críticas para que mesmo com o gasto memória e poder computacional de compilar o código para nativo. para cobrir esse problema de performance. Just In Time (JIT) Compilation 32 . e tem a responsabilidade de armazenar a instância dos objetos e o streams e informações da classe respectivamente. os seus valores são indefinidos. O Heap e o method Area são compartilhadas entre a JVM. apenas aponta para a instrução que está sendo executada e possui uma por Thread .Imergindo na JVM Recapitulando Com isso foi falado sobre os registradores que contém na JVM. no entanto. vale lembrar que algumas são exclusivas por Threads ou outra não. O registrador PC não possui informações. já as pilhas Java são criados tão logo um método é iniciado ele é subdividido em frames. Recapitulando 33 . ambas as pilhas são particular por Thread . A pilha nativa são importantes para obter recursos da máquina. todas as Threads . será falado um pouco sobre o funcionamento das instruções. daí o bytecode. A maioria das operações desse código operam para um tipo específico de valor. l para long . ela possui opcode e no tamanho de 1 byte. b para byte . ByteCodes 34 . c para char . s para short . no entanto. por exemplo. Uma boa dica para saber o tipo operado é saber a letra inicial da operação: i para uma operação de inteiro. bytecodes diferentes. iload (carregar um int para a pilha) e o fload (carrega um float para a pilha) possuem operações semelhantes. Cada bytecode representa uma ação ou uma operação. f para float . d para double e a para referência.Imergindo na JVM ByteCodes Uma vez tendo noção dos registradores e aonde ficam armazenados cada valor na JVM. dload e aload ) informações da pilha de variáveis para operações e armazenar (definido por: istore. Carregar e salvar informações 35 . fload . fstore. astore) realiza o processo inverso. lload . dstore.Imergindo na JVM Carregar e salvar informações Essas instruções realizam troca de informações entre o vetor de variáveis locais e a pilha operações. lstore. sendo que carregar (definido por iload . em estouro de pilha e divisão por zero. fsub. Variável local incremente: iinc . lcmp . Comparação: dcmpg . lshr. drem. O seu processamento é subdividido em flutuantes e inteiros que possuem comportamentos diferentes para alguns resultados. iushr. bit a bit ou exclusivo: ixor. fneg. lrem. dmul. fmul. resto: irem. subtrair: isub. fadd. Operações aritméticas 36 .Imergindo na JVM Operações aritméticas: Elas são realizadas com os dois primeiros valores na pilha de operações e retornando o resultado. adicionar: iadd. lor. multiplicar: imul. fcmpl . ldiv. fdiv. fcmpg . lsub. lmul. ddiv. dcmpl . lshl. dneg. divisão: idiv. dsub. bit a bit "and": iand. lushr. negação: ineg. frem. sidh. lneg. ladd. a terra. deslocar: ishl. dadd. por exemplo. bit a bit "or": ior. lxor. essa variável pode ter seu tipo ampliado como: Promoção: int para long . e d2f ) vale lembrar que tais modificações existe a possibilidade de perder precisão ou estouro do valor. long para float e float para double ( i2l . d2l .Imergindo na JVM Conversão de valores As instruções de conversão de valores serve para modificar o tipo da variável. e f2d ) esse ampliamento perde não perde a precisão do valor original. i2f . double para int . Conversão de valores 37 . d2i . long para float para int ou long para. double para long ou double para float ( i2b . int para short . l2f . i2d . int para char . f2i . l2i . i2s . int para double . O encurtamento do tipo como: int para byte . int para float . i2c . l2d . f2l . long para int . daload . aaload ) Salvar na pilha ( bastore . putfield . laload . multianewarray ). fastore . faload . anewarray . putstatic ). castore . caload . dastore e aastore ) Vetores além do seu tamanho ( arraylength ). Acessar atributos estáticos ou da instância de uma classe ( getfield . getstatic . iaload . Checa a propriedade da instância ou array ( instanceof e checkcast ). lastore . Carregar ( baload . sastore . Criação e manipulação de objetos 38 . saload . iastore .Imergindo na JVM Criação e manipulação de objetos: Instruções para a criação e manipulação de instâncias ( new ) Intruções para criação de arrays ( newarray . if_acmpeq . if_icmple . goto . ifne . goto_w . ifge . jsr . if_icmplt . jsr_w e ret`). iflt . ifnull . ifgt . tableswitch elookupswitch . if_icmpeq . if_icmpne .Imergindo na JVM Instruções condicionais Instruções que retornam valores boolianos ( ifeq . ifle . Instruções condicionais 39 . if_acmpne . if_icmpgt if_icmpge . ifnonnull . lreturn . esses tipos de métodos são definidos pela flag ACC_SYNCHRONIZED em seu constate pool. freturn .Imergindo na JVM Chamada de métodos e retorno de valores As chamadas de um método são: invokevirtual: Chama um método de uma instância invokeinterface: Chama um método de uma interface invokespecial: Chamada de um método privado ou da superclasse invokestatic: Realiza a chamada de um método estático invokedynamic: Método que constrói um objeto O retorno de uma instrução pode ser definido ( ireturn . que quando possui tal flag o método entra no monitor( monitorenter ) e é executado. Os métodos síncronos são possíveis graças à presença de um simples encapsulando chamado de monitor. e sai ( monitorexit ) quando seu método é encerrado (de um modo normal ou por interrupção). e nenhuma outra Thread pode acessá-lo. dreturn e areturn ). Durante a execução do método caso seja interrompida de maneira inesperada com uma exceção a chamada athrow é realizada. Chamada de métodos e retorno de valores 40 . métodos que possuem seus respectivos vetor e índices. ou atributos e o seu contador ou índice que funciona como limitador do vetor. Para guardar essas informações existem dois registadores par cada informação importante: O vetor coma s informações da classe. por exemplo. ou seja.class. métodos. referência S short Z boolean [ referência de um vetor Classes após compilação 41 . método. a única classe que não possui pai. Como já foi dito após a compilação é gerado um bytecode. do contrário terá que ser um índice válido e ter informações que apontam para a classe pai. constant pool: O constant pool é uma estrutura de tabela que contém o nome das classes. As descrições dos atributos ou dos parâmetros em um método quanto ao seu tipo é definido a seguir: B byte signed byte C char D double F float I int J long L Classname . Cada arquivo possui as seguintes características: Um número mágico em hexadecimal definindo que essa clase é um . se ocupar o índice zero essa classe é o java. a nome da String seria java/lang/String.class o valor é 0xCAFEBABE O maior e menor número da versão do arquivo class que juntos definem a versão do arquivo. access_flags: Essa flag indica o tipo de encapsulamento da classe. métodos e de suas propriedades os flags podem ser: ACC_PUBLIC: flag método. JVM antes rodar precisa verificar se a versão V que ela pode executar estar entre: Menor Versão<V< Maior Versão. atributos públicos ACC_PRIVATE: flag para privados ACC_PROTECTED: protected ACC_STATIC: estático ACC_FINAL: final ACC_SYNCHRONIZED: indica um método sincronizado ACC_BRIDGE: indica que o método foi gerado pelo compilador ACC_VARARGS: indica que é varags ACC_NATIVE: nativo ACC_ABSTRACT: abstrato ACC_STRICT: indica que o método é strict ACC_SYNTHETIC: indica que o método não é “original” . e cada arquivo representa apenas uma classe. this_class: o valor da corrente classe deve ter um índice válido na constant pool super_class: as informações da superclasse devem estar dentro e pode ocupar o índice zero ou não.Imergindo na JVM Classes após compilação Uma vez falando dos bytecodes é interessantes “puxar o gancho” e falar como fica uma classe após sua compilação. cujo arquivo possui a extensão . Esse é o caso das interfaces que a classe implementa. As informações da classe é definida pelo seu nome com o seu caminho. atributos e outras informações das classes. atributos.lang.Object. interfaces. } public double somarDouble(double a. RuntimeInvisibleAnnotations . por exemplo: double dobro(double d) é igual (D)D e Double dobro(Double d) é (Ljava/lang/Double. será demonstrado um simples código e o seu respectivo bytecode. interfaces implementadas. pilha de operações (sendo que para esses dois últimos o longo e o double ocupam dois espaços). esse mesmo número vale para o número de métodos. O número de dimensões de uma matriz é 255 o mesmo número vale para a quantidade de parâmetros.)Ljava/lang/Double . AnnotationDefault define as informações dentro das anotações. ele só pode conter 2¹⁶=65535 elementos. atributos. byte b) { return (short) (a + b). Dentro da constant pool cada informação possui o seu primeiro byte que indica o seu tipo de informação: CONSTANT_Class 7 CONSTANT_Fieldref 9 CONSTANT_Methodref 10 CONSTANT_InterfaceMethodref 11 CONSTANT_String 8 CONSTANT_Integer 3 CONSTANT_Float 4 CONSTANT_Long 5 CONSTANT_Double 6 CONSTANT_NameAndType 12 CONSTANT_Utf8 1 CONSTANT_MethodHandle 15 CONSTANT_MethodType 16 CONSTANT_InvokeDynamic 18 StackMapTable: é composto de stackmapframe e tem o objetivo de verificações para o bytecode Para auxiliar a depuração na linguagem Java existem algumas informações para depurar o código essas variáveis são: LocalVariableTable e LocalVariableTypeTable que define as informações das variáveis locais para o debug e LineNumberTable define a parte do bytecode e sua correspondente linha de código. Double b) { Double resultado = a + b. } Classes após compilação 42 . RuntimeVisibleParameterAnnotations . Com o objetivo de pôr em prática e visualizar esses bytescodes. ou seja. int b) { return a + b. double b) { return a + b. } public short somarShort(short a. public class PrimeiroTeste{ public Double somarInstancias(Double a. variáveis locais. caso não seja um método estático deve-se incluir a instância.Imergindo na JVM [[ referência de uma matriz Assim. o nome do método ou atributo. RuntimeInvisibleParameterAnnotations que contém informações das anotações quanto a sua visibilidade em tempo de execução aos atributos e métodos ou não. O contador da consant pool possui 16 bits. return resultado. } public int somarInteiros(int a. Para as anotações exitem: RuntimeVisibleAnnotations . existem essas mesmas informações para os parâmetros quanto as suas visibilidades. )Ljava/lang/Double. O Constant Pool contém as informações da respectiva classe.java #21 = NameAndType #6:#7 // "":()V #22 = Class #27 // java/lang/Double #23 = NameAndType #28:#29 // doubleValue:()D #24 = NameAndType #30:#31 // valueOf:(D)Ljava/lang/Double. os próximos passos serão entrar pelo terminal no caminho que se encontra o arquivo PrimeiroTeste.valueOf:(D)Ljava/lang/Double. #25 = Utf8 PrimeiroTeste #26 = Utf8 java/lang/Object #27 = Utf8 java/lang/Double #28 = Utf8 doubleValue #29 = Utf8 ()D #30 = Utf8 valueOf #31 = Utf8 (D)Ljava/lang/Double. compilar e analisar o seu respectivo byte code com os seguintes comandos. public PrimeiroTeste()."":()V 4: return LineNumberTable: line 1: 0 Classes após compilação 43 . flags: ACC_PUBLIC Code: stack=1.#21 // java/lang/Object. int b) { return a + b."":()V #2 = Methodref #22.Ljava/lang/Double. } } Criado o arquivo PrimeiroTeste. args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object.java javap -verbose PrimeiroTeste O resultado: minor version: 0 major version: 51 flags: ACC_PUBLIC.#24 // java/lang/Double. #12 = Utf8 somarDouble #13 = Utf8 (DD)D #14 = Utf8 somarInteiros #15 = Utf8 (II)I #16 = Utf8 somarShort #17 = Utf8 (SB)S #18 = Utf8 somarStatic #19 = Utf8 SourceFile #20 = Utf8 PrimeiroTeste. javac PrimeiroTeste.doubleValue:()D #3 = Methodref #22. ACC_SUPER Constant pool: #1 = Methodref #5. inclusive as InnerClasses. #4 = Class #25 // PrimeiroTeste #5 = Class #26 // java/lang/Object #6 = Utf8 #7 = Utf8 ()V #8 = Utf8 Code #9 = Utf8 LineNumberTable #10 = Utf8 somarInstancias #11 = Utf8 (Ljava/lang/Double.java. já que toda classe possui essa informação.#23 // java/lang/Double. e eles são armazenadas em um vetor.java e inserido o código 1 nesse arquivo.Imergindo na JVM public static int somarStatic(int a. Nesse primeiro resultado podemos visualizar a constant pool e a menor e a maior versão do class. locals=1. flags: ACC_PUBLIC Code: stack=2. 13 2 3 resultado Ljava/lang/Double. 0 5 1 a S 0 5 2 b B public static int somarStatic(int. args_size=3 0: aload_1 1: invokevirtual #2 // Method java/lang/Double.Double). public double somarDouble(double.doubleValue:()D 4: aload_2 5: invokevirtual #2 // Method java/lang/Double.lang. byte).Double somarInstancias(java. flags: ACC_PUBLIC Code: stack=4. locals=4. flags: ACC_PUBLIC Code: stack=2. locals=3.Imergindo na JVM LocalVariableTable: Start Length Slot Name Signature 0 5 0 this LPrimeiroTeste.valueOf:(D)Ljava/lang/Double. 12: astore_3 13: aload_3 14: areturn LineNumberTable: line 5: 0 line 6: 13 LocalVariableTable: Start Length Slot Name Signature 0 15 0 this LPrimeiroTeste. 0 4 1 a D 0 4 3 b D public int somarInteiros(int. args_size=3 0: iload_1 1: iload_2 2: iadd 3: i2s 4: ireturn LineNumberTable: line 17: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this LPrimeiroTeste. 0 4 1 a I 0 4 2 b I public short somarShort(short. int). java.doubleValue:()D 8: dadd 9: invokestatic #3 // Method java/lang/Double. 0 15 1 a Ljava/lang/Double. flags: ACC_PUBLIC. public java.Double. flags: ACC_PUBLIC Code: stack=4. args_size=3 0: iload_1 1: iload_2 2: iadd 3: ireturn LineNumberTable: line 13: 0 LocalVariableTable: Start Length Slot Name Signature 0 4 0 this LPrimeiroTeste. double). locals=3. args_size=3 0: dload_1 1: dload_3 2: dadd 3: dreturn LineNumberTable: line 10: 0 LocalVariableTable: Start Length Slot Name Signature 0 4 0 this LPrimeiroTeste. ACC_STATIC Classes após compilação 44 . locals=5.lang.lang. int). 0 15 2 b Ljava/lang/Double. diz que a linha de número cinco do código java equivale a instrução do começo.)Ljava/lang/Double . esse método é construído automaticamente caso não seja feita pelo usuário. ele possui o tamanho de três na pilha de variáveis.Imergindo na JVM Code: stack=2. já que uma para as duas variáveis de referência e uma já que o método é da instância. linha zero do bytecode e line 6: 13.Ljava/lang/Double. por exemplo. No segundo método. No primeiro que é o método construtor. a linha seis do código java começa na instrução do bytecode número 13. locals=2. byte. já que se trata da criação de um objeto do tipo referência e esse ocupa um espaço no vetor de operação. olhando pelas inicias do comando. assim suas operações são realizadas como inteiros. ele possui 1 tamanho de operação. Classes após compilação 45 . quatro no tamanho de pilha de operações. a soma de instâncias e retorna uma terceira instância. 1 no tamanho de variável. Isso demonstra como é diferente o código Java e o byteCode gerado. O campo LocalVariableTable também serve para debugar e define o nome do campo. LocalVariable e LineNumberTable para auxiliar na hora de debugar. LineNumberTable 5: 0. já que no processo os Doubles serão transformados em double primitivo. (Ljava/lang/Double. Nesse capítulo falamos um pouco sobre o bytecode e o seu macete para entender. args_size=2 0: iload_0 1: iload_1 2: iadd 3: ireturn LineNumberTable: line 21: 0 LocalVariableTable: Start Length Slot Name Signature 0 4 0 a I 0 4 1 b I Ao vermos os métodos podemos perceber que todos os métodos possui o tamanho da pilha de operação e de variáveis além do tamanho das variáveis envolvidas em um determinado método. já que ele é um método não estático e essas informações pertence a interface que a está chamando e o número de variáveis utilizadas é de um já que estamos nos referindo a instância criada. essas variáveis são utilizadas pelo modo debug das IDEs modernas. assim cada um ocupará duas unidades no vetor. tipo. linha que ele nasce e a que morre. shorts são transformados para inteiros. O campo LineNumberTable é para ajudar a debugar o código num determinado método. vale lembrar que durante a execução os boolianos. Se demonstrou quão diferente é o código Java do bytecode gerado e em função disso se criou tabelas e variáveis. e começa quando ela nasce dentro da JVM. se discriminará as ações de cada um. carregar as informações e colocar a sua classe dentro da JVM. Caso a classe estenda de uma classe ou implemente interfaces as mesmas terão de ser carregadas primeiro. ou seja. esse processo é feito de modo lazy. então criar o objeto. Todas as classes precisam passar por esse processo inclusive a classe que inicia a JVM.Imergindo na JVM Ciclo de vida de uma classe Toda classe pela JVM possui o seu ciclo de vida. ao instanciar um objeto é feito o processo de encontrar a representação binária da classe. a class X será carregada no momento em que for necessário. Ciclo de vida de uma classe 46 . Como cada um desses três processos possui detalhes. interfaces. Ciclo de vida de uma classe 47 .lang. As Classes por sua vez. como lista dos métodos. com isso ele contém as informações do mesmo. esse processo acontece uma vez com pot qualifield. atributos. etc.Imergindo na JVM O carregamento de classe consiste em subir a classe para memória principal e colocar na JVM. são carregadas pelo ClassLoader (com exceção dos array que não possui representação binária). o java.Class . A interface Class é o produto do processo de carregar a classe para a memória principal. é a representação do arquivo. com esse stream carregado se realiza o parser para o registrador method Area e concluindo gera a interface que representa tal arquivo. anotações. sendo que antes é chamado o construtor da superclasse. ele é responsável por carregar as classes que estão contidas no classpath. esse processo consiste na verificação da classe recém-carregada. entre eles definir um grupo de class loader específico para um domínio ou aplicação. Abaixo do System Class Loader o usuário adicionará um class loader. e os objetos que possuam um altíssimo nível de confiança pela JVM. Extensão é responsável por carregar as API padrões do Java como as de segurança e Collection.Imergindo na JVM Na JVM existem múltiplos classe loaders com diferentes regras. ele verifica a palavra-chave. não existe verificação para as interfaces apenas se os métodos foram implementados. se a estrutura está correta. o tamanho dos arquivos. assim podemos classificar-las como: BootStrap ele se encontra no topo da hierarquia dos class loaders. Após a classe ser carregada o próximo passo será linkar para JVM. são carregados os atributos estáticos. é o caso dos servidores de aplacação como o tomcat e o Glassfish. esse objeto é responsável por carregar a API básica do Java. encerrando esse processo todos os link de referência são substituídos por links diretos. O system esse é o class loader padrão da aplicação. Ciclo de vida de uma classe 48 . após a verificação são alocadas memórias para os atributos e serão setados os valores padrão dos campos. No último estágio será a criada a instância com a chamada do método construtor. que tem alguns motivos especiais. no entanto. assim haverá o processo de compactação dos dados. basicamente dois processos que marca os objetos utilizados e no final os objetos não marcados são dispensáveis para retomar a memória. isso permite que a memória de um objeto não mais utilizado seja retomada. Para melhor gerenciar o coletor de lixo a memória heap é dividia basicamente em algumas partes: Young Generation: É onde contém os objetos recém-criados. com os objetos apagados a próxima preocupação será em relação a fragmentação do registrador. alguns levam bastante tempo na memória. essa certamente é uma das grandes vantagem da plataforma em relação ao C . o maior problema é que todos os processos são parados para executar tal procedimento inviabilizando chamá-lo constantemente. depois de um tempo. os objetos são copiados “vivos” para os Survivers. existem algoritmos derivados do Swep and Mark. assim os algoritmos se baseia em gerações que divide a memória em três partes (jovem. nesse espaço o gerenciamento de objetos é realizado de forma diferente. O primeiro desafio da JVM é identificar quais objetos dispensáveis. O mais conhecido certamente é o Mark and Sweep. assim não há cópia. outros objetos ocuparão seu espaço. mas no futuro. O seu funcionamento é de maneira simples: Os objetos nascem no Eden. efetiva e permanente).Imergindo na JVM Garbage Collector Diferente de algumas linguagens o Java possui um gerenciamento de memória automática. Garbage Collector 49 . Em função desse problema citado anteriormente falaremos do segundo algorismo. a grande maioria dos objetos morrem dentro dessa área. os objetos que não foram copiados não são apagados. Com o passar das coleções os objetos existentes saem da Young e vão para Tenured generation. que leva em consideração que muitos objetos não possuem uma longa vida. e assim retomar a memória com isso foi realizado várias técnicas para assim o fazer. Ela é subdivida em duas partes: Eden (local aonde o objetos nascem) e Survivers(N) locais aonde os objetos vão passando até sair da Young Generation. Garbage Collector 50 .Imergindo na JVM Comentado um pouco sobre os processos de minor collector (procedimento de generation que cópia objetos para registradores sobreviventes) e o maior collector (procedimento cujo os algoritmos são derivados de Mark and Swep que apaga os objetos não utilizados e quando fragmentada a memória haverá o procedimento de compactação. vale lembrar que para tal procedimento a JVM para todos os seus processos). O objetivo agora será falar o estilo ou o modo dos Garbage Collector. maior e menor collector. desse modo pode economizar recursos. utilizando apenas uma Thread .Imergindo na JVM Implementação Serial Esse estilo é muito indicado para pequenas aplicações ou hardware de pequeno poder computacional e apenas um processador. monocore. Implementação Serial 51 . porém caso haja um grande número de memória haverá um grande delay. ele se na baseia na execução dos processos . Implementação Paralelo 52 . porém utilizando mais recursos de máquina. assim o processo tende a ser realizar em um tempo menor. será utilizado duas ou mais Threads por coleção.Imergindo na JVM Implementação Paralelo Trabalha de forma semelhante da serial. no entanto. Indicado para muitos objetos duram muito tempo. Em resumo seu processo divide realizar marcação em que todas as Thread estão paradas e marcações concorrentes. o único problema desse estilo é o fato que não há compactação de dados periódicos. Implementação Concurrent 53 . apenas quando se torna crítico (usando o SerialOdl). assim eles ficam na Turnered. o seu objetivo é diminuir o tempo do maior collector. mesmo que para isso o execute várias vezes. no entanto.Imergindo na JVM Implementação Concurrent Esse também executa processos em paralelos. mas a remoção dos objetos ocorrem sem nenhum processo parar. ele também acionará o serialOdl (que além de remover os dados também compactará os objetos sobreviventes). mas é realizado de forma incremental (realizado aos poucos e agendado entre as minor-collector) seu funcionamento é bem semelhante ao anterior. mas adiciona um processo que é redimensionar e preparar os dados para uma próxima coleção o ciclo que controla o tempo que o colector fica no processador. Implementação Incremental Concurrent 54 .Imergindo na JVM Implementação Incremental Concurrent Também é concorrente. Caso tenha problemas com fragmentação. é coletor paralelo projetada para ter um grande throughput. Assim como os dois últimos concorrentes. e realiza o calculo de objetos alcançáveis de cada região. Terão maior prioridade as regiões com o maior número de objetos “mortos” (assim se terá menos trabalho em realizar a copia para a outra área). Não ter um tempo determinado para deixar o processador e a compactação do heap (uma vez que muito crítica chamada o serialOdl). fazendo com que a região em questão seja totalmente tomada. O G1 veio para substituir os tipos concorrente de coleção ( CMS e I-CMS ) devido a lacuna que ambos deixavam. ele foi projetado para sistemas com uma alta quantidade de memória e de processadores. um outro aspecto é que tão logo as memórias existentes tenha sido copiado para uma nova área. ele possui uma fase em que realiza a marcação concorrente. O G1 toma como estratégia o fato de ser mais fácil controlar pequenas regiões do que uma geração. o Garbage first. assim de tempos em tempos. todos os processos são parados os objetos vivos são copiados para outra região.Imergindo na JVM Implementação Garbage First Lançado na versão 7 do Java. a anterior é considerada uma área limpa. Para alcançar seu objetivo ele divide igualmente o tamanho do Heap. Implementação Garbage First 55 . principalmente do fato dele ser multiplataforma.Class .Imergindo na JVM Interface Nativa Java Muito se fala do Java. Assim é muito importante saber o momento em que se usará o JNI. Esse recurso é muito interessante também para fazer a ponte para plataformas em que o Java ainda não atingiu. uma vez no nativo será concatenado o “Hello world” com o nome digitado. não é possível debugar o código nativo através da plataforma Java.lang. dentre outros recursos. Java I/O. assim é possível um grande aproveitamento de código. Com o JNI é possível chamar método do objeto. Dentro da JVM esse recurso é usado para alguns na plataforma JSE. assim é possível estar passando um objeto Java para o lado nativo ver o seu valor. vale lembrar que usar o JNI perde a portabilidade. Primeiramente será criado a classe HelloWorld. não se sabe o seu valor preciso). a implementação da interface java. Tipo em Java Tipo Nativo boolean jboolean byte jbyte char jchar double jdouble float jfloat int jint long jlong short jshort void void Com o objetivo de dar um pequeno exemplo com o JNI será mostrado dois simples exemplos. talvez essa característica em especial. o arquivo . a comunicação entre a classe. No entanto. alguns métodos da classe java.class . A porta entre o código nativo e o Java é conhecido como JNI (Java Native Interface). tornou o Java a linguagem e plataforma mais popular no mundo. por exemplo. por exemplo. mas surge a seguinte dúvida: Como a JVM faz isso? Como ela conseguir abstrair as outras plataformas para min? Obter esse conhecimento é muito importante uma vez que pode ser necessário utilizar um recurso específico da máquina e fazer com esse recurso converse diretamente com a JVM. A comunicação entre a JVM e o código nativo quase em sua grande maioria é feito na linguagem C/C++ uma vez que elas possuem o padrão ANSI e que o mesmo é compatível com a grande maioria das plataformas. um erro nativo não é controlado pela JVM (Vale lembrar na parte em que se falou de registrados. de se compilar uma vez e poder rodar em diversas plataformas. verificar estado do objeto criado dentro da JVM. usar o requer algumas responsabilidades. as implementações do Garbage Colector dentre outros recursos. e a sua representação dentro da JVM. o primeiro será o “olá mundo” com o JNI e o segundo será um método estático que calcula o dobro do resultado passado. o segundo parâmetro seria calculado o seu dobro. mas em alguns casos é necessário que seja feita uma implementação específica para cada plataforma ou que existe compatibilidade com um sistema legado que foi feito em C . caso acontece um erro nativo pode quebrar a execução da JVM. Os objetos em Java podem ser mapeados para objetos nativos e virse-versa.lang. ele não prover um Garbage Collector automático ou qualquer gerenciamento por parte da JVM. O código será bem simples. no segundo exemplo. Interface Nativa Java 56 .java. para isso é necessário que se tenha instalado o GCC e o JDK. no primeiro caso será enviado o nome por parâmetro e essa String será passada para o valor nativo. instanciar classes. para garantir a comunicação de duas mãos.System . Muito se tem explorado já que toda a complexidade é feita pela JVM. JavaSound. a pilha nativa e o PC quando aponta para um processo nativo. #ifdef __cplusplus } #endif #endif Repare que na interface o método possui o seguinte formato: Java_NomeClasse_nomeMetodo.valueOf(args[1]). jobject. HelloWorld helloWorld=new HelloWorld(). } static {System.)V */ JNIEXPORT void JNICALL Java_HelloWorld_chamarMensagem (JNIEnv *. int valor=args[1]==null?2:Integer. será necessário gerar a interface JNI como seguinte comando: javah -jni HelloWorld Com o comando será gerado um arquivo HelloWorld. public native static int dobrar(int valor). ele é um ponteiro que aponta para um vetor no qual possui todas as funções do JNI. System.out. jclass.loadLibrary("HelloWorld"). o próximo parâmetro será o jclass que conterá as Interface Nativa Java 57 . /* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.dobrar(valor).Imergindo na JVM public class HelloWorld { private native void chamarMensagem(String nome).} } Em seguida compilamos com o seguinte comando: javac HelloWorld. o JNIEnv. int resultado=HelloWorld.chamarMensagem(nome).h> /* Header for class HelloWorld */ #ifndef _Included_HelloWorld #define _Included_HelloWorld #ifdef __cplusplus extern "C" { #endif /* * Class: HelloWorld * Method: chamarMensagem * Signature: (Ljava/lang/String. helloWorld.java Uma vez o arquivo compilado.println("O dobro de "+valor+" é: "+ resultado). jstring). Em relação aos parâmetros o primeiro elemento. ou seja o método possua a palavra-chave static . /* * Class: HelloWorld * Method: dobro * Signature: (I)I */ JNIEXPORT jint JNICALL Java_HelloWorld_dobrar (JNIEnv *. jint).h . Caso seja estático. o segundo depende se é método da classe ou da instância. public static void main(String[] args) { String nome=args[0]==null?"nome":args[0]. Imergindo na JVM informações da classe.path ao executar o projeto java. No entanto. o primeiro passo é carregar a biblioteca dentro do código java (para isso será utilizado o comando System. jclass classe. assim será criado o HelloWorld. NULL).c que implemente tal interface. } JNIEXPORT jint JNICALL Java_HelloWorld_dobrar(JNIEnv * env.` Interface Nativa Java 58 .so -shared -I$JAVA_HOME/include -I$JAVA_HOME/linux HelloWorld. Aprender sobre JNI é muito importante para compreender o código da máquina virtual Java. como se trata de libs nativas as pastas variam de acordo com a plataforma. jobject obj. HelloWorld Otávio 4 A saída será: Hello World!!!! Otávio `O dobro de 5 é: 10 Com isso se apresentou o recurso do JNI. Nesse exemplo será utilizado a segunda opção juntamente o parâmetro que será o nome da que será impresso no console. No caso do linux para compilar será necessário o seguinte comando: gcc -o libHelloWorld. O próximo passo é colocar a lib nativa no classpath no sistema operacional ou definir o seu caminho pelo parâmetro java. nome. O próximo passo será “linkar” o arquivo nativo com o projeto. return. ).so de Shared Object. caso seja da instância o próximo parâmetro será o jobject que conterá as informações da instância. nomeNativo). mas é necessário um conhecimento na linguagem C e C++ . } Com o arquivo criado o próximo passo é a compilação. vale salientar que se perde o fator multiplataforma e não será mais gerenciado pela JVM usando este recurso. no caso do linux o arquivo com extensão .jstring nome){ const char * nomeNativo=(*env)->GetStringUTFChars(env.loadLibrary("NomedaLib"). O próximo passo é a criação do arquivo que “implemente” a interface do HelloWorld.h" #include <stdio. a interface que se comunica o JVM para linguagens nativa como C e C++ e da sua importância para a JVM como a implementação do Garbage Collector.c Uma vez compilado o código-fonte e o transformado em uma lib.h> JNIEXPORT void JNICALL Java_HelloWorld_chamarMensagem(JNIEnv * env. assim o comando ficará: java -Djava.library.library. jint valor){ return 2*valor. printf("Hello World!!!! %s\n".h> #include "HelloWorld.path=. #include <jni. sua existência em algumas APIs como o JavaSound além de se integrar com código legado e com plataformas cujo a JVM até o momento não atingiu.h . levando em consideração as devidas importações. JEE. está na adição de códigos fechados além de pequenas mudanças na implementação para implementações fechadas para a JVM da Oracle. Essas instituições têm a missão de votar a favor ou contra uma JSR. se fazer um aplicativo que rode em qualquer JVM. é uma JVM com o Know-how de várias empresas em todo o mundo. A JVM do projeto. Quando existe uma mudança na plataforma (JSE. Azul. O OpenJDK não será em nenhum momento abalado já que existem outras empresas apoiando além da comunidade. Mac. o código seja integrado com o Hotspot. Toda mudança dentro do Java é realizada através da submissão de uma JSR.Imergindo na JVM O projeto OpenJDK O OpenJDK é um projeto que foi iniciado pela Sun Microsystems. Várias empresas fazem parte desse projeto. 2. A primeira vantagem é que ele é open source. essa garantia será possível apenas com o OpenJDK 3. no openjdk haverá os melhores de dois mundos em um só lugar. Uma conquista para o projeto que vale salientar é que a partir da versão 7 do Java o OpenJDK é a versão de referência. ou seja. O que acontece é que nem todos os códigos foram abertos com êxito já que alguns pertence a terceiros e são apenas licenciados na época pela Sun. Se a Oracle deixar o Java (Algo que eu acho muito difícil por diversos motivos) e deixar de fazer a JVM. Apple. Empresas como IBM. 4. a dessemelhança é de cerca de 4% de código. para a criação de um Java Development Kit baseado totalmente em software livre e de código aberto. Java Community Process. Essas JSRs são selecionadas a partir do JCP. está passando por constantes refatorações para melhoria de performance. 5. ou seja. SAP. JME) é dito que ela possui um guarda-chuva de especificações (Já que uma mudança de plataforma é resultado de diversas JSRs. pode estudar o seu código fonte. A diferença entre essas duas JVMs. Ela agora é a implementação de referência. RedHat etc. atualização de bibliotecas e atualização do código sem falar que para adicionar qualquer recurso é necessário que se tenha testes. O projeto foi iniciado em 2006 e tem como base o HotSpot (a jvm da Sun). Ou seja. previsto para o final de 2013. Java Specification Requests. por exemplo. que é um documento que possui informações quanto a melhoria a ser feita e seus impactos dentro da linguagem. mas além dessa o uso do OpenJDK te garante algumas vantagens: 1. por exemplo com o Java 7. Intel. atualmente mantido pela por várias empresas e a comunidade. HotSpot (a JVM mais popular da Sun atualmente da Oracle) e o OpenJDK. 6. A comunidade Java é certamente uma das comunidades mais fortes do mundo. SouJava e London Comunity). A Oracle doou o código fonte do jRockit e no java 8. ou seja. que é composta por 31 instituições (Podemos destacar a participação da Oracle. fazem parte do projeto. O projeto OpenJDK 59 . precisa ter um conjunto de JSR ou um guarda-chuva de especificação.openjdk.net/ Para baixar o código é necessário: hg clone http://hg. no caso de uma nova versão da plataforma JSE. possui dentro dela as JSRs 314 o projeto Coin. para melhorias. 292 o invoke dynamic). todas as suas mudanças precisam estar documentadas em JSRs que são votadas pelo JCP.sh (shell script para baixar o código fonte dos módulos da JVM). 203 o NIO2.net/jdk8/jdk8 jdk8 (para baixar o código fonte em sua máquina). sh get_source.java.Imergindo na JVM documentada na JSR 336. onde se encontra o código fonte). JDK Enhancement Proposals ou propostas de melhorias para o JDK. cd jdk8 (entrando no diretório. Com o OpenJDK não é diferente. O código do projeto é mantido em mercurial e mais informações do projeto pode ser encontrado em: http://openjdk. Ao baixar o código se verá que o projeto OpenJDK é composto por subprojetos: O projeto OpenJDK 60 . refatorações existe o JEP.java. No entanto.


Comments

Copyright © 2024 UPDOCS Inc.