JVM- Máquina Virtual Java ©André Santos / Pablo Sampaio 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 Máquinas Virtuais • 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 Máquinas Virtuais para LP´s • • • • • 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) Máquinas Virtuais para LP´s • 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 JVM - Introdução • 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 JVM - Introdução • 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 JVM - Introdução • Camadas de abstração: Programa em Java Java Bytecode JVM Sistema Operacional Hardware Arquivo class • 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. Arquivo .class • 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 Arquivo class Tipos de Dados • 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 Primitivos • 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 Tipos Primitivos • 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 Tipo Referência • É 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: (IDLjava/lang/Thread;)[J Frames • 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 Frames • 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 Frames • 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 Frames Pilha de Operandos Frame 5 0 1 2 3 4 5 Frame 4 Frame 3 Ref. Constant Pool Frame 2 Frame 1 JVM Stack 0 1 2 ... <Class> “My Class” <String> “Hello World” <Integer> 1234567 ... 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 5 ... 4 3 3 4 bipush 10 31 33 6 2 23 iload_2 iadd 7 istore_3 1 10 0 33 23 ... 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. – Tamanho do array: arraylength 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, swap, wide, etc. 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 – Switch: tableswitch, lookupswitch Instruções 5 ... 4 5 3 6 ifeq 11 9 2 fcmpg aconst_null 10 astore_2 1 1.0 1.0 11 fload_0 0 5.43 5.43 0 1.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 – Gera o arquivo HelloWorld.class 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. – Exemplos: Jas, Jasmin, Kawa, etc. 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. • java jasmin.Main <arquivo_fonte> 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 .end method 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 constante d2 na pilha dadd //soma de double dreturn //retorna o double do topo da pilha .end method 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 .end method 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 istore_1 goto teste laco: iinc 1 1 teste: iload_1 bipush 100 if_icmplt laco return .end method // // // // // // // // // põe valor zero na pilha armazena na variável 1 (i=0) desvia para o teste do laço label do início do laco incrementa variável 1 (i) de 1 label do teste da condicao põe variável i na pilha põe constante 100 na pilha compara os valores da pilha e desvia 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.ht m • Jasmin – http://cat.nyu.edu/meyer/jasmin