JVM- Máquina Virtual Java
Prof. Pablo Azevedo Sampaio BCC / UFRPE
Estrutura da Apresentação
• Máquinas Virtuais • Introdução à JVM • Arquivo class • Tipos de Dados • Descritores de Tipos • Frames • Instruções • Compilando para a JVM • Referências• Definições:
– Particionamento de uma máquina: sistema IBM VM/ESA para o IBM 370 (1965).
– SO rodando sobre SO: Unix sobre Windows – Software que simula o comportamento de
uma máquina (diferente daquela na qual roda).
• Emuladores
– Ambientes independentes de plataforma para linguagens de programação
• O-Code machine para BCPL (1960’s)
• P-Code machine para UCSD Pascal (1970´s) • Smalltalk (1970´s)
• Java Virtual Machine para Java (1995) • Microsoft .NET: VB, C#, C++, ... (2001)
• Impacto na Performance
– Linguagens Interpretadas: JavaScript, Perl, etc.
• Portabilidade e Segurança
• 100x a 200x mais lentas que C
– Linguagens Baseadas em Bytecodes
• Linguagens semi-compiladas • 10 a 20x mais lentas que C • JIT: ~5x mais lenta que C
• Engenho que executa um programa Java • Processador virtual:
– Possui seu próprio conjunto de instruções – Manipula diferentes áreas de memória
• Baseada em pilha de operandos
• Responsável por gerenciar: memória
(garbage collector), erros, exceções, threads
• Garante as seguintes características da linguagem Java: – Portabilidade – Eficiência (JIT) – Segurança
JVM - Introdução
• A JVM não “sabe” nada da linguagem Java. Ela entende apenas arquivos em um formato binário particular: arquivos class.
• Permite rodar outras linguagens desde que seja possível traduzi-las para arquivos class.
– Haskell, Pascal, Ada etc.
• Instruções lembram as de processadores
reais, mas são mais complexas (de mais alto nível).
– Ex: Instruções para manipular objetos
• Camadas de abstração: Programa em Java JVM Sistema Operacional Hardware Java Bytecode
JVM - Introdução
• Formato único independente de plataforma • Ênfase na compacidade
• Representa de maneira precisa uma classe ou interface
• Guarda informações sobre: atributos,
métodos, permissões de acesso, herança. • Informações extras: nomes das variáveis
locais, linhas do código (Java), etc.
• Constant Pool: armazena valores constantes referenciados pelas instruções. Exemplos:
– Nomes e assinaturas de métodos e atributos – Nomes de classes
– Constantes numéricas – Strings constantes
• Constant Pool favorece a compacidade
• Dividem-se em:
– Primitivos – Referência
• Checagem de tipos deve ser feita em tempo de compilação (ou pelo Verifier)
• JVM não faz distinção entre valores de tipos diferentes.
• No entanto, oferece instruções específicas para cada tipo de dado.
• Tipos numéricos:
– Inteiros:
• byte: 8 bits com sinal
• char: 16 bits sem sinal, representando caracteres Unicode
• short: 16 bits com sinal • int: 32 bits com sinal • long: 64 bits com sinal – Ponto-flutuante:
• float: 32 bits com sinal • double: 64 bits com sinal
• Tipo boolean:
– Suporte limitado, não há instrução que opere exclusivamente sobre esse tipo de dado
– Em geral, é tratado com o tipo int da JVM – Valores: 0 (false) e 1 (true)
• Tipo returnAddress:
– Seus valores são ponteiros para opcodes da JVM – Usado por algumas instruções da JVM
– Único tipo que não tem correspondente em Java
• É o tipo usado para referenciar: arrays, classes e interfaces
• Seus valores são endereços para objetos criados dinamicamente
• O valor null representa uma referência inválida
Descritores de Tipos
• São strings usadas para descrever o tipo de um atributo ou método dentro de um arquivo
class.
– Exemplos: “[[I” significa int[][]
• São usados para definir a assinatura de
métodos e atributos e também para acessá-los.
Descritores de Tipos
• descritor_simples: básico | array | classe • Tipos básicos: – “Z”: boolean – “B”: byte – “I”: int – “F”: float – “J”: long – etc.
Descritores de Tipos
• Arrays: “[“ + <descritor_simples>
– Ex.: “[[[Z” => boolean[][][]
• Classes: “L” + <nome_classe> + “;”
– nome_classe: nome “completo” da classe (informando o pacote a que ela pertence, usando barras “/” ao invés de ponto “.”) – Ex.: “Ljava/lang/String;” => String
Descritores de Tipo
• Métodos: “(“ + <descritor_simples>* + “)” + <descritor_simples> • Exemplo: – Um método Java:long[] myMethod(int i, double d, Thread t)
– Descritor do método:
• São estruturas que guardam informações específicas de uma chamada de método.
• São criados a cada chamada de método e destruídos quando a chamada termina.
• São sucessivamente empilhados na JVM Stack em chamadas aninhadas.
• Cada frame da JVM possui:
– Uma pilha de operandos
– Um array de variáveis (locais)
– Referência para a runtime Constant Pool
• Array de variáveis locais
– Posições de 4 bytes acessadas através de seus índices
– Valores byte, char, short, int, ... ocupam uma única posição do array
– Valores long e double ocupam duas posições – Tem seu tamanho determinado em tempo de
compilação e informado no arquivo class
• Pilha de operandos
– Estrutura FILO de onde as instruções buscam seus operandos e para onde retornam resultados
– Vazia quando o frame é criado
– Usada para preparar parâmetros para a chamada a um método, bem como para retornar valores
– Tamanho determinado em tempo de compilação – long e double ocupam dois espaços
this argu men tos var. loca is Pilha de Operandos
Ref. Constant Pool
0 <Class> “My Class”
1 <String> “Hello World” 2 <Integer> 1234567 ... ... 0 1 2 3 4 5 JVM Stack Frame 1 Frame 2 Frame 3 Frame 4 Frame 5
Frames
Instruções
• O conjunto de instruções da JVM não é ortogonal, ou seja, instruções disponíveis para um tipo podem não possuir
instrução análoga para outro tipo.
– O tipo int é o que apresenta melhor suporte na JVM: 23 instruções
– O tipo boolean apresenta o pior suporte: 0 instruções
• Alguns tipos são operados como int:
– char, boolean: estendidos (para 32 bits) com zero – byte, short: estendidos com o sinal
Instruções
• Instruções com opcodes de apenas 1 byte. • Algumas instruções vêm acompanhadas de
um ou mais operandos.
• A maioria das instruções da JVM opera apenas sobre um tipo específico.
• A maioria das instruções tem representado no seu mnemônico o tipo sobre o qual ela opera.
Instruções
• Uma letra para representar cada tipo:
– i : operações sobre int – l : operações sobre long – s : operações sobre short – b : operações sobre byte – c : para char
– f : para float – d : para double
– a : para o tipo referência (classes, arrays, interfaces)
Instruções
• Instruções de load/store:
– Para carregar uma variável local na pilha de operandos: iload, lload, dload, aload, etc. – Para armazenar uma valor da pillha de
operandos em uma variável local: istore,
lstore, fstore, dstore, astore, etc.
– Colocar uma constante na pilha de
operandos: bipush, sipush, ldc, aconst_null, etc.
Instruções
• Instruções aritméticas:
– Soma: iadd, ladd, fadd, dadd.
– Multiplicação: imul, lmul, fmul, dmul. – Negação: ineg, lneg, fneg, dneg.
– Shift: ishl, ishr, lshl, lshr, etc. – AND bit-a-bit: iand, land.
– Comparação: dcmpg, dcmpl, fcmpg, lcmp, etc.
• Retornam –1 (menor), 0 (igual) ou +1 (maior)
– Incrementa variável local (sem colocar na pilha): iinc. – etc.
Instruções
...
3 iload_2 4 bipush 10 6 iadd 7 istore_3...
23 31 235
4
3
2
1
0
23 33...
3 iload_2 4 bipush 10 6 iadd 7 istore_3...
...
3 iload_2 4 bipush 10 6 iadd 7 istore_3...
...
3 iload_2 4 bipush 10 6 iadd 7 istore_3...
...
3 iload_2 4 bipush 10 6 iadd 7 istore_3...
23 10 33...
3 iload_2 4 bipush 10 6 iadd 7 istore_3...
Instruções
• Conversões de tipo:
– A primeira letra é o tipo origem, a última é o tipo destino.
– O número 2 tem o sentido de “to” (para).
– A JVM suporta diretamente as seguinte conversões de extensão (sem perdas significativas):
• int => long => float => double • i2l, i2f, l2f, f2d.
– As outras conversões suportadas podem resultar em perdas significativas do valor: i2b, i2c, l2i, ...
Instruções
• Instruções para criação e manipulação de objetos:
– Criação de objetos: new, newarray, etc. – Acessar atributos: getfield, putfield, etc. – Acessar uma posição do array: baload,
caload, bastore, castore, etc.
Instruções
• Checar propriedades dos objetos:
instanceof, checkcast.
• Instruções para manipulação da pilha e do array de variáveis: pop, pop2, dup, dup2,
Instruções
• Instruções de controle (desvios):
– Desvios incondicionais: goto, goto_w, etc.
– Desvios condicionais: ifeq, iflt, ifle, ifnull, etc.
• Desvios condicionais sobre o tipo int realizam a
comparação automaticamente: if_icmplt, if_icmpeq,
if_icmpg, etc.
• Desvios condicionais sobre outros tipos precisam ser precedidos por uma instrução de comparação:
dcmpg
ifeq loop
Instruções
...
5 fcmpg 6 ifeq 11 9 aconst_null 10 astore_2 11 fload_0...
5
4
3
2
1
0
1.0 5.43 1.0 1.00...
5 fcmpg 6 ifeq 11 9 aconst_null 10 astore_2 11 fload_0...
...
5 fcmpg 6 ifeq 11 9 aconst_null 10 astore_2 11 fload_0...
...
5 fcmpg 6 ifeq 11 9 aconst_null 10 astore_2 11 fload_0...
...
5 fcmpg 6 ifeq 11 9 aconst_null 10 astore_2 11 fload_0...
5.43...
5 fcmpg 6 ifeq 11 9 aconst_null 10 astore_2 11 fload_0...
Instruções
• Chamada e retorno de métodos:
– Chamada: invokevirtual, invokespecial,
invokestatic.
– Retorno: lreturn, freturn, ireturn.
– Ao chamar um método, os parâmetros devem ser colocados (na ordem da declaração) na pilha. Quando a execução termina, o valor de retorno, se houver, é colocado no topo da pilha do frame “pai”.
Compilando para a JVM
• Arquivo “HelloWorld.java”:
public class HelloWorld {
public static void main(String args[]) { System.out.println(“Hello World!”); }
}
• javac HelloWorld.java
Compilando para a JVM
• A ferramenta javap, distribuída junto com o JDK da Sun, permite decompilar:
> javap –c HelloWorld.class
Compiled from HelloWorld.java
public class HelloWorld extends java.lang.Object { public static void main(java.lang.String[]); }
Method void main(java.lang.String[])
0 getstatic #2 <Field java.io.PrintStream out> 3 ldc #3 <String "Hello World!">
5 invokevirtual #4 <Method void
println(java.lang.String)> 8 return
Compilando para a JVM
• O código gerado pelo javap não pode ser alterado e recompilado.
• Para compilar uma arquivo com código assembler JVM é necessário usar alguma biblioteca.
Jasmin
• Java Assembler Interface.
• Compilador de assembly JVM para arquivos
class.
• Recebe um arquivo texto como entrada. • A sintaxe do arquivo é parecida com a dos
arquivos gerados com o javap.
Jasmin – Exemplos
• Exemplo de chamada de método
– Código Java original
int add12and13() {
return addTwo(12, 13); }
Jasmin – Exemplos
• Exemplo de chamada de método
– Código Jasmin:
.method add12and13()I
aload_0 //coloca variável zero na pilha (this)
bipush 12 //coloca constante 12 na pilha bipush 13 //coloca constante 13 na pilha invokevirtual “Classe/addTwo(II)I”
//chama metodo addTwo da classe “Classe”
ireturn //retorna o inteiro do topo da pilha
Jasmin – Exemplos
• Exemplo de uso de parâmetros e retorno de valores:
– Código Java:
double doubleLocals(double d1, double d2){ return d1 + d2;
Jasmin – Exemplos
• Exemplo de uso de parâmetros e retorno de valores:
– Código Jasmin:
.method doubleLocals(DD)D
dload_1 //coloca variável d1 na pilha
dload_3 //coloca variável d2 na pilha
dadd //soma de double
dreturn //retorna o double do topo da pilha
Jasmin – Exemplos
• Instanciando um novo objeto:
– Código Java:
Object create() {
return new Object(); }
Jasmin – Exemplos
• Instanciando um novo objeto:
– Código Jasmin:
.method create()Ljava/lang/Object;
new “java/lang/Object” //aloca espaço no heap
dup //duplica o topo da pilha
invokespecial “java/lang/Object/<init>”
//chama o construtor (método “<init>”)
areturn //retorna a referência para o objeto
Jasmin – Exemplos
• Laço for: – Código Java: void spin() { int i; for (i =0; i < 100; i ++) { ; } }Jasmin – Exemplos
• Laço for:
– Código Jasmin:
.method spin()V
iconst_0 // põe valor zero na pilha
istore_1 // armazena na variável 1 (i=0)
goto teste // desvia para o teste do laço
laco: // label do início do laco
iinc 1 1 // incrementa variável 1 (i) de 1
teste: // label do teste da condicao
iload_1 // põe variável i na pilha
bipush 100 // põe constante 100 na pilha
if_icmplt laco // compara os valores da pilha e desvia return
Referências
• The Java Virtual Machine Specification (Lindholm & Yellin)
– http://java.sun.com (capítulos 3 a 7)
• WikiPedia – The Free Encyclopedia
– http://www.wikipedia.org/wiki/Virtual_machine
• The Core Of Information Technology
– http://cne.gmu.edu/itcore/virtualmachine/history.h
tm
• Jasmin