Máquinas Virtuais: Java e Dalvik
Por: rrlnamcl • 3/4/2017 • Trabalho acadêmico • 1.526 Palavras (7 Páginas) • 293 Visualizações
[pic 1]
Análise e Desenvolvimento de Sistemas
2º Semestre
MÁQUINA VIRTUAL
André Bariani – RA.: 0030481611003
Caique Siqueira – RA.: 0030481611009
SOROCABA - SP
Dezembro de 2016
Java Virtual Machine
Introdução
A Máquina Virtual Java (JVM, do inglês Java Virtual Machine) é um sistema computacional virtual usado, principalmente, para executar programas escritos em Java. A partir da proposta da linguagem Java, que é “Escreva uma vez, execute em qualquer lugar” (Write once, run anywhere), a máquina virtual foi criada, sendo responsável pela execução do código compilado em diversos dispositivos diferentes, sem a necessidade de alterações no código.
A implementação da JVM é feita de maneira a funcionar como um computador real, com seu próprio conjunto de instruções e sistema de manipulação de memória, tornando o programa executado por ela praticamente independente do sistema operacional em que esteja rodando e também trazendo segurança a esse sistema, por não permitir que o aplicativo acesse áreas da memória física alheias ao escopo da máquina virtual.
A proposta de executar aplicações Java em qualquer sistema exige que exista uma JVM específica para cada sistema operacional. Para isso, há um conjunto de especificações básicas definidas pela Oracle para qualquer máquina virtual que execute o código Java compilado, sendo que essas especificações podem ser implementadas tanto em programas quanto em dispositivos físicos (ou seja, seguindo essas especificações, é possível até desenvolver uma CPU física que execute instruções bytecode).
Mesmo sendo a Máquina Virtual Java, com sua proposta de portabilidade e sua estabilidade, atualmente é possível executar códigos escritos em outras linguagens na JVM, sendo que algumas (como Groovy e Scala) tem a JVM como padrão (ou principal) para execução de programas, enquanto outras precisam ser compiladas com compiladores específicos.
Compilação e execução
Um código Java ou de outra linguagem, antes de ser executado pela JVM, precisa ser compilado para bytecode (representado por um arquivo .class), que representa a tradução dos comandos da linguagem para o conjunto de instruções da JVM, mais compacto que a linguagem Java e ligeiramente próximo a uma linguagem de máquina. Ao executar esse arquivo compilado, uma instância da JVM do dispositivo é carregada e inicia a interpretação do bytecode, que é compilado para a linguagem de máquina no momento da execução (Just-in-time). Mesmo que isso implique em uma ligeira perda de desempenho durante a inicialização, torna o código mais rápido posteriormente do que se fosse completamente interpretado durante sua execução.
Para execução, a JVM possui um sistema de carregamento de classes (Class Loader), responsável por três passos:
Carregamento: cada arquivo .class é carregado, e suas instruções são e armazenadas na área de métodos, associadas ao nome, tipo e variáveis internas. Posteriormente, é criado um (e apenas um) objeto que representa esse arquivo na memória.
Ligação (linking): Verifica se o arquivo .class foi compilado corretamente, cria as variáveis locais necessárias e substitui referências simbólicas a tipos por referências diretas à área de métodos.
Inicialização: Variáveis estáticas são inicializadas e armazenadas na área de dados estáticos, depois classes das bibliotecas do sistema são carregadas e, por último, são carregadas totalmente as classes da aplicação.
Funcionamento interno
Para executar os programas compilados garantindo a portabilidade do código e a segurança do dispositivo em que esse programa está sendo executado, a JVM implementa todas as principais funções de um computador real e as emula no ambiente virtual da aplicação, de onde traduz os comandos da aplicação para o sistema operacional e o hardware real.
Registradores: a JVM usa registradores internos para determinar a posição na memória virtual para valores, variáveis, métodos e da instrução sendo executada.
Pilha: Em vez de armazenar os operandos da instrução em registradores, a JVM utiliza uma estrutura de pilha para esse fim. Todas as instruções carregam os operandos da pilha, realizam a operação e o resultado é retornado para essa pilha. Cada operação exige uma determinada ordem dos valores na pilha, que usa o método LIFO (último a entrar, primeiro a sair) para armazenamento de seus valores.
Ambiente de Execução: usada para referenciar funções, verificar retorno de métodos e lançar erros, mantém uma pilha armazenando determinados valores de referência. Por exemplo, ao término de um método no programa, se o retorno foi o esperado por aquele método, os registradores do método anterior são restaurados e a execução continua. Se o retorno não era o esperado, é lançado um erro ou exceção no sistema.
Alocação de memória: Armazena instâncias de objetos em uso pelo sistema, mantendo o controle da memória total. Esse uso da memória reflete na memória física do sistema. Se o espaço ocupado por esses objetos na memória alcançar um determinado limite, objetos que não estão mais em uso são desalocados automaticamente por um método da JVM chamado de garbage collector (coletor de lixo). Dependendo do sistema operacional e do hardware que está rodando a aplicação, esse método pode ser invocado com maior frequência (em casos onde há pouca memória) ou de maneira mais branda (quando o sistema possui mais recursos disponíveis).
Constantes: para cada classe carregada na memória, é mantido um grupo de constantes associado. Esse grupo é criado na compilação.
Área de métodos: Mantém as instruções de cada método/função do programa em bytecode e suas ligações com o ambiente de execução.
Conjunto de instruções bytecode: Similar a uma linguagem de montagem, o conjunto de instruções utilizado pela JVM usa tipos primitivos (int, long, float, double) e alguns valores de referência especiais para representar os dados dos operandos e endereços, com instruções específicas para cada tipo de dado sendo usado.
...