Java Virtual Machine

Published on May 2016 | Categories: Types, Research, Internet & Technology | Downloads: 33 | Comments: 0 | Views: 206
of 7
Download PDF   Embed   Report

Java Virtual Machine

Comments

Content

JAVA VIRTUAL MACHINE (JVM)
Por Leandro Baptista, Marlon Palangani e Tiago Deoldoto, 11 de Abril de 2009

A linguagem de programação Java proporciona o desenvolvimento aplicações que podem ser executadas em diversos tipos de plataformas e Sistemas Operacionais. Tudo isso tornou-se possível graças a Máquina Virtual Java. Nesse artigo você encontrará informações a respeito do funcionamento, arquitetura e diversas vantagens que essa ferramenta proporciona, tanto para usuários simples como para desenvolvedores de sistemas. O QUE É JAVA VIRTUAL MACHINE?
A JVM (do inglês Java Virtual Machine) é um programa que carrega e executa os aplicativos Java, convertendo os bytecodes em código executável de máquina, é apenas um aspecto do software Java envolvido na interação com a Web. A JVM é reponsável pelo gerenciamento dos aplicativos, à medida que são executados. Graças à maquina virtual Java, os programas escritos em Java podem funcionar em qualquer plataforma de hardware e software que possua uma versão da JVM, tornando assim essas aplicações independentes da plataforma onde funcionam. A arquitetura de JVM permite um controle muito fino sobre as liberadas para o código que esta rodando na VM. Isso permite a execução de código confiável de fontes remotas, um modelo usado pelos applets. Os applets rodam dentro de uma VM incorporada ao browser do usuário, exectando código baixado de um servidor HTTP remoto. O código remoto roda em uma sandbox, que protege o usuário de códigos maliciosos. O autor do applet pode aplicarum certificado para assinar digitalmente o applet como “seguro”, dando a ele permissão de sair do sandbox e acessar livremente a máquina onde esta rodando. Podemos dizer também que a maquina virtual Java é uma máquina de computação abstrata. Como uma máquina de computação real, tem um jogo de instrução e manipula várias áreas de memória no tempo de execução. É razoavelmente comum executar uma linguagem de programação usando máquina virtual. A máquina virtual mais conhecida, pode ser a máquina do P-Código de UCSD Pascal. A primeira execução do protótipo da máquina virtual de Java, emulou o jogo de instruções em um software hospedado por um dispositivo handheld que se assemelhasse a um assistente de Digitas pessoais contemporâneo (PDA). As execuções atuais da máquina virtual de Java, emulam em anfitriões de Win32 e de solaris em umas maneiras muito mais sofisticadas. Com a linguagem de programação Java, podemos, por exemplo, criar um aplicativo que rode tanto no Linux quanto no Windows, como foi dito acima. Mas não se limita a esses sistemas operacionais, sendo possivel desenvolver para uma infinidade de plataformas, para isso basta que elas tenham uma JVM. Você ja deve ter usado Java antes e não sabe. Por exemplo, em uma fila de banco, onde você fica jogando em seu telefone celular enquanto aguarda sua vez. Os aplicativos feitos em Java estão presentes em uma infinidade de dispositivos, desde relógios até mainframes, relembrando novamente que, tudo isso graças a Máquina Virtual Machine.

ENTENDENDO MELHOR O FUNCIONAMENTO DA JVM
Vamos tentar entender melhor como a JVM funciona. Quando se faz um programa em Java e o compila, se tudo estiver certo, o compilador gera bytecodes desse programa. Bytecode é uma espécie de codificação que traduz tudo o que foi escrito no programa para um formato que a JVM entenda e seja capaz de executar,

assim sendo capaz de rodar em qualquer sistema operacional que tenha a JVM. Isso ocorre porque não existe bytecodes diferentes, isto é, os bytecodes dos programas em Java compilados no Windows são constituiídos da mesma forma que bytecodes gerados se a compilação fosse feita em Mac OS. De certo que, podem haver algumas diferenças, que dependem da implementação da JVM e claro, do compilador. Quando um código em Java é compilado, um arquivo com a extensão .class é gerado. Esse tipo de arquivo é o bytecode, então quando o programa Hello.java for compilado, um arquivo chamado Hello.class deverá ser executado. A imagem a seguir ilustra esse processo.

Construir uma JVM não é fácil, ela envolve uma série de conceitos complexos, como instruções equivalentes a de processadores, controle de acesso à memória, registradores, etc. Isso pode até parecer estranho, mas é necessário entender que as JVMs atuam, de fato, como uma máquina. Muitos usuários relutam em instalar a máquina virtual Java, dizem que gastam memória, que ocupa muito espaço desnecessário, mas a verdade é que bem configurado, ela se torna leve “como uma pluma”. Uma curiosidade que podemos citar, é que, um ponto que merece destaque na arquitetura desenvolvida pela Sun para a plataforma Java é o uso da máquina virtual em troca de um código compilado especifico para um computador. Diversos outros modelos necessitam que um determinado programa seja compilado para cada tipo de computador em que será utilizado, o que pode ser proibitivo para alcançar uma larga escala.

ARQUITETURA DA MAQUINA VIRTUAL JAVA
Principais subsistemas da máquina virtual Java (JVM): - Carregador de classe (class loader), carregar classes e interfaces a partir de nomes completamente qualificados. - Máquina de execução (execution engine), executa instruções das classes carregadas. - Áreas de dados de execução (runtime data areas), organizada em área de métodos (method area), área de memória dinâmica (help), pilhas (stacks), contadores de programas (program counters ou pc) e pilhas dos métodos nativos (native methods stacks). A especificação destas áreas varia de implementação para implementação para permitir que características especificas de uma dada arquitetura possam ser exploradas. Cada instância da máquina virtual tem uma área de métodos e uma “heap” que são compartilhadas por todas as “threads” sendo executadas na máquina virtual. Cada “thread” cria um registro de ativação (frame) na pilha

da “thread” contendo o estado do método, o que inclui parâmetros, variáveis locais, valor de retorno e cálculos intermediários. - Interface de métodos nativos (native method interface). A JVM é uma maquina de pilha. As instruções da JVM utilizam a pilha para armazenar resultados intermediários, ao invés de utilizar registradores como é feito em arquiteturas concretas. Isto permite a definição de um conjunto simples de instruções que é facilmente implementado em diferentes arquiteturas. Na JVM existem tipos primitivos, como byte, short, int, long, float e Double e referencias a objetos. O tamanho de uma palavra (“Word”) na JVM varia de implementação para implementação da JVM e deve ser grande o suficiente para armazenar um byte, int, float, uma referencia a um objeto ou um “return address”, este ultimo utilizado para implementar cláusulas finally em Java. Duas palavras devem ser capazes de armazenar os tipos long e Double.

OTIMIZANDO O USO DA MEMÓRIA EM APLICAÇÕES JAVA Em Java, diferente de outras linguagens como C e C++, o programador não precisa desalocar memória, usando funções como free e delete. Java possui um coletor de lixo, uma thread de baixa prioridade que executa junto com a Java Virtual Machine. Sua função é gerenciar a utilização de memória, procuranado áreas de memória que não estejam mais em uso para realizar a liberação das mesmas. A execução do coletor de lixo é transparente para o programador, porém, podemos em algumas situações desejar usar artifícios para otimizar o uso da memória pela JVM.

FUNCIONAMENTO DO COLETOR DE LIXO
O coletor de lixo libera a memória mantida por um objeto se não houver mais nenhuma referência para ele. Dependendo do algoritmo da coleta de lixo usado pela máquina virtual Java no qual o código está sendo executado, nem todo objeto não referenciado será desalocado pelo coletor de lixo. Um objeto mais antigo, de longa duração, é menos provável de estar não referenciado do que um objeto novo, de modo que um algoritmo comum para coleta de lixo é analisar os objetos mais antigos com menos freqüência do que os objetos mais novos. Podemos ter uma métrica da eficiência da implementação do coletor de lixo utilizado pela sua JVM com o código abaixo: Runtime rt = Runtime.getRuntime(); long mem = rt.freeMemory(); System.out.println("Memória Livre: " + mem); // ... algum código System.gc(); // ... mem = rt.freeMemory(); System.out.println("Memória Livre: " + mem);

O código acima obtém o ambiente de execução com o método estático getRuntime() da classe Runtime. O método freeMemory() retorna a memória disponível no ambiente runtime. A linha System.gc() faz a chamada explícita do coletor de lixo. Em algumas implementações da JVM, o coletor de lixo pode ser ativado através da chamada ao método System.gc(), embora a especificação não garanta isso. De todo modo, a

maior parte das JVMs fazem a chamada do coletor implicitamente quando a memória está baixa ou quando a CPU está inativa por um certo período de tempo. Problemas com a utilização de memória podem surgir quando os objetos contém variáveis de instância que são iniciadas no construtor, ocupam um grande quantidade de memória e não são mais utilizadas no restante da aplicação. Isso pode degradar o desempenho de um código.

LIBERANDO UM OBJETO
Uma maneira de tornar um objeto candidato a ser retirado da memória pelo coletor de lixo é atribuindo o valor null à sua referência. Com isso, o objeto torna-se não referenciado e pode ser retirado da memória pelo coletor de lixo. O programa abaixo ilustra essa técnica: import java.util.*; class GarbageExample { private static Vector vetor; public static void main(String args) { vetor = new Vector(); for (int a=0; a < 500; a++) vetor.addElement(new StringBuffer("teste")); Runtime rt = Runtime.getRuntime(); System.out.println("Memória Livre: " + vetor = null; System.gc(); System.out.println("Memória Livre: " + rt.freeMemory()); } } O código acima aloca 500 objetos StringBuffer e os coloca dentro de um Vector. O objeto da classe Vector é referenciado pela variável vetor. Quando se atribui o valor null para a variável vetor o conteúdo do objeto Vector (500 objetos StringBuffer) não possui mais referência na aplicação. A chamada explícita ao coletor de lixo faz a limpeza desse objeto. O programa exibe a quantidade de memória livre antes e depois da execução do coletor de lixo. Essa técnica pode solucionar o problema de manter grandes quantidades de memória desnecessárias. Para usar o mínimo de memória possível, os objetos que precisem existir durante um tempo maior devem ser os menores possíveis. Do outro lado, os grandes objetos deverão existir pelo menor tempo possível. Essa técnica pode ajudar, em alguns casos, somente o desempenho das aplicações Java que executam na mesma JVM e não necessariamente de outros processos rodando no sistema. Isso porque muitos algoritmos de gerenciamento de heap alocam antecipadamente uma parte da memória para ser usada pelo seu código. rt.freeMemory());

Ou seja, você libera a memória da máquina virtual Java, o que não afetará outras aplicações não-Java, pelo fato da JVM pre-alocar o heap que ela precisa. A qualquer momento pode-se solicitar a execução do coletor de lixo (sem garantias de execução), chamando o método System.gc(). Porém, é necessário analisar o impacto de desempenho na sua aplicação. Muitos algoritmos de coleta de lixo suspendem todas as outros threads antes de entrar em execução. Isso garante que, quando o coletor de lixo for executado, ele terá acesso completo à memória no heap e poderá realizar suas tarefas com segurança, sem que seja interrompido por outra thread. Quando o coletor de lixo termina seu trabalho, todas as threads que ele suspendeu são retomados. O coletor de lixo de Java é executado com uma grande freqüência, sua chamada explícita dificilmente é necessária. Porém, em alguns casos pode tornar-se conveniente. É recomendado evitar a chamada ao método System.gc() pelo bloqueio que provoca. É recomendado também nunca fazer essa chamada explícita dentro de loops.

O MÉTODO FINALIZE()
O programador pode definir o método finalize() que será chamado sempre antes do objeto ser retirado da memória pelo coletor de lixo. A aplicação abaixo ilustra isso: import java.util.*; class GarbageExample { private static MeuVetor vetor; public static void main(String args) { vetor = new MeuVetor(); for (int a=0; a <500; a++) vetor.addElement(new StringBuffer("teste")); Runtime rt = Runtime.getRuntime(); System.out.println("Memória Livre: " + rt.freeMemory()); vetor = null; // deixa os 500 StringBuffers sem //referência System.gc(); System.out.println("Memória Livre: " + rt.freeMemory()); } } class MeuVetor extends Vector { public void finalize() { System.out.println("Vou ser coletado!!"); } }

O método finalize da classe MeuVetor é executado antes do objeto ser coletado da memória, a saída deste programa é: Memória Livre: 459808 Vou ser coletado!! Memória Livre: 600664

JVM E QUESTÃO DA SEGURANÇA
Desde sua criação, sempre considerou com seriedade a questão da segurança. Por isso, é praticamente impossível criar programas em Java para fins maliciosos. Quando um programa em Java é executado, seu bytecode precisa passar pelos requisitos de segurança presentes na JVM, que impede a execução se o código tiver alguma irregularidade. Assim, se no programa houver instruções para acessar áreas restritas da memória ou acessar recursos de hardware, a JVM não aprovará o código. Outras linguagens, como C, são executadas diretamente pelo sistema operacional. Com isso, é possível criar programas que acessem recursos críticos do sistema. No caso da linguagem Java, a JVM atua como uma espécie de intermediária entre o programa e o sistema. Sendo assim, até mesmo o acesso a recursos de entrada e saída só é feito por meio da JVM.

UM EXEMPLO ATUAL DA UTILIZAÇÃO DO JVM
ST lança Máquina Virtual Java para TV Interativa. A STMicroelectronic anunciou a disponibilidade do STJ Engine, uma arquitetura de software projetada para funcionar com a Máquina Virtual Java (JVM). O STJ Engine oferece uma Java Virtual Machine (JVM) otimizada com compilador HotSpot Just-In-Time (JIT) e implementa a interfaces padrões como Java debugger (JVMDI) e Java profiling (JVMPI), permitindo debugging e profiling de aplicações Java. Ao utilizar essas capacidades, os clientes poderão aprimorar as capacidades gráficas de seus sistemas, permitindo uma interface de usuários muito melhor e recursos interativos como jogos de perguntas e respostas, compra virtual, e outros.

REFERÊNCIA BIBLIOGRÁFICA VENNERS, Bill. Inside the Virtual Machine. http://www.mundojava.com.br http://forums.sun.com/index.jspa http://www.ime.usp.br http://www.infowester.com http://www.elektorbrasil.com.br

Sponsor Documents

Or use your account on DocShare.tips

Hide

Forgot your password?

Or register your new account on DocShare.tips

Hide

Lost your password? Please enter your email address. You will receive a link to create a new password.

Back to log-in

Close