You are on page 1of 116

UNIVERSIDADE ESTADUAL DE CAMPINAS

Instituto de Computao

MO401 Arquitetura de Computadores I Prof. Dr. Ricardo Pannain

Arquitetura de Mquinas Virtuais

Daniele Junqueira Frosoni Diego Zuquim Guimares Garcia Fabiano Costa Teixeira

Maio, 2005

NDICE
1. INTRODUO ..............................................................................................................................................................5 1.1. 1.2. 2. CENRIO .................................................................................................................................................................5 OBJETIVO ................................................................................................................................................................7

ESTRUTURA DA MQUINA VIRTUAL JAVA.......................................................................................................8 2.1. 2.2. 2.3. 2.4. 2.5. ARQUIVO DE CLASSE ...............................................................................................................................................9 TIPOS DE DADOS .....................................................................................................................................................9 MEMRIA JVM .....................................................................................................................................................12 QUADROS ..............................................................................................................................................................15 EXCEES .............................................................................................................................................................16

3.

ARQUITETURA CLR ................................................................................................................................................17 3.1. 3.2. 3.3. MEMRIA CLR .....................................................................................................................................................19 ESTADO GLOBAL ...................................................................................................................................................19 ESTADO DE MTODO .............................................................................................................................................20

4.

CONJUNTO DE INSTRUES JVM ......................................................................................................................22 4.1. 4.2. 4.3. 4.4. 4.5. 4.6. 4.7. 4.8. 4.9. INSTRUES LOAD/STORE......................................................................................................................................27 INSTRUES ARITMTICAS/LGICAS ....................................................................................................................27 INSTRUES DE CONVERSO DE T IPOS .................................................................................................................28 INSTRUES DE OBJETOS ......................................................................................................................................28 INSTRUES DE PILHA...........................................................................................................................................29 INSTRUES DE DESVIO ........................................................................................................................................29 INSTRUES DE MTODOS ....................................................................................................................................29 INSTRUES DE EXCEES ...................................................................................................................................30 INSTRUES DE SINCRONIZAO ..........................................................................................................................30

5.

CONJUNTO DE INSTRUES CLR.......................................................................................................................30 5.1. 5.2. 5.3. 5.4. 5.5. 5.6. TIPOS DE DADOS SUPORTADOS .............................................................................................................................30 TIPOS NUMRICOS .................................................................................................................................................32 TIPOS PONTEIROS ..................................................................................................................................................32 DADOS AGREGADOS..............................................................................................................................................33 CONTROLE DE FLUXO ............................................................................................................................................35 INVOCAO DE MTODOS .....................................................................................................................................36

6.

FORMATO DO ARQUIVO DE CLASSE JAVA .....................................................................................................36 6.1. 6.2. 6.3. 6.4. ESTRUTURA DO ARQUIVO DE CLASSE ...................................................................................................................36 CONSTANT POOL ....................................................................................................................................................38 ESTRUTURA DE CAMPOS .......................................................................................................................................42 ESTRUTURA DE MTODOS .....................................................................................................................................43

4
6.5. 6.6. 6.7. 6.8. 6.9. 6.10. 7. ESTRUTURA DE ATRIBUTOS ...................................................................................................................................44 RESTRIES NO CDIGO JVM...............................................................................................................................46 VERIFICAO DE ARQUIVO DE CLASSE .................................................................................................................48 VERIFICAO DE BYTECODE ..................................................................................................................................49 MANIPULADORES DE EXCEES ...........................................................................................................................51 FORMATO DE ARQUIVO CLR ................................................................................................................................51

EXECUO DE PROGRAMAS ...............................................................................................................................52 7.1. 7.2. 7.3. 7.4. 7.5. 7.6. 7.7. EXECUO DE PROGRAMAS JVM .........................................................................................................................52 CARGA DE TIPOS ...................................................................................................................................................52 LIGAO DE TIPOS ................................................................................................................................................54 INICIALIZAO DE T IPOS .......................................................................................................................................55 OBJETOS ................................................................................................................................................................56 DESCARGA DE T IPOS .............................................................................................................................................57 EXECUO DE PROGRAMAS CLR..........................................................................................................................58

8.

COMPILAO............................................................................................................................................................61 8.1. 8.2. 8.3. 8.4. 8.5. 8.6. 8.7. 8.8. 8.9. 8.10. 8.11. 8.12. 8.13. USO DE CONSTANTES E VARIVEIS LOCAIS, E DE CONSTRUES DE CONTROLE ....................................................61 ARITMTICA ..........................................................................................................................................................63 ALCANANDO O CONSTANT POOL..........................................................................................................................63 MAIS CONSTRUES DE CONTROLE ......................................................................................................................63 RECEBENDO ARGUMENTOS ...................................................................................................................................64 INVOCANDO MTODOS ..........................................................................................................................................65 TRABALHAR COM INSTNCIAS DE CLASSE ............................................................................................................67 ARRAYS.................................................................................................................................................................69 COMPILANDO SWITCHES .......................................................................................................................................70 OPERAES NA PILHA DE OPERANDOS..................................................................................................................72 MANIPULANDO EXCEES ....................................................................................................................................72 COMPILAR FINALMENTE ........................................................................................................................................76 SINCRONIZAO ....................................................................................................................................................78

9.

LINHAS DE EXECUO E MONITORES.............................................................................................................79 9.1. 9.2. 9.3. SINCRONIZAO ....................................................................................................................................................79 TRAVAMENTO DE OBJETOS ...................................................................................................................................81 SUPORTE NO CONJUNTO DE INSTRUES ..............................................................................................................82 REFERNCIAS BIBLIOGRFICAS...................................................................................................................84 CONJUNTO DE INSTRUES JVM COMPLETO ......................................................................86 MQUINAS VIRTUAIS IMPLEMENTADAS EM HARDWARE ..............................................110

10.

APNDICE A. APNDICE B.

Arquitetura de Mquinas Virtuais

1. Introduo
Segundo Meijer (2001) e Venners (1997), mquina virtual (virtual machine) uma abstrao que define um modelo computacional, e tambm uma implementao, construda sobre outra mquina virtual, ou diretamente em hardware. Recentemente, o termo tem sido empregado, usualmente, para referenciar uma plataforma de software que existe em mltiplas plataformas de hardware, e prov uma camada de abstrao que possibilita aos programadores desenvolverem programas sem considerar o hardware no qual eles sero executados. Em sua forma tpica, uma mquina virtual pode ser considerada uma camada de software, conforme ilustrado abaixo: Programas Compilados Mquina Virtual Plataforma Computacional (Hardware e Sistema Operacional)
Figura: localizao de uma mquina virtual em um sistema computacional. Fonte: Venners (1997) [adaptada].

Como exemplos de mquinas virtuais podem ser citadas as mquinas: Sun Microsystems Java Virtual Machine, para a tecnologia Java; Microsoft Common Language Runtime, para a tecnologia .NET; Perl Foundation Parrot Code Virtual Machine, para as tecnologias Perl e Python.

Mquinas virtuais so empregadas para solucionar problemas importantes, considerando o modelo computacional corrente, tais como, compartilhar o mesmo hardware entre muitos programas atravs do particionamento do mesmo, possibilitar que o software seja portvel entre vrios sistemas operacionais, bem como, executar programas legados em plataformas computacionais atuais. A palavra virtual do termo mquina virtual empregada com o sentido de simulao, pois, desejado que a mquina virtual comporte-se como se fosse a mquina real. Portanto, apesar de existirem diversos tipos de implementao de mquinas virtuais, em sua forma mais bsica, uma mquina virtual a simulao de uma mquina que na verdade no est presente. O termo virtual refere-se de fato ao conjunto de instrues. Existem diversos tipos de mquinas virtuais, mas, o tema comum entre elas a idia de simular um conjunto de instrues de uma mquina. Cada mquina virtual utiliza um conjunto de instrues virtual que o usurio tem acesso, e ento a mquina virtual mapeia essas instrues virtuais para o conjunto de instrues real do computador.

1.1. Cenrio
De acordo com Venners (2000) e Microsoft (2001), as infra-estruturas de dispositivos microprocessados portteis e ubquos, e de redes de interconexo de computadores, proporcionam um ambiente que gera desafios ao desenvolvimento da computao. As tecnologias baseadas em abstraes de mquinas, tais como Java e .NET, so inerentemente apropriadas para tal ambiente, possibilitando a distribuio em redes, e a execuo em ambientes computacionais heterogneos, de programas independentes de plataforma.

Arquitetura de Mquinas Virtuais

Figura: applet Java e rede de computadores. Fonte: Venners (2000).

A tecnologia de maior destaque a arquitetura Java, que engloba: linguagem de programao Java; mquina virtual Java (Java Virtual Machine JVM); interface de programao de aplicao Java (Java Application Programming Interface Java API); formato de arquivo de classe Java (Java Class File Format).

Esses quatro componentes da arquitetura Java relacionam-se da seguinte maneira: o programa expresso em arquivos fonte na linguagem de programao Java, chamando mtodos nas classes que implementam a Java API para acessar recursos de sistema; tais arquivos so compilados para arquivos de classe Java, que so executados na JVM, invocando as rotinas da Java API. Em conjunto, a JVM e a Java API constituem uma plataforma abstrata para a qual os programas so compilados. Consequentemente, programas podem ser executados em quaisquer plataformas reais para as quais a Plataforma Java (Java Platform) tenha sido implementada.

Figura: ambiente de programao Java. Fonte: Venners (2000).

Arquitetura de Mquinas Virtuais

1.2. Objetivo
Este trabalho foca em um dos quatro componentes da arquitetura Java: a JVM; objetivando, por meio dessa mquina especfica, desenvolver conceitos que permeiam o assunto de mquina virtual, uma estratgia adotada por diversas tecnologias, com o objetivo de suportar a independncia de plataforma computacional de forma transparente aos desenvolvedores de software. JVM um computador abstrato, cuja especificao define caractersticas que toda implementao de mquina virtual Java deve possuir, mas, flexvel, possibilitando opes por parte dos projetistas de implementaes de mquinas virtuais. A flexibilidade da especificao possibilita que a JVM possa ser implementada em variados dispositivos, conforme indica Gough (2001). Toda JVM deve ser apta a executar instrues JVM (bytecodes), entretanto, o projetista pode escolher que tcnica utilizar para a execuo dos bytecodes. Alm disso, uma JVM pode ser implementada completamente em software, com graus variados em software e hardware, ou mesmo completamente em hardware. A principal tarefa da JVM carregar arquivos de classe (.class) e executar os bytecodes contidos neles. Uma JVM contm basicamente dois componentes: carregador de classe (class loader), que carrega arquivos de classe tanto do programa quanto da Java API, sendo que, apenas as classes da Java API que so necessrias de fato para o programa em execuo so carregadas na mquina virtual; motor de execuo (execution engine), que responsvel pela execuo dos bytecodes. O motor de execuo pode variar em implementaes JVM diferentes: na variao mais simples, o motor de execuo apenas interpreta os bytecodes um por vez; em outra variao, mais rpida, mas que porm requer mais memria, o motor um compilador JIT (just-in-time), que compila os bytecodes de um mtodo para cdigo nativo de mquina na primeira vez que o mtodo invocado, e o armazena em cache, de forma que possa ser reutilizado na prxima vez que o mesmo mtodo for invocado; uma variao intermediria do motor de execuo o otimizador adaptativo, tcnica na qual a mquina virtual inicia com a interpretao dos bytecodes, mas monitora a execuo do programa, procurando identificar as pores de cdigo mais utilizadas, que so compiladas para cdigo nativo e otimizadas, com o restante do cdigo permanecendo como bytecodes, os quais a mquina virtual continua interpretando; as trs primeiras tcnicas so empregadas quando a JVM implementada em software, mas, em uma JVM construda sobre um chip que executa bytecodes Java nativamente, o motor de execuo est de fato embutido no chip.

Figura: JVM implementada em software sobre um sistema operacional hospedeiro. Fonte: Venners (2000).

Arquitetura de Mquinas Virtuais

Em Java existem dois tipos de mtodos: mtodos Java, que so escritos na linguagem Java, compilados para bytecodes, e armazenados em arquivos de classe; mtodos nativos, que so escritos em alguma outra linguagem (por exemplo, C e C++), compilados para o cdigo nativo de mquina de um processador especfico, e armazenados em bibliotecas de ligao dinmica.

Mtodos Java so independentes de plataforma, ao contrrio de mtodos nativos, e, portanto, um programa que utiliza mtodos nativos torna-se dependente de plataforma. Quando um programa Java em execuo chama um mtodo nativo, a mquina virtual carrega a biblioteca dinmica que contm o mtodo nativo e o invoca. Mtodos nativos proporcionam uma conexo entre um programa Java e o sistema operacional, possibilitando acesso direto aos seus recursos. No decorrer do trabalho, temas tratados em relao JVM sero abordados no contexto da CLR, com o objetivo de apresentar a arquitetura dessa mquina virtual, e, possibiltar a comparao entre as tecnlogias. O Microsoft .NET Framework contm a CLR (Common Language Runtime), uma implementao do padro CLI, conforme indica Meijer (2001). A CLI (Common Language Infrastructure), descrita no padro ECMA Standard 335, define a plataforma bsica para a arquitetura .NET. A mquina virtual CLR proporciona as mesmas vantagens discutidas com relao JVM. Entretanto, uma das principais vantagens apresentadas refere-se ao desenvovlimento cross-language, ou seja, a possibilidade de escrever programas em diversas linguagens de programao, tais como, C#, J#, VB.NET, dentre outras. Os cdigos fontes so compilados para uma linguagem intermediria comum, a MSIL (Microsoft Intermediate Language), que desempenha o mesmo papel dos bytecodes Java. A CLR executa instrues MSIL por meio de um compilador JIT (diferentemente da JVM a CLR nunca atua como interpretador). Apesar de a JVM poder suportar desenvolvimento cross-language, devido a algumas restries do framework Java, o suporte muitas vezes difcil e algumas vezes incompleto. Isso conseqncia do compromisso de projeto relativo segurana da mquina virtual. A CLR apresenta as seguintes caractersticas, no presentes na JVM: objetos na pilha (records, unions), chamada por referncia, argumentos variveis, apontadores, matrizes, checagem de overflow, tail calls, tipos de dados de tamanho nativo. Isso a torna mais apropriada para utilizao com variadas linguagens de programao.

2. Estrutura da Mquina Virtual Java


A figura abaixo demonstra a estrutura da JVM. Os componentes sero apresentados a seguir.

Arquitetura de Mquinas Virtuais

Figura: arquitetura interna da mquina virtual Java. Fonte: Venners (2000).

2.1. Arquivo de Classe


Segundo Lindholm (1996) e Venners (1996, 2000), toda implementao JVM deve ser capaz de ler arquivos de classe e realizar as operaes neles especificadas. Quando um programa fonte escrito em Java compilado, gerado um cdigo independente de hardware e sistema operacional. Esse cdigo armazenado geralmente, mas no necessariamente, em um arquivo de classe. Esse arquivo , analogamente, comparado a um arquivo executvel (.exe) gerado pelo compilador da linguagem C++ para ambientes Microsoft Windows. Eles se diferem principalmente na forma de execuo, pois o arquivo executvel executa diretamente na plataforma, ao passo que o de classe executado em uma mquina virtual.

2.2. Tipos de Dados


Assim como a linguagem de programao Java, a JVM trabalha com tipos de dados primitivos e de referncias. Ambos os tipos de dados podem ser armazenados em variveis, passados como argumentos, retornados por mtodos e manipulados como valores primitivos e valores de referncia. O conjunto de instrues da mquina virtual Java distingue os tipos dos operandos de uma instruo. Por exemplo, para as instrues de adio de dois valores so oferecidas as instrues: iadd, ladd, fadd e dadd (as instrues JVM so apresentadas no Apndice A), que so, respectivamente, utilizadas para efetuar somas de valores dos tipos int, long, float e double.

Arquitetura de Mquinas Virtuais

10

Figura: tipos de dados da mquina virtual Java. Fonte: Venners (2000).

A mquina virtual contm explicitamente suporte a objetos. Um objeto tanto uma instncia de classe dinamicamente alocada, como um vetor (array). Objetos so referenciados por meio do tipo de dado reference, que pode ser considerado um ponteiro para objeto. 2.2.1. Tipos de Dados Primitivos e Valores Os tipos de dados primitivos suportados pela JVM so: numrico, booleano (boolean) e endereo de retorno (returnAddress). O tipo numrico consiste dos tipos inteiro e ponto-flutuante. So eles: byte: composto por 8 bits, sinalizado por complemento a dois; short: composto por 16 bits, sinalizado por complemento a dois; int: composto por 32 bits, sinalizado por complemento a dois; long: composto por 64 bits, sinalizado por complemento a dois; char: composto pos 16 bits, no sinalizado, com a finalidade de representar caracteres Unicode; float: cujos valores so elementos do conjunto de valores de ponto-flutuante em preciso simples, ou, onde suportado, o conjunto de valores de ponto-flutuante em preciso simples com expoente estendido; double: cujos valores so elementos do conjunto de valores de ponto-flutuante em preciso dupla, ou, onde suportado, o conjunto de valores de ponto-flutuante em preciso dupla com expoente estendido.

Os valores do tipo de dados boolean representam os dois valores de tabela-verdade: verdadeiro (true) e falso (false). Os valores de um tipo de dados returnAddress so ponteiros para opcodes de instrues JVM. Dos tipos primitivos manipulados pela JVM, somente o tipo returnAddress no diretamente associado a um tipo da linguagem de programao Java.

Arquitetura de Mquinas Virtuais

11

2.2.2. Tipos de Dados Integrais e Valores Os valores para variveis dos tipos numricos suportados pela JVM so os mesmos utilizados na linguagem de programao Java: byte: de 128 a 127; short: de 32768 a 32767; int: de 2147483648 a 2147483647; long: de 9223372036854775808 a 9223372036854775807; char: de 0 a 65535.

2.2.3. Tipos de Dados Ponto-Flutuante e Valores Os tipos ponto-flutuante so float e double, que so conceitualmente associados aos formatos de 32 bits (preciso simples) e 64 bits (preciso dupla), especificados no padro IEEE 754 (Standard for Binary Float-Point Arithmetic, ANSI/IEEE Std. 754-1985). O padro IEEE 754 inclui no somente nmeros com sinais positivos e negativos, como tambm zeros positivos e negativos, infinitos positivos e negativos, e o Not-a-Number Value, que utilizado para representar o resultado de certas operaes invlidas como, por exemplo, a diviso por zero. Toda implementao JVM requer o suporte de dois conjuntos padres de valores de pontoflutuante, chamados float value set e double value set. Uma implementao da mquina virtual Java pode, opcionalmente, suportar conjuntos de valores de ponto-flutuante com expoente estendido, chamados: float-extended-exponent value set e double-extended-exponent value set. 2.2.4. Tipo de Dados returnAddress e Valores O tipo returnAddress (endereo de retorno) utilizado pelas instrues jsr, ret, e jsr_w da mquina virtual (descritas no Apndice A). Os valores de um tipo returnAddress so ponteiros para opcodes das instrues da mquina virtual Java. Ao contrrio dos tipos primitivos numricos, o tipo returnAddress no corresponde a nenhum tipo de dados da linguagem de programao Java e no pode ser modificado pelo programa em execuo. 2.2.5. Tipo de Dados Boolean e Valores Embora a mquina virtual defina um tipo boolean ela no tem instrues exclusivas para tratar esse tipo de dados. Sendo assim, instrues na linguagem Java que utilizam tipo de dados boolean so compiladas para trabalhar com o tipo de dados int. Dessa forma, o compilador mapeia os valores true e false para os valores inteiros 1 e 0, respectivamente. 2.2.6. Tipo de Dados Reference e Valores Existem trs gneros de tipos de referncia (reference): classe, array e interface. Seus valores so referncias para instncias de classe, arrays, e instncias de classe ou arrays que implementam uma interface. Alm disso, pode ser atribudo o valor nulo (null) a uma referncia, o qual no aponta para nenhum objeto.

Arquitetura de Mquinas Virtuais

12

2.3. Memria JVM


A mquina virtual Java define vrias reas de dados de tempo de execuo (run-time data reas), que constituem a memria da mquina, e so utilizadas durante a execuo de um programa. Algumas dessas reas so criadas durante a inicializao da mquina virtual e so destrudas somente quando essa se encerra. Outras reas de dados so para linhas de execuo (threads), tendo como tempo de vida o mesmo da thread. 2.3.1. Registrador Program Counter A mquina virtual suporta a execuo de vrias threads simultaneamente. Cada thread da JVM executa o cdigo de um nico mtodo, referido como o mtodo corrente para a thread. Dessa forma cada thread sendo executada possui seu prprio registrador program counter (PC), que armazena, caso o cdigo atualmente processado no seja nativo, o endereo da instruo JVM que est sendo executada. Caso o cdigo executado pela thread seja nativo, o valor do PC indefinido. 2.3.2. Pilha Cada thread executada na mquina virtual possui uma pilha (stack) privada, criada conjuntamente com a thread, com a finalidade de armazenar quadros de mtodos (frames). Essas pilhas tm um funcionamento anlogo quelas utilizadas em linguagens convencionais, como no caso da linguagem de programao C, armazenam variveis locais, resultados parciais, dentre outros valores. Pelo fato da pilha no ser manipulada diretamente, exceto para empilhar (push) e desempilhar (pop) frames, ela pode ser alocada dinamicamente, no necessitando assim de memria contgua para armazen-la. A mquina virtual permite que essa pilha tenha tamanho fixo ou variado (dependendo da necessidade da execuo ela pode ser expandida ou contrada). Para o caso de ela ter o tamanho fixo, esse valor pode ser definido pelo programador. Para o caso de ser variado os tamanhos mnimo e mximo tambm podem ser definidos. Alguns erros podem ocorrer em funo da utilizao da pilha: se a execuo da thread requer um tamanho de pilha maior que o permitido dispara uma exceo de StackOverflowError; para o caso de expanso dinmica, se no momento da expanso no houver memria suficiente para efetuar a operao dispara uma exceo de OutOfMemoryError. 2.3.3. Heap A mquina virtual Java contm uma rea heap que compartilhada entre todas as threads. a partir dessa rea de dados de tempo de execuo que memria para todas as instncias alocada. A rea heap criada no momento de inicializao da mquina virtual. Ela pode ter um tamanho fixo pr-definido, ou ser expandida ou contrada dinamicamente, de acordo com a necessidade da computao corrente (podendo ter seus tamanhos mnimo e mximo pr-definidos). A memria para a rea heap no precisa ser contgua. Essa rea gerenciada por um sistema de gerenciamento de armazenamento automtico, mais conhecido como coletor de lixo (garbage collector). As sees da rea heap utilizadas para armazenamento de objetos so recuperadas pelo garbage collector automaticamente, de forma que objetos nunca so desalocados da rea heap explicitamente. Se for necessrio um tamanho de rea heap maior que aquele que pode ser disponibilizado pelo sistema de gerenciamento de armazenamento, a mquina virtual dispara uma exceo de OutOfMemoryError.

Arquitetura de Mquinas Virtuais

13

2.3.4. rea de Mtodo A JVM tem uma rea de mtodo (method area), que compartilhada entre todas as suas threads. A rea de mtodo anloga rea de armazenamento para cdigo compilado de uma linguagem de programao convencional, ou, anloga ao segmento de texto (text segment) em um processo Unix. A rea de mtodo armazena as estruturas especficas de cada classe, tais como, o conjunto de constantes de tempo de execuo (runtime constant pool), dados de campo (field data), dados de mtodo (method data), cdigo para mtodos e construtores, incluindo mtodos especiais utilizados na inicializao de instncias (objetos) e tipos (classes e interfaces). Essa rea criada na inicializao da mquina virtual, e apesar dessa rea ser logicamente parte da reas heap, implementaes JVM podem decidir a respeito da coleta de lixo e da compactao dessa rea. Seu tamanho pode ser fixo ou expansvel com limites definidos, e a memria no precisa ser contgua. A condio de exceo relacionada com essa rea acontece se memria na rea de mtodo no pode ser disponibilizada para satisfazer uma requisio de alocao. Para tal situao, a JVM dispara uma exceo de OutOfMemoryError.

Figura: runtime data areas compartilhadas entre todas as threads. Fonte: Venners (2000).

2.3.5. Runtime Constant Pool Uma rea de dados de conjunto de constantes de tempo de execuo (runtime constant pool) uma representao de tempo de execuo da tabela de constantes em um arquivo de classe. Portanto, cada tipo (classe ou interface) possui seu runtime constant pool, que armazena diversos tipos de constantes, variando de literais numricos conhecidos em tempo de compilao a referncias de campos e mtodos que devem ser resolvidas em tempo de execuo. A rea de runtime constant pool possui uma funo similar funo de uma tabela de smbolos para uma linguagem de programao convencional, apesar de ela conter uma variao mais ampla de dados. Cada runtime constant pool alocada na rea de mtodo da JVM, a partir da criao de um tipo pela JVM. A construo de reas de runtime constant pool tambm sujeita a erros, e portanto, quando da criao de um tipo, se a construo da rea de runtime constant pool requerer mais memria que pode ser disponibilizada na rea de mtodo, a mquina virtual dispara uma exceo de OutOfMemoryError.

Arquitetura de Mquinas Virtuais

14

2.3.6. Pilhas de Mtodos Nativos Uma JVM pode utilizar pilhas convencionais, coloquialmente chamadas C Stacks, para suportar mtodos nativos (mtodos implementados em outras linguagens de programao que no Java). Se a implementao JVM no suportar carga de mtodos nativos, no necessrio alocar reas de dados para pilhas de mtodos nativos. Caso contrrio, pilhas de mtodos nativos so alocadas por thread, quando de sua criao. Uma aplicao Java em execuo pode utilizar outras reas de dados criadas para mtodos nativos. Quando um mtodo nativo invocado, a execuo entra em um outro mundo, onde as estruturas e restries de segurana da mquina virtual no podem mais ser totalmente preservadas. Um mtodo nativo pode utilizar reas de dados de tempo de execuo da mquina virtual ou utilizar os registradores nativos do processador real, alocar memria nativa e utilizar qualquer tipo de pilha nativa. Mtodos nativos so inerentes implementao. Projetistas de implementaes JVM so livres para escolherem os mecanismos que sero utilizados para habilitar uma aplicao Java a acessar mtodos nativos. Quando uma thread invoca um mtodo nativo ela dinamicamente faz uma ligao (link) e diretamente invoca o mtodo. Uma maneira de se fazer isso estendendo dinamicamente a prpria mquina virtual com o cdigo nativo. como se a mquina virtual estivesse invocando um mtodo prprio. Se a implementao da interface de cdigo nativo utilizar o modelo de ligao da linguagem C, ento as pilhas de mtodos nativos sero C Stacks. Nesse modelo, quando um programa C invoca uma funo C, os parmetros so empilhados em certa ordem, o controle passado funo que desempilha esses parmetros, efetua o processamento e empilha o resultado de retorno. A figura abaixo ilustra uma forma de invocao de um mtodo nativo. Um mtodo Java invoca outro mtodo, o qual invoca um mtodo nativo. Esse mtodo nativo invoca ou outro que por sua vez, atravs da interface de mtodos nativos, invoca um mtodo Java.

Figura: pilha para uma thread que invoca mtodos Java e nativos. Fonte: Venners (2000).

As pilhas de mtodos nativos podem ser de tamanho fixo ou varivel. Uma implementao JVM pode prover ao programador ou ao usurio controle sobre os limites de tamanho da pilha. As excees tratadas pela JVM para o caso de pilhas de mtodos nativos so as mesmas para o caso de

Arquitetura de Mquinas Virtuais

15

pilhas de mtodos Java (StackOverflowError e OutOfMemoryError).

2.4. Quadros
Quadros (frames) so utilizados para armazenar dados e resultados parciais, fazer ligao dinmica, retornar valores para mtodos e disparar excees. Um novo quadro criado toda vez que um mtodo invocado e destrudo quando a execuo do mtodo termina. Ele armazenado na pilha da thread associada. Cada quadro possui seu prprio array de variveis locais, sua prpria pilha de operandos e uma referncia para o run-time constant pool da classe do mtodo atual. Somente um quadro, aquele do mtodo em execuo, ativo durante um determinado ponto na execuo de uma thread. Esse quadro referido como quadro corrente (current frame) e seu mtodo como mtodo corrente (current method). A classe na qual o mtodo corrente definido dita como classe corrente (current class). Operaes em variveis locais e pilha de operandos so feitas com referncia ao quadro corrente. Um quadro deixa de ser corrente quando um mtodo invoca um outro mtodo ou quando conclui sua execuo. Quando um mtodo invocado, criado um novo quadro, e esse se torna corrente quando o controle transferido para o novo mtodo. No retorno do mtodo, o quadro corrente retorna o resultado de sua invocao de mtodo, se houver algum, ao quadro anterior. Ento esse quadro descartado e o anterior passa a ser o corrente.

Figura: runtime data areas exclusivas para cada thread. Fonte: Venners (2000).

2.4.1. Variveis Locais Cada quadro contm um array de variveis chamado local variables. Seu tamanho definido em tempo de compilao e inserido na representao binria da classe juntamente com o cdigo do mtodo associado. Uma varivel local pode armazenar dados dos tipos: boolean, byte, char, short, int, float, reference, returnAddress, long e double.

Arquitetura de Mquinas Virtuais

16

Variveis locais so endereadas atravs de indexao. O ndice da primeira varivel local 0. Um nmero inteiro pode ser considerado como um ndice do vetor de variveis locais se, e somente se, ele for maior ou igual a 0 e menor que o tamanho do array. Valores para tipos long e double ocupam duas posies do array. Sendo assim, para enderelos devemos utilizar o menor valor de ndice das duas posies ocupadas. O array de variveis locais utilizado para a passagem de parmetros a um mtodo. A posio 0 do array utilizada para armazenar a referncia ao objeto do qual pertence o mtodo invocado (utilizado pelo this na linguagem Java) e os demais parmetros so passados da posio 1 do array em diante. 2.4.2. Pilha de Operandos Cada quadro possui uma pilha chamada operand stack. A mquina virtual Java fornece instrues para armazenar dados nessa pilha, e tambm outras que retiram valores da pilha, efetuam operaes com eles e devolvem os resultados na pilha. Essa pilha utilizada para preparar os parmetros a serem passados a um mtodo, bem como para armazenar o resultado do mtodo. Por exemplo, a instruo iadd efetua a adio de dois valores do tipo int. Essa instruo requer que os dois operandos da adio estejam nas duas posies mais altas da pilha atravs de instrues de empilhamento executadas anteriormente. Ambos os valores so retirados da pilha, adicionados e o resultado empilhado de volta. Para empilhar um valor do tipo long ou double a pilha incrementada em duas unidades. Para os demais tipos ela incrementada em apenas uma unidade. 2.4.3. Ligao Dinmica Cada quadro contm uma referncia para o run-time constant pool da classe do mtodo corrente para suportar ligao dinmica (dynamic linkage) do cdigo do mtodo. O cdigo contido no arquivo de classe refere-se a mtodos a serem invocados, e variveis a serem acessadas via referncias simblicas. A ligao dinmica traduz essas referncias simblicas a mtodos em referncias concretas a mtodos, carregando classes, se necessrio, para resolver os smbolos no definidos, e tambm traduz acessos a variveis em deslocamentos (offsets) apropriados na estrutura de armazenamento. 2.4.4. Concluso de Invocao de Mtodos A concluso de invocao de um mtodo pode acontecer de duas maneiras: Concluso normal: a invocao de um mtodo conclui normalmente se no foi disparada nenhuma exceo ou, caso tenha sido disparada, essa tenha sido tratada corretamente. Se um mtodo concludo normalmente, ento o resultado pode ser retornado para o mtodo que o invocou. Nesse caso, o quadro do mtodo que o invocou restaurado e o resultado da execuo do mtodo invocado armazenado no topo da pilha do quadro atual; Concluso brusca: a invocao de um mtodo termina bruscamente quando a execuo causa uma exceo e essa no tratada. Um mtodo que conclui dessa forma jamais retorna o resultado ao mtodo que o invocou.

2.5. Excees
Disparar uma exceo implica em uma transferncia de controle imediata a partir do ponto onde

Arquitetura de Mquinas Virtuais

17

a exceo foi disparada. Essa transferncia de controle pode concluir abruptamente, um por um, comandos mltiplos, invocaes de construtores, avaliaes de inicializadores estticos e de campo e invocaes de mtodos regulares. Na linguagem Java, o processo continua at encontrar uma clusula catch que manipula o valor disparado. Caso contrrio, a thread corrente termina. Nos casos em que uma clusula finally utilizada, ela executada durante a propagao de uma exceo disparada a partir do bloco try associado e qualquer bloco catch associado, mesmo se nenhuma clusula catch que manipula a exceo for encontrada. Conforme implementado pela JVM, cada clusula catch ou finally de um mtodo representada por um manipulador de exceo (exception handler). Um exception handler responsvel por: especificar os limites de deslocamentos nos bytecodes que implementam o mtodo para os quais o exception handler ativo; descrever o tipo de exceo que o exception handler capaz de manipular; especificar a localizao do cdigo que trata a exceo.

Uma exceo emparelha com um exception handler se o deslocamento da instruo que causou a exceo est dentro dos limites de deslocamentos do exception handler e o tipo da exceo a mesma classe ou uma sub-classe da classe de exceo que o exception handler manipula. Quando uma exceo dispara, a JVM procura por um exception handler compatvel no mtodo corrente. Caso algum seja encontrado, o sistema desvia para o cdigo tratador da exceo especificado pelo exception handler compatvel. Caso a JVM no encontre exception handler compatvel no mtodo corrente, a invocao do mtodo corrente concluda abruptamente. Em uma concluso de invocao de mtodo abrupta, a pilha de operando e as variveis locais da invocao de mtodo corrente so descaradas, e seu frame desempilhado, restabelecendo o frame do mtodo que o invocou. A exceo ento disparada novamente no contexto do frame do mtodo invocador, e assim por diante. Caso nenhum exception handler compatvel seja encontrado antes do topo da corrente de invocaes de mtodos ser alcanado, a execuo da thread onde foi disparada a exceo terminada. Os exception handlers para cada mtodo so armazenados em uma tabela no arquivo de classe Java. Em tempo de execuo, quando uma exceo disparada, a JVM procura por exception handlers o mtodo corrente na ordem em que eles aparecem na tabela de exception handler correspondente no arquivo de classe, comeando do incio da tabela. Como os comandos try so estruturados, um compilador Java pode ordenar as entradas na tabela de exception handler de forma que, para qualquer exceo disparada, e qualquer valor de PC (program counter) no mtodo, o primeiro exception handler compatvel com a exceo disparada corresponde clusula catch ou finally mais interna no mtodo. A JVM no demanda qualquer ordem para as entradas da tabela de exception handler de um mtodo. A semntica de manipulao de exceo da linguagem Java implementada com a cooperao apenas do compilador, de forma que, quando arquivos de classe so gerados por outros meios, o procedimento de procura definido pela JVM garante que todas as mquinas virtuais apresentaro comportamento consistentemente.

3. Arquitetura CLR
De acordo com Meijer (2001) e Microsoft (2001), ao prover servios, tais como, carga de classe, verificao, compilao JIT, e gerenciamento de cdigo, a CLR cria um ambiente para execuo de cdigo chamado Virtual Execution System.

Arquitetura de Mquinas Virtuais

18

A figura a seguir mostra os principais elementos da arquitetura da CLR, com os vrios caminhos que podem ser seguidos atravs desse ambiente de execuo.

Figura: arquitetura CLR. Fonte: Microsoft (2000).

Em muitos casos, o cdigo-fonte compilado em MSIL. O cdigo MSIL carregado, compilado em cdigo nativo on-the-fly utilizando um compilador JIT, e executado pela mquina real. No caso de cdigo confivel, a etapa de verificao pode ser omitida. O motor de meta-dados CLR (metadata engine) possibilita ao compilador de cdigo-fonte

Arquitetura de Mquinas Virtuais

19

inserir meta-dados no arquivo PE conjuntamente com o cdigo MSIL compilado. PE significa Portable Executable, o formato utilizado para arquivos executveis (EXE) e bibliotecas de ligao dinmica (DLL). Durante a carga e a execuo, esses meta-dados provem informao necessria para registro, depurao, gerenciamento de memria, e segurana. Tambm indicado no diagrama, est o fato de que classes da .NET Framework Class Library podem ser carregadas pelo carregador de classe juntamente com cdigo nativo, MSIL ou OptIL (um sub-conjunto de instrues MSIL). Outro caminho de execuo que pode ser escolhido envolve pr-compilao para cdigo nativo utilizando um compilador backend. Essa opo pode ser escolhida se compilar cdigo em tempo de execuo, ou seja, compilao JIT, no aceitvel devido a restries de performance. Conforme indicado no diagrama, cdigo nativo pr-compilado desvia da verificao e compilao JIT. Pelo fato de cdigo nativo pr-compilado no ser verificado, ele deve ser considerado cdigo completamente confivel para que possa ser executado.

3.1. Memria CLR


Memria, no contexto de mquina virtual, relaciona-se com a memria de processo regular onde a mquina virtual opera. Conceitualmente, na CLR, assim como na JVM, essa memria simplesmente um array de bytes. O ndice nesse array o endereo de um objeto de dados. A CLR acessa objetos de dados na memria atravs de instrues ldind.* e stind.*. Um dos objetivos de projeto da CLR foi esconder detalhes de um frame (quadro) de invocao de mtodo do gerador de cdigo MSIL. Isso permite que a CLR, e no o gerador de cdigo MSIL, possa escolher a conveno de invocao e o layout de pilha mais eficientes. Para alcanar essa abstrao, o quadro de invocao integrado CLR. As definies de estado de mquina a seguir refletem essas escolhas de projeto, onde estado de mquina consiste primariamente de estado gloabal e estado de mtodo. O alinhamento de tipos de dados maiores que um byte depende do processador alvo. fortemente recomendado que tipos primitivos sejam alinhados para o tamanho do tipo, ou seja, tipos com tamanho igual a dois bytes comeam em endereos pares, com quatro bytes, em endereos divisveis por quatro, e com oito bytes, em endereos divisveis por oito. Existe um prefixo de instruo, unaligned.. Ele pode imediatamente preceder uma instruo ldind, stind, itblk, ou cpblk, e indica que o dado pode no estar alinhado, requerendo que o compilador JIT gere cdigo que no poder causar erros de no-alinhamento de memria. Para tipos de dados maiores que um byte, a ordem de byte dependente do processador alvo. Cdigos que dependem da ordem de byte no podem ser executados em todas as plataformas. O arquivo de cdigo MSIL pode ser marcado para indicar que ele depende de um tipo de ordem de byte particular.

3.2. Estado Global


A CLR gerencia mltiplos threads de controle concorrentes, mltiplas heaps gerenciadas, e um espao de endereamento de memria compartilhado. Uma thread de controle pode ser imaginada como uma lista separadamente ligada de estados de mtodos, onde um novo estado criado e ligado de volta ao estado corrente por uma instruo de invocao de mtodo, seguindo o modelo tradicional de seqncia de invocao baseada em pilha. A figura a seguir ilustra o modelo de estado de mquina, que inclui threads de controle, estados de mtodos, e mltiplas heaps em um espao de endereamento compartilhado.

Arquitetura de Mquinas Virtuais

20

Figura: modelo de estado de mquina CLR. Fonte: Microsoft (2000).

3.3. Estado de Mtodo


O estado de mtodo, mostrado na figura abaixo, uma abstrao do quadro de mtodo. Argumentos e variveis locais so parte do estado de mtodo, mas eles tambm podem conter Object References para dados armazenados em quaisquer das heaps gerenciadas.

Figura: estado de mtodo CLR. Fonte: Microsoft (2000).

Um estado de mtodo descreve o ambiente no qual um mtodo executa (na terminologia

Arquitetura de Mquinas Virtuais

21

convencional de compiladores, ele corresponde a um super-conjunto da informao capturada no invocation stack frame). O estado de mtodo CLR consiste dos seguintes itens: um apontador de instruo (instruction pointer - IP). O IP aponta para a prxima instruo MSIL a ser executada pela CLR no mtodo presente; uma pilha de avaliao (evaluation stack). A pilha est vazia quando do incio da execuo do mtodo. Seu contedo inteiramente local ao mtodo e preservado atravs de instrues de chamada, ou seja, se o mtodo corrente chama outro, uma vez que o mtodo chamado retorne, o contedo da pilha de avaliao do mtodo invocador continua como estava no momento da invocao. A pilha de avaliao no enderevel. Em qualquer instante possvel deduzir que tipo est armazenado em qualquer localizao da pilha; um array de variveis locais (local variable array), iniciando no ndice zero. Valores desse array so preservados atravs de chamadas, assim como acontece com a pilha. Uma varivel local pode conter qualquer tipo de dados. Entretanto, um elemento de array particular deve ser utilizado de uma maneira consistente em relao ao tipo. O endereo de uma varivel local individual pode ser obtido utilizando a instruo ldloca; um array de argumentos (argument array), iniciando no ndice zero. Esse array contm os valores dos argumentos de entrada do mtodo corrente. Eles podem ser lidos ou escritos por indexao lgica. O endereo de um argumento pode ser obtido por meio da instruo ldarga. Alm disso, o endereo de um argumento obtido implicitamente pela instruo arglist para uso em conjunto com iterao typesafe atravs de listas de argumento de tamanho varivel; um methodInfo handle. Ele contm informao read-only sobre o mtodo. Em particular, ele mantm a assinatura do mtodo, os tipos de suas variveis locais, e dados sobre seus manipuladores de exceo; um local memory pool. A CLR contm instrues para alocao dinmica de objetos do local memory pool (localloc). A memria alocada no local memory pool enderevel, e recuperada no momento de finalizao de contexto de mtodo; um return state handle, que utilizado para restaurar o estado de mtodo no retorno do mtodo corrente. Tipicamente, o estado restaurado o do mtodo invocador, mas, tanto o estado de retorno, como o apontador de instruo de retorno, podem ser ajustados pelo gerenciador de cdigo; um security descriptor. Ele no acessvel diretamente pelo cdigo gerenciado, mas, o sistema de segurana o utiliza para manter aes de segurana (assert, permit-only, e deny).

A especificao da CLR (CLI) define uma arquitetura na qual as quatro reas do estado de mtodo, ou seja, array de argumentos de entrada, array de variveis locais, local memory pool e pilha de avaliao, so reas logicamente distintas. Entretanto, implementaes CLI podem mapear essas reas em um array de memria contguo, mantido como um quadro de pilha convencional na arquitetura alvo subjacente. 3.3.1. Pilha de Avaliao Associado a cada estado de mtodo est uma pilha de avaliao. Muitas instrues CLR obtm seus argumentos da pilha de avaliao e armazenam seus valores de retorno nessa pilha. Alm disso, argumentos para outros mtodos e seus valores de retorno tambm so armazenados na pilha de avaliao. Quando uma invocao de mtodo realizada, os argumentos para o mtodo chamado tornamse o array de argumentos de entrada para o mtodo. Isso pode requerer uma cpia de memria, ou

Arquitetura de Mquinas Virtuais

22

simplesmente um compartilhamento dessas duas reas pelos dois mtodos. A pilha de avaliao constituda de slots que podem manter qualquer tipo de dado. O estado de tipo da pilha, ou seja, a profundidade da pilha e tipos de cada elemento na pilha, em qualquer ponto em um programa deve ser idntico para todos os possveis caminhos de fluxo de controle. Por exemplo, um programa que possui um lao que repete um nmero desconhecido de vezes e empilha um novo elemento na pilha a cada iterao proibido. 3.3.2. Variveis Locais e Argumentos Arrays que mantm variveis locais e argumentos de entrada fazem parte de cada estado de mtodo. Assim como a pilha de avaliao, cada elemento desses arrays pode conter qualquer tipo de dados. Associado a cada mtodo esto meta-dados que especificam: se a memria de variveis locais e memory pool dever ser inicializada quando entrar no mtodo; o tipo de cada argumento e o tamanho do array de argumentos de entrada; o tipo de cada varivel local e o tamanho do array de variveis locais.

A CLR insere padding de acordo com o apropriado para a arquitetura alvo. Ou seja, em arquiteturas de 64 bits, todas as variveis locais devem ser alinhadas a 64 bits, enquanto que em outras elas podem ser alinhadas a 8, 16 ou 32 bits. 3.3.3. Local Memory Pool Associado com cada estado de mtodo est um local memory pool. Memria pode ser explicitamente alocada do local memory pool utilizando a instruo localloc. Toda memria no local memory pool recuperada na sada de mtodo, e essa a nica forma de recuperar memria, pois, no h instrues para liberar memria que foi alocada durante a execuo do mtodo corrente. O local memory pool utilizado para alocar objetos cujos tipos e tamanhos no so conhecidos em tempo de compilao, e os quais o programador no deseja alocar na heap gerenciada. Como o local memory pool no pode ser contrado durante o tempo de vida do mtodo, uma linguagem de implementao no pode utiliz-lo para alocao de memria de propsito geral.

4. Conjunto de Instrues JVM


De acordo com Lindholm (1996) e Venners (1996, 2000), um stream de bytecodes de um mtodo uma seqncia de instrues para a JVM. Cada instruo consiste de um opcode de um byte seguido por zero ou mais operandos. O opcode (cdigo de operao) indica a operao a ser realizada. Operandos fornecem informao extra necessitada pela JVM para realizar a operao especificada pelo opcode. O prprio opcode indica se ele ou no seguido por operandos, e a forma que os operandos possuem, caso haja algum. Muitas instrues JVM no possuem operandos, e, portanto, consistem de apenas um opcode. Um mnemnico definido para cada bytecode. Os mnemnicos podem ser imaginados como uma linguagem de montagem (assembly) para a mquina virtual. Por exemplo, existe uma instruo que faz com que a JVM empilhe um valor zero na pilha. O mnemnico para essa instruo iconst_0, e seu bytecode 60. Essa instruo no recebe operandos.

Arquitetura de Mquinas Virtuais

23

Outra instruo faz com que a execuo do programa desvie incondicionalmente para frente ou para trs na memria. Essa instruo requer um operando, um offset sinalizado de 16 bits. Adicionando o offset localizao de memria corrente, a JVM pode determinar a localizao de memria para onde desviar. O mnemnico para essa instruo goto, e seu bytecode a7.

Figura: bytecodes e mnemnicos de instrues JVM. Fonte: Venners (1997).

Dependendo do opcode, a JVM pode referir-se a dados armazenados em outras reas alm de, ou ao invs de, operandos que acompanham o opcode. Quando executa uma instruo, a JVM pode utilizar entradas na constant pool corrente, nas variveis locais do frame corrente, ou valores localizados no topo da pilha de operando do frame corrente. O motor de execuo abstrato da JVM funciona executando bytecodes uma instruo por vez. Esse processo acontece para cada thread (instncia de motor de execuo) do programa em execuo na JVM. Um motor de execuo de uma JVM busca (fetch) um opcode e, se o opcode tem operandos, busca os operandos. Ele executa a ao requerida pelo opcode, e ento busca outro opcode. A execuo de bytecodes continua at que uma thread conclua, tanto retornando ao mtodo invocador, quanto no capturando uma exceo disparada. Ignorando excees, a iterao mais interna de uma mquina virtual o seguinte: faa { busca uma instruo; se (operandos) busca os operandos; executa a ao para o opcode; } enquanto (houver instrues) O motor de execuo pode encontrar uma instruo que requer uma invocao de mtodo nativo. Nessas situaes, o motor de execuo tentar obedientemente invocar o mtodo nativo. Quando o mtodo retornar, se ele completar normalmente, ou seja, sem disparar exceo, o motor de execuo continuar executando a prxima instruo no stream de bytecodes. Mtodos nativos podem ser considerados extenses customizadas pelo programador para o conjunto de instrues da JVM. Se uma instruo requerer uma invocao de um mtodo nativo, o motor de execuo invoca o mtodo nativo. Executar o mtodo nativo como se a JVM executasse a instruo. Quando o mtodo nativo retorna, a mquina virtual passa para a prxima instruo. Se o mtodo nativo dispara uma exceo, a JVM segue os mesmos passos para tratar a exceo que ela segue quando qualquer instruo JVM dispara uma exceo. Parte do trabalho de executar uma instruo a determinao da prxima instruo a ser executada. Um motor de execuo determina o prximo opcode a ser buscado em uma de trs maneiras possveis: para muitas instrues, o prximo opcode a ser executado segue diretamente o opcode corrente e seus operandos, se houver algum, no stream de bytecodes; para algumas instrues, tais como goto e return, o motor de execuo determina o prximo

Arquitetura de Mquinas Virtuais

24

opcode como parte da execuo da instruo corrente; se uma instruo dispara uma exceo, o motor de execuo determina o prximo opcode a buscar procurando por uma clusula catch apropriada.

Diversas instrues podem disparar excees. A instruo athrow, por exemplo, dispara uma exceo explicitamente. Essa instruo a forma compilada de um comando throw no cdigo fonte Java. Sempre que uma instruo athrow executada, ela disparar uma exceo. Outras instrues disparam excees apenas quando determinadas condies so encontradas. Por exemplo, se a JVM descobre que o programa est tentando realizar uma diviso inteira por zero, ela disparar uma ArithmeticException. Isso pode acontecer, por exemplo, enquanto executando quaisquer das quatro instrues idiv, ldiv, irem, e lrem, as quais realizam divises ou clculos de restos em inteiros (int ou long). Cada tipo de opcode no conjunto de instrues JVM tem um mnemnico. No estilo tpico de linguagem de montagem (assembly), streams de bytecodes podem ser representados por seus mnemnicos, seguidos por valores de operando, opcionalmente. Abaixo mostrado um exemplo de stream de bytecodes de um mtodo e mnemnicos. O mtodo utilizado para a exemplificao o mtodo doMathForever(), cujo cdigo fonte Java mostrado abaixo: public static void doMathForever() { int i = 0; for (;;) { i += 1; i *= 2; } } O stream de bytecodes do mtodo doMathForever() pode ser desmontado (disassembled) em mnemnicos como mostrado abaixo. No exemplo, a coluna esquerda mostra o deslocamento (offset) em bytes a partir do incio do stream de bytecodes do mtodo at o incio de cada instruo. A coluna central mostra a instruo e quaisquer operandos em mnemnicos. A coluna direita contm os bytecodes correspondentes aos mnemnicos da instruo. Stream de bytecodes para o mtodo doMathForever(): 03 3b 84 00 01 1a 05 68 3b a7 ff f9 Desmontando o stream de bytecodes para o mtodo doMathForever() em mnemnicos: Offset 0 1 2 5 6 7 8 9 Mnemnico iconst_0 istore_0 iinc 0, 1 iload_0 iconst_2 imul istore_0 goto 2 Bytecode 03 3b 84 00 01 1a 05 68 3b a7 ff f9

A representao de instrues utilizada acima a sada do programa javap do pacote Sun

Arquitetura de Mquinas Virtuais

25

J2SDK, que mostra os mnemnicos de bytecodes de mtodos de qualquer arquivo de classe Java. Os endereos de desvio so determinados como deslocamentos a partir do incio do mtodo. A instruo goto faz com que a JVM salte para a instruo no deslocamento 2. O operando real no stream -7. Para executar essa instruo, a mquina virtual adiciona o operando ao contedo corrente do registrador PC (program counter). O resultado o endereco da instruo iinc no offset 2. Para tornar o mnemnico mais legvel, os operandos para instrues de desvio so mostrados como se a adio j tivesse sido feita. O foco central do conjunto de instrues da JVM a pilha de operando. Valores so usualmente empilhados na pilha de operando antes de serem utilizados. Apesar de a JVM no possuir registradores para armazenar valores arbitrrios, cada mtodo tem um conjunto de variveis locais. O conjunto de instrues trata as variveis locais, de fato, como um conjunto de registradores que so referenciados por ndices. No entanto, diferentemente da instruo iinc, que incrementa uma varivel local diretamente, os valores armazenados em variveis locais devem ser movidos para a pilha de operando antes de serem utilizados. Por exemplo, para dividir uma varivel local por outra, a JVM deve empilhar ambas na pilha de operando, realizar a operao de diviso, e ento armazenar o resultado de volta nas variveis locais. Para mover o valor de um elemento de array ou campo (field) de objeto em uma varivel local, a mquina virtual deve primeiro empilhar o valor na pilha de operando, ento armazen-lo na varivel local. Para colocar em um elemento de array ou campo de objeto um valor armazenado em uma varivel local, a JVM deve seguir o procedimento reverso. Primeiro, ela deve empilhar o valor da varivel local na pilha de operando, e ento desempilh-lo no elemento de array ou campo de objeto na rea heap. Diversos objetivos, alguns conflitantes, guiaram o projeto do conjunto de instrues da JVM. Esses objetivos so basicamente os mesmos que motivaram a arquitetura geral da tecnologia Java: independncia de plataforma, mobilidade de rede e segurana. O objetivo de independncia de plataforma foi a principal influencia no projeto do conjunto de instrues. A abordagem centrada em pilha do conjunto de instrues foi escolhida em contrapartida abordagem centrada em registrador para facilitar implementao eficiente em arquiteturas com poucos registradores ou registradores irregulares, tal como a Intel 80x86. Essa caracterstica do conjunto de instrues, ou seja, a arquitetura centrada em pilha, torna mais fcil a implementao da JVM em uma ampla variedade de arquiteturas hospedeiras. Outra motivao para a arquitetura do conjunto de instrues centrada em pilha que compiladores usualmente utilizam uma arquitetura baseada em pilha para passar uma forma compilada intermediria ou o programa compilado para um ligador/otimizador. O arquivo de classe Java, que em muitos aspectos similar aos arquivos objeto do Unix e Windows emitidos por compiladores C, de fato representa uma forma compilada intermediria de um programa Java. No caso de Java, a mquina virtual atua como ligador dinmico e pode atuar como otimizador. A arquitetura centrada em pilha do conjunto de instrues da mquina virtual Java facilita a otimizao que pode ser realizada em tempo de execuo em conjunto com motores de execuo que realizam compilao JIT ou otimizao adaptativa. O tamanho do arquivo de classe foi tambm um dos principais objetivos de projeto, tendo em vista a possibilidade de facilitar e tornar mais rpida a transmisso de arquivos de classe atravs de redes de computadores. Nos bytecodes armazenados em arquivos de classe, todas as instrues, com exceo de duas que lidam com tabelas de salto, so alinhadas em fronteiras de byte. O nmero total de opcodes demanda apenas um byte para a representao de todos eles. Essa estratgia de projeto favorece a compactao do arquivo de classe, mas proporciona impacto de performance quando o programa executado. Em algumas implementaes JVM,

Arquitetura de Mquinas Virtuais

26

especialmente aquelas que executam bytecodes em chips, o opcode de byte nico pode obstruir certas otimizaes que poderiam aprimorar a performance. Alm disso, melhor performance poderia ser possvel em algumas implementaes se os streams de bytecodes fossem alinhados por palavras ao invs de bytes. Uma implementao poderia sempre realinhar streams de bytecodes, ou traduzir opcodes em uma forma mais eficiente conforme classes so carregadas. Bytecodes so alinhados por bytes nos arquivos de classe e na especificao da rea de mtodo e do motor de execuo. Implementaes concretas podem armazenar os streams de bytecodes carregados da forma que desejarem. Outro objetivo que guiou o projeto da arquitetura do conjunto de instrues foi a habilidade de fazer verificao de bytecode, especialmente todo o stream de uma vez por um analisador de fluxo de dados. A capacidade de verificao necessria como parte do framework de segurana de Java. A habilidade de utilizar um analisador de fluxo de dados nos bytecodes quando eles so carregados, ao invs de verificar cada instruo conforme ela executada, possibilita melhor velocidade de execuo. Uma das formas na qual esse objetivo de projeto se manifesta no conjunto de instrues que os opcodes indicam o tipo com o qual eles operam. Por exemplo, ao invs de ter uma instruo que desempilha uma palavra da pilha de operando e armazena a palavra em uma varivel local, a arquitetura do conjunto de instrues tem duas. Uma instruo, istore, desempilha e armazena um inteiro. A outra, fstore, desempilha e armazena um pontoflutuante. Ambas, portanto, realizam a mesma operao. A distino entre desempilhar e armazenar um int e um float importante somente para o processo de verificao. Para muitas instrues, a mquina virtual necessita saber os tipos que esto sendo operados para saber como realizar a operao. Por exemplo, a JVM suporta dois modos de adio de duas palavras, gerando como resultado uma palavra. Uma adio trata as palavras como inteiros, e a outra, como pontos-flutuantes. A diferena entre essas duas instrues facilita a verificao, conforme indicado anteriormente, mas tambm informa mquina virtual se ela deve realizar aritmtica inteira ou de ponto-flutuante, que envolvem operaes diferenciadas. Poucas instrues operam sobre qualquer tipo. A instruo dup, por exemplo, duplica a palavra do topo de uma pilha indiferentemente de seu tipo. Algumas instrues, tais como goto, no operam com valores tipados. A maioria das instrues, no entanto, operam sobre valores de tipos especficos. Os mnemnicos para muitas dessas instrues tipadas indica seus tipos por um prefixo de um caractere que inicia o mnemnico. A tabela abaixo mostra os prefixos para os diversos tipos. Algumas poucas instrues, tais como, arraylength e instanceof, no incluem um prefixo, pois seus tipos so bvios. O opcode arraylength requer uma referncia de array, e instanceof requer uma referncia de objeto. Tipo byte short int long char float double reference Prefixo b s i l c f d a Exemplo de Instruo baload saload iaload laload caload faload daload aaload

Valores na pilha de operando devem ser utilizados de uma maneira apropriada aos seus tipos. ilegal, por exemplo: desempilhar quarto inteiros, e ento adicion-los como se fossem dois longs.

Arquitetura de Mquinas Virtuais

27

ilegal empilhar um valor do tipo float na pilha de operando a partir das variveis locais, e ento armazen-lo como um inteiro em um array na heap. ilegal empilhar um valor double a partir de um campo de objeto na heap, e ento armazenar a palavra mais significativa de suas duas palavras em variveis locais como um valor de tipo reference. As regras rgidas de tipagem que so aplicadas por compiladores Java devem ser aplicadas tambm por implementaes JVM. Para manter o conjunto de instrues com um tamanho que possibilitasse a representao de todos os opcodes com apenas um byte, nem todas as operaes so suportadas em todos os tipos. Muitas operaes no so suportadas para os tipos byte, short e char, que so convertidos para int quando movidos da rea de mtodo ou da heap para a pilha. Eles so operados como inteiros, e ento convertidos novamente para o tipo correto antes de serem armazenados novamente na heap ou na rea de mtodo.

4.1. Instrues Load/Store


As instrues load e store transferem valores entre as variveis locais e a pilha de operando de um quadro JVM. A seguir so listadas as instrues load e store: carrega uma varivel local na pilha de operando: iload, iload_<n>, lload, lload_<n>, fload, fload_<n>, dload, dload_<n>, aload, aload_<n>; armazena um valor da pilha em uma varivel: istore, istore_<n>, lstore, lstore_<n>, fstore, fstore_<n>, dstore, dstore_<n>, astore, astore_<n>; armazena uma constante na pilha: bipush, sipush, ldc, ldc_w, ldc2_w, aconst_null, iconst_m1, iconst_<i>, lconst_<l>, fconst_<f>, dconst_<d>; obtm acesso a mais variveis locais utilizando um ndice mais amplo, ou a um operando imediato maior: wide.

Mnemnicos com sufixos <x> denotam famlias de instrues, com membros, por exemplo, iload_0, iload_1, iload_2, e iload_3 no caso da instruo iload_<n>. Tais famlias de instrues so especializaes de uma instruo genrica adicional (iload) que carrega um operando. Para as instrues especializadas, o operando implcito e no precisa ser armazenado ou buscado (fetch). De qualquer forma a semntica a mesma, por exemplo, iload_0 significa o mesmo que iload com o operando 0. A letra x entre <> especifica o tipo do operando implcito: <n>, inteiro no negativo; <i>, inteiro; <l>, long; <f>, float; <d>, double.

4.2. Instrues Aritmticas/Lgicas


As instrues aritmticas computam um resultado que uma funo de dois valores na pilha de operando, empilhando o resultado de volta na pilha. Existem dois tipos: as que operam com valores inteiros e as que operam com valores de ponto-flutuante. Dentro de cada um dos tipos de instrues aritmticas, as instrues so especializadas para os tipos numricos da JVM. No h suporte direto para aritmtica com valores dos tipos byte, short, e char, bem como com valores do tipo boolean suportados pela linguagem de programao Java. As operaes com esses tipos so manipuladas por instrues que operam sobre o tipo int. Instrues com inteiros e pontos-flutuantes tambm diferem em seus comportamentos com relao a overflow e diviso por zero. As instrues aritmticas e lgicas JVM so as seguintes:

Arquitetura de Mquinas Virtuais

28

adio: iadd, ladd, fadd, dadd; subtrao: isub, lsub, fsub, dsub; multiplicao: imul, lmul, fmul, dmul; diviso: idiv, ldiv, fdiv, ddiv; resto: irem, lrem, frem, drem; negao: ineg, lneg, fneg, dneg; deslocamento: ishl, ishr, iushr, lshl, lshr, lushr; OR bit-a-bit: ior, lor; AND bit-a-bit: iand, land; XOR bit-a-bit: ixor, lxor; incremento de varivel local: iinc; comparao: dcmpg, dcmpl, fcmpg, fcmpl, lcmp.

4.3. Instrues de Converso de Tipos


Permitem converses entre tipos numricos JVM. Essas instrues podem ser utilizadas para implementar converses explcitas no cdigo do usurio ou para suavizar a falta de ortogonalidade no conjunto de instrues JVM. A mquina virtual suporta diretamente as seguintes converses de ampliao numrica, listadas juntamente com as instrues correspondentes: int para long, float, ou double: i2l, i2f, i2d; long para float ou double: l2f, l2d; float para double: f2d.

Converses de ampliao numrica no provocam perda de informao sobre a magnitude do valor numrico. Entretanto, dependendo dos tipos de origem e destino, pode ocorrer perda de preciso. Apesar desse fato, converses de ampliao numrica nunca fazem com que a JVM dispare excees. A JVM tambm suporta diretamente as seguintes converses de contrao numrica, listadas juntamente com as instrues correspondentes: int para byte, short, ou char: i2b, i2s, i2c; long para int: l2i; float para int ou long: f2i, f2l; double para int, long, ou float: d2i, d2l, d2f.

Converses de contrao numrica podem resultar em um valor de sinal diferente, ordem de magnitude diferente, ou ambos. Alm disso, pode haver perda de preciso. Apesar de poder ocorrer overflow, underflow e perda de preciso, converses de contrao numrica nunca provocam o disparo de excees por parte da JVM.

4.4. Instrues de Objetos


Apesar de instncias de classes e arrays serem objetos na linguagem Java, a JVM cria e manipula instncias de classes e arrays utilizando instrues diferentes:

Arquitetura de Mquinas Virtuais

29

criao de uma nova instncia de classe: new; criao de um novo array: newarray, anewarray, multianewarray; acesso a campos de classes (tambm chamados de campos estticos ou variveis de classes) e campos de instncias de classes (tambm chamados de campos no-estticos ou variveis de instncias): getfield, putfield, getstatic, putstatic; carga de um componente de array na pilha de operando: baload, caload, saload, iaload, laload, faload, daload, aaload; armazenamento de um valor da pilha de operando como um componente de array: bastore, castore, sastore, iastore, lastore, fastore, dastore, aastore; obteno do tamanho de um array: arraylength; verificao de propriedades de instncias de classes e arrays: instanceof, checkcast.

4.5. Instrues de Pilha


Diversas instrues so providas para a manipulao direta da pilha de operandos: pop, pop2, dup, dup2, dup_x1, dup2_x1, dup_x2, dup2_x2, swap.

4.6. Instrues de Desvio


Fazem com que a JVM condicionalmente ou incondicionalmente continue a execuo com uma instruo que no a seguinte instruo de desvio. So elas: desvio condicional: ifeq, iflt, ifle, ifne, ifgt, ifge, ifnull, ifnonnull, if_icmpeq, if_icmpne, if_icmplt, if_icmpgt, if_icmple, if_icmpge, if_acmpeq, if_acmpne; desvio condicional composto: tableswitch, lookupswitch; desvio incondicional: goto, goto_w, jsr, jsr_w, ret.

A mquina virtual possui instrues distintas que condicionalmente desviam em comparaes com dados de tipo int e reference. Ela tambm possui instrues de desvio condicional distintas que testam para a referncia nula, e, portanto no requerido especificar um valor concreto para null. Desvios condicionais com comparaes entre tipos boolean, byte, char, e short so realizadas utilizando instrues int. Desvios condicionais com comparaes entre tipos long, float, ou double utilizam primeiro uma instruo que compara os dados e produz um resultado inteiro da comparao. Uma instruo int subseqente testa o resultado e realiza o desvio. Devido nfase em comparao inteira, a JVM prov um rico complemento de instrues de desvio para o tipo int. Todas as instrues de desvio int realizam comparaes sinalizadas.

4.7. Instrues de Mtodos


As seguintes instrues invocam mtodos: invocao de mtodo de objeto: invokevirtual; invocao de mtodo de interface: invokeinterface; invocao de mtodo de objeto que requer tratamento especial (mtodos de inicializao de instncias, mtodos privados e mtodos de super-classes): invokespecial; invocao de mtodo esttico de classe: invokestatic.

Arquitetura de Mquinas Virtuais

30

As instrues de retorno de mtodo so distinguidas pelo tipo de dado de retorno: retorna valores de tipo boolean, byte, char, short, ou int: ireturn; retorna valores de tipo long: lreturn; retorna valores de tipo float: freturn; retorna valores de tipo double: dreturn; retorna valores de tipo reference: areturn.

4.8. Instrues de Excees


Uma exceo disparada programaticamente utilizando a instruo athrow. Alm disso, excees podem tambm ser disparadas por vrias instrues JVM se elas detectarem uma condio anormal. A implementao da clusula finally para tratamento de excees utiliza as instrues jsr, jsr_w, e ret.

4.9. Instrues de Sincronizao


A JVM suporta a sincronizao de mtodos e seqncias de instrues dentro de um mtodo utilizando um construtor nico de sincronizao, o monitor. A JVM prov as instrues monitorenter e monitorexit para suportar tais construtores. A sincronizao de nvel de mtodo manipulada como parte de invocao e retorno de mtodo. J a sincronizao a nvel de seqncias de instrues tipicamente empregada para codificar os blocos de sincronizao da linguagem Java. A implementao apropriada de blocos de sincronizao requer a cooperao de um compilador para a JVM. O compilador deve garantir que em qualquer concluso de invocao de mtodo uma instruo monitorexit ter sido executada para cada instruo monitorenter executada a partir da invocao do mtodo.

5. Conjunto de Instrues CLR


Segundo Meijer (2001) e Microsoft (2001), MSIL um conjunto de instrues baseado em pilha, assim como bytecodes Java. Ele foi projetado com o objetivo de ser facilmente gerado a partir de cdigo fonte por compiladores e outras ferramentas. Diversos tipos de instrues so providos, incluindo instrues para operaes aritmticas e lgicas, controle de fluxo, acesso direto memria, tratamento de exceo e invocao de mtodo. H tambm instrues para a implementao de construes do paradigma orientado a objetos, tais como, chamada de mtodo virtual, acesso a campo, acesso a array, e alocao e inicializao de objeto. O projeto da MSIL permite que programas no typesafe possam ser expressos, tendo em vista que isso essencial para suportar algumas linguagens de programao ainda comumente utilizadas. Ao mesmo tempo, seguindo um conjunto de regras simples, possvel gerar programas MSIL typesafe.

5.1. Tipos de Dados Suportados


Os seguintes tipos de dados podem ser manipulados utilizando o conjunto de instrues MSIL, e, portanto so diretamente suportados pela CLR:

Arquitetura de Mquinas Virtuais

31

Tipos I1 U1 I2 U2 I4 U4 I8 U8 R4 R8 I U R4Result R8Result RPrecise O &

Descrio Valor sinalizado em complemento a dois de 8 bits Valor binrio no-sinalizado de 8 bits Valor sinalizado em complemento a dois de 16 bits Valor binrio no-sinalizado de 16 bits Valor sinalizado em complemento a dois de 32 bits Valor binrio no-sinalizado de 32 bits Valor sinalizado em complemento a dois de 64 bits Valor binrio no-sinalizado de 64 bits Valor em ponto-flutuante IEEE 754 de 32 bits Valor em ponto-flutuante IEEE 754 de 64 bits Valor sinalizado em complemento a dois de tamanho natural Valor no-sinalizado de tamanho natural, tambm unmanaged pointer Tamanho natural para resultado de uma computao com ponto-flutuante IEEE 754 de 32 bits Tamanho natural para resultado de uma computao com ponto-flutuante IEEE 754 de 64 bits Valor em ponto-flutuante de preciso mxima Object reference de tamanho natural para memria gerenciada Managed pointer de tamanho natural (pode apontar para memria gerenciada)

Os tipos de tamanho natural (ou genricos) so um mecanismo na CLR para adiar a escolha de um tamanho de valor. Esses tipos de dados existem como tipos MSIL. Mas, quando so compilados para cdigo nativo, o compilador JIT mapeia cada um para o tamanho natural para o processador especfico. Por exemplo, o tipo de dados I mapeado para I4 em um processador Pentium, e I8 em um processador IA64. Portanto, a escolha de tamanho postergada at a compilao JIT, quando a CLR foi inicializada e a arquitetura alvo conhecida, o que implica que offsets de campo (field) e quadro de pilha (stack frame) tambm no so conhecidos em tempo de compilao. Para linguagens como Visual Basic, onde offsets de campos no so computados previamente, isso no um problema. Em linguagens como C ou C++, uma suposio conservadora de que eles ocupam 8 bytes algumas vezes aceitvel. Os tipos genricos da CLR foram projetados para evitar partes desse problema. O modelo CLR utiliza uma pilha de avaliao, e diponibiliza instrues load/store para copiar valores da memria na pilha e da pilha para a memria. O completo conjunto de tipos de dados da tabela acima pode ser representado na memria da CLR. Entretanto, a CLR suporta apenas um sub-conjunto desses tipos em suas operaes sobre valores na pilha de avaliao (I4, I8, I). Alm disso, a CLR suporta um tipo de dado interno (F) para representar valores em pontoflutuante na pilha. O tipo F pode ser imaginado como comeando no tamanho de valores carregados da memria e ento espandido quando combinado com valores de alta-preciso. Valores pequenos (I1, I2, U1, U2) so ampliados quando carregados da memria para a pilha e contrados quando armazenados da pilha na memria. A CLR reflete um modelo computacional que assume que clulas de memria possuem larguras de 1, 2, 4, ou 8 bytes, mas registradores e localizaes de pilha so de 4 ou 8 bytes. O suporte para valores pequenos na CLR :

Arquitetura de Mquinas Virtuais

32

instrues load/store para/da memria: ldelem, ldind, stind, stelem; instrues aritmticas com deteco de overflow: add.ovf, mul.ovf, sub.ovf; instrues de converso de dados: conv, conv.ovf; instrues para carga de constantes: ldc; instrues de criao de array: newarr.

Os tipos inteiros sinalizados (I1, I2, I4, I8, e I) e no-sinalizados (U1, U2, U4, U8, e U) diferem apenas na forma como os bits do inteiro so interpretados. Para operaes onde um inteiro no sinalizado tratado diferentemente de um sinalizado, como, por exemplo, comparaes e aritmticas com overflow, existem instrues separadas para tratar um inteiro como no sinalizado, por exemplo, cgt.un e add.ovf.u. Essa arquitetura de conjunto de instrues simplifica compiladores JIT de MSIL ao possibilitar que eles tratem um nmero menor de tipos de dados internamente. Instrues MSIL no especificam os tipos de seus operandos. Ao invs disso, a CLR mantm tracks de tipos de operandos e o compilador JIT gera o cdigo nativo apropriado, conforme indicado abaixo. Por exemplo, uma instruo add ir adicionar ints ou floats da pilha.

5.2. Tipos Numricos


A maior parte das instrues MSIL que manipulam nmeros obtm seus operandos da pilha de avaliao, e essas entradas tm um tipo associado que conhecido pelo compilador JIT. Como resultado, diferentemente das instrues JVM, uma nica operao, tal como adio, pode ter entradas de qualquer tipo de dado numrico, apesar de nem todas as instrues poderem manipular todas as combinaes de tipos de operandos. As categories de instrues so listadas a seguir: Numeric: instrues que manipulam nmeros inteiros e em ponto-flutuante, e consideram inteiros como sinalizados. Aritmtica, desvio condicional, e instrues de comparao fazem parte dessa categoria; Integer: instrues que manipulam somente nmeros inteiros. Operaes de bit e diviso/resto de inteiros no sinalizados fazem parte dessa categoria; Floating point: instrues que manipulam somente nmeros em ponto-flutuante; Specific: instrues que manipulam nmeros inteiros e/ou em ponto-flutuante, mas possuem variantes que manipulam particularmente inteiros no sinalizados e de tamanhos diferentes. Operaes inteiras com deteco de overflow, instrues de converso de dados, e operaes que transferem dados entre a pilha de avaliao e outras partes de memria esto nessa categoria; Unsigned/unordered: h instrues de desvio e comparao especiais que tratam inteiros como no sinalizados, e consideram nmeros em ponto-flutuante no ordenados especialmente; Load constant: as instrues load constant podem ser utilizadas para carregar constantes inteiras ou reais.

5.3. Tipos Ponteiros


A CLR tem a habilidade de seguir ponteiros para objetos e coletar objetos que no so mais alcanveis (gerenciamento de memria por garbage collection). Para que isso funcione corretamente, ponteiros para objetos devem ser utilizados. Os tipos de dados O (object reference) e & (managed pointer) provem esse suporte.

Arquitetura de Mquinas Virtuais

33

A utilizao de referncias a objetos fortemente restringida na MSIL. Elas so utilizadas quase que exclusivamente com as instrues de sistema de objeto virtual virtual object system, que so instrues especialmente projetadas para manipular objetos. Entretanto, algumas poucas instrues bsicas da MSIL podem manipular referncias a objetos. Em particular, referncias a objetos podem ser: carregadas da pilha de avaliao para serem passadas como argumentos para mtodos: ldloc, ldarg; armazenadas, a partir da pilha, em suas home locations: stloc, starg; duplicadas ou desempilhadas da pilha de avaliao: dup, pop; comparadas entre si: beq, beq.s, bne, bne.s, ceq; carregadas de / armazenadas em memria no gerenciada, apenas em cdigo de tipo no gerenciado: ldind.ref, stind.ref; criao de uma referncia nula: ldnull; retornada como valor: ret. Ponteiros gerenciados possuem diversas operaes bsicas adiconais: adio e subtrao de inteiros, em unidades de bytes, retornando um ponteiro gerenciado: add, add.ovf.u, sub, sub.ovf.u; subtrao de dois ponteiros gerenciados para elementos do mesmo array, retornando o nmero de bytes entre eles: sub, sub.ovf.u; comparao no sinalizada e salto condiconal baseado em dois ponteiros gerenciados: bge.un, bge.un.s, bgt.un, bgt.un.s, ble.un, ble.un.s, blt.un, blt.un.s, cgt.un, clt.un.

5.4. Dados Agregados


A CLR suporta dados agregados, isto , itens de dados que possuem sub-componentes (arrays, estruturas, objetos), mas que so passados por valor; os sub-componentes podem incluir referncias para memria gerenciada. Dados agregados so representados utilizando um tipo de valor, que pode ser instanciado de duas maneiras: boxed: como um objeto, carregando informao de tipo completa em tempo de execuo, e tipicamente sendo alocado na heap pelo gerenciador de memria; unboxed: como uma instncia de tipo de valor, que no carrega informao de tipo em tempo de execuo, e que nunca alocada diretamente na heap, podendo ser armazenada nas variveis locais ou no array de argumentos de entrada.

5.4.1. Homes para Valores A casa (home) de um valor onde o valor armazenado para possvel reuso. A CLR suporta diretamente as seguintes home locations: um argumento de entrada, uma varivel local de um mtodo, um campo de instncia de um objeto ou tipo de valor, um campo esttico de uma classe, interface ou mdulo, e um elemento de array. Para cada home location existe meio para computer em tempo de execuo o endereo da home location, e meio para determinar em tempo de compilao JIT o tipo de uma home location, conforme mostrado na tabela a seguir:

Arquitetura de Mquinas Virtuais

34

Home location Argumento Varivel Local Campo Esttico Elemento de Array

Computao de endereo ldarga para argumentos por valor. ldarg para argumentos por referncia. ldloca para locais por valor. ldloc para locais por referncia. ldflda ldslfda ldelema

Determinao de tipo Assinatura do mtodo. Assinaturas locais no cabealho do mtodo. Tipo do campo na classe, interface ou mdulo. Tipo do campo na classe, interface ou mdulo. Tipo de elemento do array.

Alm das homes, valores built-in podem existir em duas maneiras adicionais, isto , sem homes: como valores constantes: embarcados no stream de instrues MSIL utilizando instrues ldc.*; como um valor intermedirio na pilha de avaliao, quando retornado por um mtodo ou instruo MSIL.

5.4.2. Operaes em Instncias de Tipo de Valor Instncias de tipo de valor podem ser criadas, passadas como argumentos, retornadas como valores, e armazenadas ou carregadas de variveis locais, campos, e elementos de array. Assim como classes, tipos de valor podem ter membros (mtodos e campos) estticos e noestticos. Mas, como eles no carregam nenhuma informao de tipo em tempo de execuo, eles no podem ser substitutos para itens de tipo Object, de forma que, eles de fato atuam como tipos primitivos. Existem trs opes para inicializar a home location de uma instncia: zerar a home location, carregando seu endereo e utilizando a instruo initobj; chamar um construtor definido pelo usurio, carregando o endereo da home location e ento chamando o construtor diretamente; copiar uma instncia existente na home location. Existem duas opes para carregar uma instncia na pilha de avaliao: carregar o valor da home que possui o tipo apropriado diretamente, utilizando instrues ldarg, ldloc, ldfld, ou ldsfld; computar o endereo do tipo, e ento utilizar a instruo ldobj. Existem duas opes para armazenar uma instncia da pilha de avaliao: armazenar o valor na home do tipo apropriado diretamente, utilizando instrues starg, stloc, stfld, ou stsfld; computar o endereo do tipo, e ento utilizar a instruo stobj.

Arquitetura de Mquinas Virtuais

35

Instrues para passar e retornar tipos de valores: para passar um tipo de valor por valor, carrega-o na pilha como qualquer outro argumento, utilizando instrues ldloc, ldarg, etc., ou chama um mtodo que retorna um tipo de valor. Para acessar um parmetro de tipo de valor que foi passado por valor utiliza-se a instruo ldarga para computar seu endereo ou ldarg para carregar o valor na pilha de avaliao; para passar um tipo de valor por referncia, carrega seu endereo normalmente. Para acessar um parmetro de tipo de valor que foi passado por referncia utiliza-se a instruo ldarg para computar seu endereo do argumento, e ento a instruo ldobj para carreg-lo na pilha de avaliao; para retornar um tipo de valor, carrega o valor na pilha de avaliao e ento emite uma instruo ret.

5.5. Controle de Fluxo


A arquitetura do conjunto de instrues MSIL prov um rico conjunto de instrues para alterar o fluxo de controle normal de uma instruo MSIL para a prxima: instrues de desvio condicional e incondicional para utilizao dentro de mtodos (cuidando para que a transferncia no cruze a fronteira de uma regio protegida); instrues de chamada de mtodo para computar novos argumentos; prefixo tail call para indicar que um mtodo deveria abdicar de seu quadro de pilha antes de executar uma chamada de mtodo; instrues para retornar de um mtodo, despachando um valor se necessrio; instrues de salto de mtodo para transferir os argumentos do mtodo corrente para um mtodo destinatrio conhecido ou computado; instrues relacionadas a exceo, que incluem instrues para iniciar uma exceo, transferir controle para fora de uma regio protegida, e concluir um filtro (filter), clusula catch ou clusula finally.

Enquanto a CLR suporta transferncias arbitrrias de controle dentro de um mtodo, h diversas restries que devem ser observadas, e que so testadas pelo verificador: no permitido entrar em clusulas catch e finally, exceto atravs do mecanismo de tratamento de exceo; sair de uma regio protegida permitido somente atravs de instrues de tratamento de exceo (leave, end.filter, end.catch, ou end.finally); a pilha de avaliao deve estar vazia aps o valor de retorno ser desempilhado por uma instruo ret; todos os slots na pilha devem ter o mesmo tipo de dados em todos os pontos dentro do corpo de um mtodo; para que compiladores JIT possam eficientemente rastrear os tipos de dados armazenados na pilha, a pilha deve estar vazia na instruo seguinte a uma instruo de transferncia de controle incondicional (br, br.s, ret, jmp, jmpi, throw, end.filter, end.catch, ou end.finally). A pilha poder no estar vazia nesse ponto somente se em algum local anterior dentro do mtodo existir alguma instruo de desvio para a localizao dessa instruo; todos os caminhos de um mtodo devem terminar com um das seguintes instrues: ret, throw, jmp, jmpi, ou (tail. seguida por call, calli, ou callvirt).

Arquitetura de Mquinas Virtuais

36

5.6. Invocao de Mtodos


Todas as invocaes de mtodos inicializam as reas de estado de mtodo da seguinte forma: o array de argumentos de entrada preenchido pelo invocador com os valores desejados; o array de variveis locais sempre possui null para tipos Object e para campos de tipos de valores que contm objetos. Alm disso, se o flag de inicializao zerada estiver selecionado no cabealho de mtodo, ento ele inicializado com 0 para todos os tipos inteiros e 0.0 para todos os tipos pontos-flutuantes; se o flag de inicializao zerada estiver selecionado no cabealho de mtodo, ento o local memory pool inicializado com zeros; a pilha de avaliao est vazia.

6. Formato do Arquivo de Classe Java


Segundo Lindholm (1996) e Venners (1996, 2000), o formato de arquivo de classe da JVM consiste de um stream de bytes. Os tipos de dados u1, u2 e u4, representando quantidades no sinalizadas de um, dois e quatro bytes, representam os dados do arquivo de classe. Itens de dados maiores que um byte so armazenados no arquivo, na ordem big-endian, na qual os bytes mais significativos so localizados antes dos menos significativos.

6.1. Estrutura do Arquivo de Classe


A estrutura de um arquivo de classe (.class) a seguinte: ClassFile{ u4 magic; u2 minor_version; u2 major_version; u2 constant_pool_count; cp_info constant_pool[constant_pool_count-1]; u2 access_flags; u2 this_class; u2 super_class; u2 interfaces_count; u2 interfaces[interfaces_count]; u2 fields_count; field_info fields[fields_count]; u2 methods_count; method_info methods[methods_count]; u2 atributes_count; attribute_info attributes[attributes_count]; } Os itens na estrutura do arquivo so os seguintes: magic: o item magic fornece o nmero identificador do arquivo;

Arquitetura de Mquinas Virtuais

37

minor_version, major_version: os itens minor_version e major_version armazenam, respectivamente, a menor e a maior verso do arquivo. Juntamente, os dois definem a verso do arquivo. Se o major_version for representado pelo nmero M e o minor_version representado pelo nmero m, ento a verso do arquivo M.m. Uma implementao JVM pode executar um arquivo se, e somente se, sua verso est no intervalo de verso que a mquina suporta, ou seja, Mi.0 <= verso <= Mj.m; constant_pool_count: O valor do item constant_pool_count igual ao nmero de entradas na tabela constant_pool + 1. Um ndice para a tabela constant_pool s vlido se ele for maior que zero e menor que constant_pool_count; constant_pool[]: o item constant_pool[] uma tabela onde cada entrada representa constantes string, nomes de classes e interfaces, nomes de campos e outras constantes referenciadas no arquivo. O formato de cada entrada na tabela constant_pool indicado pelo seu primeiro byte, chamado tag; access_flags: o valor do item access_flags utilizado para denotar permisses de acesso para classes ou interfaces e suas propriedades. A interpretao de cada flag, caso tenha sido definido, demonstrada a seguir: Nome do flag ACC_PUBLIC ACC_FINAL ACC_SUPER ACC_ABSTRACT Valor 0x0001 0x0010 0x0020 0x4000 Interpretao Declarada como pblica; externamente ao seu pacote. pode ser acessada

Declarada como final; no so permitidas sub-classes. Para tratamento de mtodos de super-classes. Indica uma interface. Declarada como abstrata; no pode ser instanciada.

ACC_INTERFACE 0x0200

this_class: o valor do item this_class precisa ser um ndice vlido para a tabela constant_pool. A entrada na tabela constant_pool precisa ser uma estrutura CONSTANT_Class_info, representando a classe ou interface definida pelo arquivo; super_class: para uma classe, o valor do item super_class precisa ser zero ou um ndice vlido para a tabela constant_pool. Se o valor no for zero, a entrada na tabela constant_pool precisa ser uma estrutura CONSTANT_Class_info. Caso seja zero, ento o arquivo precisa representar a classe Object (classe sem super-classe direta). Para uma interface, o valor do item super_class precisa sempre ser um ndice para a tabela constant_pool. A entrada na tabela apontada por esse ndice precisa ser uma estrutura CONSTANT_Class_info representando a classe Object; interfaces_count: o valor desse item fornece o nmero de super-interfaces diretas da classe ou interface; interfaces[]: cada valor da tabela interfaces precisa ser um ndice para a tabela constant_pool. As entradas da tabela constant_pool apontadas por cada item da tabela interfaces precisam ser uma estrutura CONSTANT_Class_info representando uma interface que a super-interface direta da classe ou interface do arquivo; fields_count: armazena o nmero de estruturas field_info armazenadas na tabela fields. A estrutura field_info representa todos os campos, tanto para variveis de classe quanto para variveis de instncia, declaradas pela classe ou interface; fields[]: cada entrada na tabela fields precisa ser uma estrutura field_info fornecendo a descrio completa de um campo da classe ou interface. No so inclusos itens representando campos que so inerentes a super-classes ou super-interfaces;

Arquitetura de Mquinas Virtuais

38

methods_count: armazena o nmero de estruturas method_info inseridas na tabela methods; methods[]: cada entrada na tabela methods precisa ser do tipo method_info fornecendo uma descrio completa de um mtodo da classe ou interface. A estrutura method_info representa todos os mtodos declarados na classe ou interface. A tabela methods no inclui itens representando mtodos que so inerentes a super-classes ou super-interfaces; atributes_count: armazena o nmero de entradas na tabela atributes da classe; atributes[]: cada entrada na tabela atributes deve ser uma estrutura atribute_info.

6.2. Constant Pool


Instrues JVM no se baseiam no layout de tempo de execuo de classes, interfaces, instncias de classe, ou arrays; durante a execuo de um programa, as instrues referem-se a informaes simblicas que so armazenadas na tabela constant_pool. Todas as entradas na tabela constant_pool possuem o seguinte formato geral: cp_info{ u1 tag; u1 info[]; } Cada entrada precisa comear com um byte (tag) indicando o tipo do cp_info empregado. O contedo da tabela info varia de acordo com o valor do tag. Os tags vlidos e seus possveis valores so: Valor Tipo de constante 7 9 10 11 8 3 4 5 6 12 1 CONSTANT_Class CONSTANT_Fieldref CONSTANT_Methodref CONSTANT_InterfaceMethodref CONSTANT_String CONSTANT_Integer CONSTANT_Float CONSTANT_Long CONSTANT_Double CONSTANT_NameAndType CONSTANT_Utf8

6.2.1. Estrutura de Classes e Interfaces A estrutura CONSTANT_Class_info utilizada para representar uma classe ou uma interface: CONSTANT_Class_info{ u1 tag; u2 name_index;

Arquitetura de Mquinas Virtuais

39

} Sendo os itens: tag: contm o valor CONSTANT_Class (7); name_index: ndice vlido para a tabela constant_pool. A entrada da tabela apontada por name_index precisa ser uma estrutura CONSTANT_Utf8_info representando o nome de uma classe ou interface.

6.2.2. Estruturas de Campos e Mtodos Campos e mtodos so representados por estruturas similares: CONSTANT_Fieldref_info { u1 tag; u2 class_index; u2 name_and_type_index; } CONSTANT_Methodref_info { u1 tag; u2 class_index; u2 name_and_type_index; } CONSTANT_InterfaceMethodref_info { u1 tag; u2 class_index; u2 name_and_type_index; } Os itens dessa estrutura so: tag: para estruturas CONSTANT_Fieldref_info possui o valor CONSTANT_Fieldref (9), para estruturas CONSTANT_Methodref_info possui o valor CONSTANT_Methodref (10), e para estruturas CONSTANT_InterfaceMethodref_info possui o valor CONSTANT_InterfaceMethodref (11); class_index: seu valor deve ser um ndice vlido para a tabela constant_pool. A entrada apontada por ele deve conter uma estrutura do tipo CONSTANT_Class_info representando a classe ou interface que contm a declarao do campo ou mtodo. O valor de class_index de uma estrutura CONSTANT_Methodref_info precisar ser um tipo classe, no um tipo interface, para uma estrutura CONSTANT_InterfaceMethodref_info precisa ser um tipo interface, e para uma estrutura CONSTANT_Fieldref_info pode ser tanto classe quanto interface; name_and_type_index: seu valor deve ser um ndice vlido para a tabela constant_pool. A entrada apontada por ele deve ser uma estrutura CONSTANT_NameAndType_info. A entrada na tabela constant_pool indica o nome e o descritor do campo ou mtodo. Em uma CONSTANT_Fieldref_info o descritor indicado precisa ser um descritor de campo. Caso contrrio, precisa ser um descritor de mtodo.

Arquitetura de Mquinas Virtuais

40

6.2.3. Estrutura de Strings usada para representar objetos do tipo String: CONSTANT_String_info{ u1 tag; u2 string_index; } Os itens dessa estrutura so: tag: possui o valor CONSTANT_String (8); string_index: precisa ser um ndice vlido da tabela constant_pool. A entrada apontada dessa tabela precisa ser uma estrutura CONSTANT_Utf8 representando a seqncia de caracteres com a qual a string de caracteres ser iniciada.

6.2.4. Estruturas de Inteiros e Pontos-Flutuantes Essas estruturas representam constantes numricas de 4 bytes (32 bits), float e int: CONSTANT_Integer_info{ u1 tag; u4 bytes; } CONSTANT_Float_info{ u1 tag; u4 bytes; } Os itens dessas estruturas so: tag: para CONSTANT_Integer_info seu valor CONSTANT_Integer (3). Para CONSTANT_Float_info seu valor CONSTANT_Float (4); bytes: contm o valor das constantes dos tipos int e float para CONSTANT_Integer_info e CONSTANT_Float_info, respectivamente.

6.2.5. Estruturas de Long e Double Essas estruturas representam constantes numricas de 8 bytes (64 bits), long e double: CONSTANT_Long_info{ u1 tag; u4 high_bytes; u4 low_bytes; } CONSTANT_Double_info{

Arquitetura de Mquinas Virtuais

41

u1 tag; u4 high_bytes; u4 low_bytes; } Os itens dessa estrutura so: tag: para estrutura do tipo CONSTANT_Long_info possui o valor CONSTANT_Long (5). Para o tipo CONSTANT_Double_info possui o valor CONSTANT_Double (6); high_bytes, low_bytes: na estrutura CONSTANT_Long_info armazenam o valor de uma constante do tipo long. Para se formar o valor representado necessrio adicionar o valor de low_bytes ao deslocamento de 32 bits de high_bytes. Para estrutura do tipo CONSTANT_Double_info armazenam uma constante do tipo double no formato IEEE 754.

6.2.6. Estrutura de Campos e Mtodos Independentes Essa estrutura representa um campo ou mtodo sem indicar a qual classe ou interface ele pertence: CONSTANT_NameAndType_info{ u1 tag; u2 name_index; u2 description_index; } Seus itens so os seguintes: tag: possui o valor CONSTANT_NameAndType (12); name_index: seu valor deve ser um ndice vlido para a tabela constant_pool. A entrada dessa tabela, para onde aponta esse ndice, deve ser uma estrutura do tipo CONSTANT_Utf_8_info representando um nome vlido de campo ou mtodo; descriptor_index: seu valor deve ser um ndice vlido para a tabela constant_pool. A entrada apontada deve ser uma estrutura do tipo CONSTANT_Utf_8_info representando um descritor para um campo ou mtodo.

6.2.7. Estrutura Utf8 Utilizadas para representar constantes do tipo String. Strings na estrutura Utf8 so seqncias de caracteres ASCII no nulos que podem ser representados utilizando um byte por caractere. No entanto, caracteres com mais de 16 bits tambm podem ser representados. Caracteres no intervalo de '\u0001' at '\u007F' so representados por um nico byte: 0 bits 6-0 Caracteres no intervalo de '\u0080' at '\u07FF' so representados por um par de bytes x e y: 1 1 0 bits 10-6

Arquitetura de Mquinas Virtuais

42

1 0 bits 5-0 Caracteres no intervalo de '\u0800' at '\uFFFF' so representados por trs bytes x, y, e z: 1 1 1 0 bits 15-12 1 1 0 bits 11-6 0 bits 5-0

A estrutura CONSTANT_Utf8_info : CONSTANT_Utf8_info{ u1 tag; u2 length; u1 bytes[length]; } Seus itens so: tag: contm o valor CONSTANT_Utf8 (1); length: armazena o nmero de bytes no array (no o nmero de caracteres resultantes, visto que um caractere pode ocupar at trs posies do array); bytes[]: array que contm os bytes de uma string.

6.3. Estrutura de Campos


Cada campo descrito por uma estrutura do tipo fied_info. O formato dessa estrutura : fiend_info{ u2 access flags; u2 name_index; u2 descriptor_index; u2 atributes_count; attribute_info attributes[attributes_count]; } Os itens dessa estrutura so: access_flags: seu valor utilizado para definir as permisses de acesso ao campo e s suas propriedades. Os possveis valores so: Nome ACC_PUBLIC ACC_PRIVATE Valor 0x0001 0x0002 Interpretao Declarado como public Declarado como private

Arquitetura de Mquinas Virtuais

43

Nome ACC_PROTECTED ACC_STATIC ACC_FINAL ACC_VOLATILE ACC_TRANSIENT

Valor 0x0004 0x0008 0x0010 0x0040 0x0080

Interpretao Declarado como protected Declarado como static Declarado como final Declarado como volatile Declarado como transient

name_index: precisa ser um ndice vlido para a tabela constant_pool. A entrada da tabela deve ser uma estrutura CONSTANT_Utf8_info que descreva o nome para o campo; descriptor_index: precisa ser um ndice vlido para a tabela constant_pool. A entrada da tabela deve ser uma estrutura CONSTANT_Utf8_info que contenha um descritor para o campo; attributes_count: contm o nmero de atributos do campo; attributes[]: cada item dessa tabela precisa ser uma estrutura attribute. Um campo pode ter qualquer nmero de atributos associados a ele.

6.4. Estrutura de Mtodos


Cada mtodo, incluindo cada mtodo de inicializao de instncia e de iniciao de classe ou interface descrito por uma estrutura method_info. Essa estrutura tem o seguinte formato: method_info{ u2 access_flags; u2 name_index; u2 descriptor_index; u2 atributes_count; atribute_info attributes[atributes_count]; } Os itens so: access_flags: define a permisso de acesso ao mtodo e s suas propriedades. Os valores possveis so os seguintes: Nome ACC_PUBLIC ACC_PRIVATE ACC_PROTECTED ACC_STATIC ACC_FINAL ACC_SYNCHRONIZED ACC_NATIVE ACC_ABSTRACT Valor 0x0001 0x0002 0x0004 0x0008 0x0010 0x0020 0x0100 0x0400 Interpretao Declarado como public Declarado como private Declarado como protected Declarado como static Declarado como final Declarado como synchronized Declarado como native Declarado como abstract

Arquitetura de Mquinas Virtuais

44

Nome ACC_STRICT

Valor 0x0800

Interpretao Declarado como strictfp

name_index: precisa ser um ndice vlido para a tabela constant_pool. A entrada da tabela deve conter uma estrutura do tipo CONSTANT_Utf8 representando um dos nomes especiais para mtodos (<init> ou <clinit>) ou um nome vlido de mtodo da linguagem Java; descriptor_index: precisa ser um ndice vlido para a tabela constant_pool. A entrada da tabela deve conter uma estrutura do tipo CONSTANT_Utf8 representando um descritor de mtodo vlido; attributes_count: informa o nmero de atributos do mtodo; attributes[]: cada valor dessa tabela necessariamente deve ser da estrutura attribute. Um mtodo pode ter qualquer nmero de atributos associados a ele.

6.5. Estrutura de Atributos


Atributos so utilizados nas estruturas ClassFile, field_info, method_info e Code_attribute. Todos os atributos tm o seguinte formato: attribute_info{ u2 attribute_name_index; u4 attribute_length; u1 info[attribute_length]; } Seus itens so: attribute_name_index: ndice vlido para a tabela constant_pool. A entrada da tabela deve ser uma estrutura CONSTANT_Utf8 contendo o nome do atributo; attribute_length: contm o nmero de bytes na tabela info; info[]: informaes sobre a natureza do atributo.

6.5.1. Atributo Code O atributo code um atributo de tamanho variado usado na tabela attributes da estrutura method_info. Um atributo code contm instrues JVM e informaes auxiliares para mtodos regulares e de inicializao de instncia, classe ou interface. O atributo code possui o seguinte formato: code_attribute{ u2 attribute_name_index; u4 attribute_length; u2 max_stack; u2 max_locals; u4 code_length; u1 code[code_length]; u2 exception_table_length; { u2 start_pc; u2 end_pc;

Arquitetura de Mquinas Virtuais

45

u2 handler_pc; u2 catch_type; } exception_table[exception_table_length]; u2 attributes_count; attribute_info attributes[attributes_count]; } Os itens da estrutura code_attribute so: attribute_name_index: precisa ser um ndice vlido para a tabela constant_pool. A entrada dessa tabela para onde esse ndice aponta deve ser uma estrutura CONSTANT_Utf8 que contenha a string Code; attribute_length: indica o tamanho do atributo em bytes; max_stack: indica o tamanho mximo que a pilha de operandos pode alcanar durante a execuo do mtodo; max_locals: indica o nmero de elementos que foram inseridos no array de variveis locais, inclusive os elementos referentes ao recebimento de parmetros; code_length: indica o nmero de bytes existentes no tabela code; code[]: contm os bytecodes que implementam o mtodo; exception_table_length: informa o nmero de entradas na tabela exception_table; exception_table: cada entrada nessa tabela representa um tratamento de exceo no cdigo contido na tabela code e deve possuir os seguintes quatro itens: o start_pc, end_pc: os valores contidos nesses dois itens descrevem o intervalo, na tabela code, onde o manipulador de excees (exception handler) ativo; o handler_pc: indica um ponto, dentro da tabela code, onde o tratamento de uma exceo deve ser iniciado; o catch_type: ndice para a tabela constant_pool, de forma que a entrada da tabela deve ser uma estrutura CONSTANT_Class_info, representando uma classe de excees que o exception handler foi projetado para capturar. attributes_count: define o nmero de atributos do atributo code; attributes[]: cada entrada na tabela attributes precisa possuir a estrutura attribute. O atributo code pode possuir vrios atributos opcionais associados a ele.

6.5.2. Atributo SourceFile O atributo SourceFile um atributo opcional na tabela attributes da estrutura ClassFile. A estrutura desse atributo : SourceFile_attribute{ u2 attribute_name_index; u4 attribute_length; u2 sourcefile_index; } Os itens dessa estrutura so: atribute_name_index: deve ser um ndice vlido para a tabela constant_pool, onde a entrada apontada por esse ndice deve ter a estrutura CONSTANT_Utf8 contendo a string SourceFile;

Arquitetura de Mquinas Virtuais

46

attribute_length: o valor desse campo para esse atributo deve ser 2; source_file_index: deve ser um ndice vlido para a tabela constant_pool, onde a entrada apontada por esse ndice deve ter a estrutura CONSTANT_Utf8 contendo uma string que represente o arquivo no qual a classe foi compilada.

6.6. Restries no Cdigo JVM


O cdigo de mquina virtual Java para mtodos regulares, de inicializao de instncias, ou de inicializao de classes ou interfaces armazenado no array do atributo Code da estrutura method_info de um arquivo de classe. A seguir sero descritas algumas restries associadas s instrues JVM, que devem ser verificadas para correta operao da mquina virtual. A anlise dessas restries possibilita um melhor entendimento do conjunto de instrues, bem como da arquitetura em geral da mquina virtual. 6.6.1. Restries Estticas Algumas das restries estticas para as instrues so as seguintes: O valor de code_length precisa ser menor que 65536; O opcode da primeira instruo no array code comea no ndice 0; Para cada instruo no array code (exceto para a ltima), o ndice do opcode da prxima instruo deve ser o ndice do opcode da instruo atual adicionado ao tamanho da instruo; O ltimo byte da ltima instruo precisa ser o byte localizado no ndice code_length 1. Algumas das restries estticas para os operandos das instrues so as seguintes: O endereo alvo de uma instruo de salto (jsr, jsr_w, goto, goto_w, ifeq, ifne, ifle, iflt, ifge, ifgt, ifnull, ifnonnull, if_icmpeq, if_icmpne, if_icmple, if_icmplt, if_icmpge, if_icmpgt, if_acmpeq, if_acmpne) precisa ser um opcode de uma instruo que esteja no mtodo; Cada alvo, incluindo o padro, de cada instruo tableswitch precisa ser o opcode de uma instruo que esteja no mtodo. Cada instruo tableswitch precisa ter um nmero de entradas em sua tabela jump que seja consistente com os valores dos operandos low e high da tabela jump; Cada alvo, incluindo o padro, de cada instruo lookupswitch precisa ser o opcode de uma instruo que esteja dentro do mtodo. Cada instruo lookupswitch precisa ter um nmero match-offset que seja consistente com o valor do operando npair; O operando da instruo ldc, assim como os operandos da instruo ldc_w precisam representar um ndice vlido para a tabela constant_pool. Em ambos os casos a entrada da constant_pool precisa ser do tipo CONSTANT_Integer, CONSTANT_Float ou CONSTANT_String; O operando de cada instruo ldc2_w precisa representar um ndice vlido da tabela constant_pool. A entrada da tabela constant_pool referenciada por esse ndice precisa ser do tipo CONSTANT_Long ou CONSTANT_Double; Os operandos de cada instruo getfield, putfield, getstatic e putstatic precisam representar um ndice vlido da tabela constant_pool. A entrada dessa tabela referenciada pelo ndice precisa ser do tipo CONSTANT_Fieldref; Os operandos de cada instruo invokevirtual, invokespecial e invokestatic precisam representar um ndice vlido da tabela constant_pool. A entrada referenciada por esse ndice precisa ser do tipo CONSTANT_Methodref;

Arquitetura de Mquinas Virtuais

47

Somente a instruo invokespecial permitida para invocar um mtodo de inicializao de instncia. Nenhum outro mtodo cujo nome comece com o caractere < pode ser invocado por instrues de invocao de mtodos. Particularmente, o mtodo de inicializao de classe ou interface especialmente chamada de <clinit> nunca explicitamente invocado por uma instruo JVM, mas implicitamente pela prpria mquina virtual; Os operandos indexbyte de cada instruo invokeinterface precisam representar um ndice vlido da tabela constant_pool. A entrada referenciada por esse ndice precisa ser do tipo CONSTANT_InterfaceMethodref. O valor do operando count de cada instruo invokeinterface precisa refletir o nmero de variveis locais necessrias para serem passadas para o mtodo interface; Os operandos de cada uma das instrues instanceof, checkcast, new e anewarray e os operandos indexbyte de cada instruo multianewarray precisam representar um ndice vlido da tabela constant_pool. A entrada apontada por esse ndice precisa ser do tipo CONSTANT_Class; Nenhuma anewarray pode ser utilizada para criar um array maior que 255 dimenses; Nenhuma instruo new pode referenciar uma entrada na tabela constant_pool que seja do tipo CONSTANT_Class representando uma classe array. A instruo new no pode ser utilizada para criar um array, uma instncia de uma interface ou uma instncia de uma classe abstrata; A instruo multiarray precisa ser utilizada para criar um array de um tipo que tenha menos dimenses que o valor do operando dimensions; O operando atype de cada instruo newarray precisa ter um dos seguintes valores T_BOOLEAN (4), T_CHAR (5), T_FLOAT (6), T_DOUBLE (7), T_BYTE (8), T_SHORT (9), T_INT (10) ou T_LONG (11); O operando index de cada instruo iload, fload, aload, istore, fstore, astore, iinc e ret precisam ser um valor inteiro no negativo menor ou igual a max_locals-1; O ndice implcito de cada uma das instrues iload_<n>, fload_<n>, aload_<n>, istore_<n>, fstore_<n> e astore_<n> precisa ser menor ou igual a max_locals-1; O operando index de cada uma das instrues lload, dload, lstore e dstore precisam ser menor ou igual a max_locals-2; O ndice implcito de cada uma das instrues lload_<n>, dload_<n>, lstore_<n> e dstore_<n> precisa ser menor ou igual que o valor max_locals-2; Os operandos indexbyte de cada instruo wide modificando uma instruo iload, fload, aload, istore, fstore, astore, ret ou iinc precisam representar inteiros no negativos menores ou iguais que max_locals-1. O operando indexbyte de cada instruo wide modificando uma instruo lload, dload, lstore ou dstore precisa representar um valor inteiro no negativo menor ou igual a max_locals-2.

6.6.2. Restries Estruturais As restries estruturais especificam restries nos relacionamentos entre as instrues JVM. Algumas das restries estruturais so as seguintes: Cada instruo s pode ser executada com argumentos na pilha de operandos que sejam dos tipos e quantidades apropriados para a instruo. Uma instruo que opera com tipo int tambm permitida a operar com os tipos boolean, byte, char e short (pois, a mquina virtual converte esses tipos para int); Em nenhum ponto da execuo a ordem dos pares que armazenam uma varivel local do tipo long ou double pode ser invertida. Em nenhum ponto, uma varivel desse par pode ser operada

Arquitetura de Mquinas Virtuais

48

individualmente; Nenhuma varivel local pode ser acessada antes de ter seu valor atribudo; Em nenhum ponto da execuo o tamanho da pilha de operandos pode crescer para um tamanho maior que o definido em max_stack; Em nenhum ponto da execuo podem ser retirados mais itens de uma pilha do que a quantidade que ela contm; Quando qualquer mtodo de instncia invocado ou quando qualquer varivel de instncia acessada, a classe que contm o mtodo de instncia ou varivel de instncia precisa j ter sido inicializada; Cada mtodo de inicializao de instncia precisa chamar outro mtodo de inicializao de instncia da referncia this ou o mtodo de inicializao de instncia de sua superclasse direta super antes que seus membros de instncia sejam acessados. Entretanto, campos de instncia da referncia this que so declarados na classe corrente podem ser atribudos antes da chamada de qualquer mtodo de inicializao de instncia; Cada instruo de return precisa ser compatvel com o tipo de retorno do mtodo. Se o mtodo retorna um valor do tipo boolean, byte, char, short ou int, ento somente a instruo ireturn pode ser utilizada. Se o mtodo retorna um tipo float, long ou double, somente as instrues freturn, lreturn ou dreturn podem ser utilizadas, respectivamente. Se o mtodo retorna um tipo de referncia ser necessrio utilizar a instruo areturn; Nenhum endereo de retorno (um valor do tipo returnAddress) pode ser carregado a partir de uma varivel local; Uma instruo que segue cada instruo jsr ou jsr_w s pode retornar atravs de instruo ret.

6.7. Verificao de Arquivo de Classe


Quando um compilador gera um cdigo ele efetua o tratamento das condies listadas anteriormente. No entanto, quando uma mquina virtual carrega um arquivo .class ela no sabe se esse foi gerado por um compilador confivel ou por um adversrio que est tentando causar uma pane na mquina virtual. Um outro problema com a checagem em tempo de execuo pode ser a diferena entre as verses do compilador e da mquina virtual. Por esses motivos a mquina virtual precisa assegurar-se de que o arquivo .class respeita todas as restries impostas atravs da checagem do arquivo. 6.7.1. O Processo de Verificao O processo de verificao opera em quatro passos: Passo 1: quando um arquivo .class carregado pela mquina virtual Java, essa primeiramente assegura-se de que o formato bsico do arquivo preservado. Os primeiros quatro bytes precisam conter o magic number. Todos os atributos reconhecidos precisam ter o tamanho prprio. O arquivo .class no pode estar truncado nem ter bytes extras no final. A constant_pool no pode conter qualquer informao superficialmente no conhecida. Passo 2: quando o arquivo .class ligado, o verificador executa todas as verificaes adicionais que podem ser feitas sem acessar o array code do atributo code. As checagens feitas por esse passo so as seguintes: o assegurar que classes final no so sub-classes e que mtodos final no so anulados; o checar se todas as classes (exceto a Object) tem uma super-classe direta;

Arquitetura de Mquinas Virtuais

49

o assegurar que a constant_pool satisfaz as restries necessrias; o checar que todas as referncias a campos e mtodos na constant_pool possuem nomes vlidos, classes vlidas e um descritor de tipo vlido. Passo 3: durante a ligao o verificador checa o array code do atributo code para cada mtodo do arquivo .class executando anlises de fluxos de dados em cada mtodo. O verificador assegura que em qualquer ponto do programa as seguintes sentenas sero verdadeiras: o a pilha de operandos tem sempre o mesmo tamanho e contm sempre os tipos de valores; o nenhuma varivel local acessada at que ela contenha um valor apropriado ao seu tipo; o mtodos so invocados com os parmetros apropriados; o so atribudos aos campos somente valores apropriados aos tipos; o todos os opcodes tem os tipos apropriados de argumentos na pilha de operandos e no array de variveis locais. Passo 4: por razes de eficincia, certos testes que poderiam, a princpio, serem feitos no passo 3 so adiados at a primeira vez que o cdigo para um mtodo invocado. O passo 4 um passo virtual, onde quem efetua as verificaes so as instrues da mquina virtual. Na primeira vez que uma instruo que referencia um tipo executada a instruo em execuo faz o seguinte: o carrega a definio do tipo caso ainda no tenha sido carregada; o checa se o tipo de execuo corrente permitida para referenciar o tipo; o a primeira vez que uma instruo invoca um mtodo, acessa ou modifica um campo, a instruo em execuo faz o seguinte: assegura-se de que o mtodo ou campo referenciado existe nessa classe; verifica se o mtodo ou campo referenciado possui o descritor indicado; checa se o mtodo em execuo tem acesso ao mtodo ou campo referenciado.

6.8. Verificao de Bytecode


O passo 3 do processo de verificao o mais complexo dos quatro passos de verificao do arquivo .class. Esta seo mostra, mais detalhadamente, a verificao do cdigo de mquina virtual no passo 3. O cdigo de cada mtodo verificado independentemente. Primeiro, os bytes que formam o cdigo so quebrados em uma seqncia de instrues. Aps isso o verificador passa novamente pelas instrues efetuando a verificao das instrues. Durante esse passo uma estrutura de dados construda para armazenar informaes sobre cada instruo do mtodo. Os operandos, se existirem, de cada instruo so checados para confirmar que so vlidos. Por exemplo: instrues de branches precisam apontar para posies no limite do array code do mtodo; os alvos das instrues de controle de fluxo precisam ser o incio de uma instruo; nenhuma instruo pode acessar ou modificar uma varivel local que tenha um ndice maior que o definido pelo mtodo; todas as referncias para a constant pool precisam apontar para uma entrada de tipo apropriado; o array code no pode terminar no meio de uma instruo; para cada tratamento de exceo, os pontos de incio e trmino do cdigo protegido pelo handler precisam apontar para o incio de uma instruo ou, no caso do ponto de trmino, imediatamente depois do fim do cdigo.

Arquitetura de Mquinas Virtuais

50

Para cada instruo executada um verificador armazena o contedo da pilha de operandos e do array de variveis locais. Para o caso da pilha de operandos ele precisa do tamanho da pilha e do tipo de cada valor armazenado nela. Para cada array de variveis locais ele precisa saber o tipo das variveis armazenadas ou se cada varivel ainda no foi inicializada. Posteriormente, um analisador de fluxo de dados inicializado. Para a primeira instruo do mtodo, as variveis locais que representam os parmetros recebidos contm os valores dos tipos informados no descritor do mtodo e a pilha de operandos est vazia. Todas as outras variveis contm um valor nulo. Para as outras instrues que ainda no tenham sido avaliadas, no existem informaes disponveis considerando a pilha de operandos e as variveis locais. Finalmente, o analisador de fluxo de dados executado. Para cada instruo um bit modificado indica se a instruo precisa ser verificada. Inicialmente, o bit modificado definido somente para a primeira instruo. O analisador de fluxo de dados executa o seguinte loop: Passo 1: seleciona uma instruo de mquina virtual que tenha o bit modificado definido. Se nenhuma instruo contiver esse bit definido, ento todas as instrues do mtodo foram analisadas. Caso contrrio desativa o bit da instruo corrente; Passo 2: modela o efeito da instruo na pilha de operandos e no array de variveis locais da seguinte forma: o se a instruo utiliza valores da pilha de operandos, verificado se existe um nmero suficiente de elementos na pilha para satisfazer a instruo e verifica tambm se os itens do topo da pilha possuem o tipo apropriado para ser utilizado pela instruo. Caso contrrio, a verificao falha; o se a instruo utiliza uma varivel local, verificado se o tipo dessa varivel compatvel com o desejado. Caso contrrio, a verificao falha; o se a instruo insere valores na pilha de operandos, verifica se essa possui espao para tal operao. Adiciona o tipo indicado no topo da pilha de operandos indicada; o se a instruo modifica uma varivel local, ento registra que essa possui um novo tipo. Passo 3: determina as instrues que podem seguir a instruo corrente. Instrues sucessoras podem ser uma das seguintes: o a prxima instruo, se a instruo corrente no uma instruo de salto incondicional (exemplo: goto, return, athrow); o a instruo alvo de um saldo condicional ou incondicional; o qualquer manipulador de exceo (exception handler) para a instruo. Passo 4: mescla o estado da pilha de operandos e do array de variveis locais no final da execuo da instruo corrente em cada uma das instrues sucessoras. No caso especial da transferncia de controle para um tratamento de exceo, a pilha de operados definida para conter um nico objeto do tipo da exceo indicado pela informao do exception handler: o se essa a primeira vez que a instruo sucessora visitada, registra que os valores da pilha de operandos e das variveis locais calculadas anteriormente so os estados antes da execuo da instruo sucessora. Define o bit modificado da instruo sucessora; o se a instruo sucessora j foi vista anteriormente, a mesclagem dos valores da pilha de operandos e das variveis locais j est feita. Define o bit modificado se houve qualquer modificao nos valores. Passo 5: voltar ao primeiro passo.

Arquitetura de Mquinas Virtuais

51

Para mesclar duas pilhas de operandos, o nmero de valores nas pilhas precisa ser idntico. Os tipos de valores nas pilhas tambm precisam ser idnticos, exceto que valores reference tipados diferentemente podem aparecer em locais correspondentes nas duas pilhas. Nesse caso, a pilha de operandos mesclada contm uma referncia para a primeira super-classe comum aos dois tipos. Se as pilhas de operandos no puderem ser mescladas a verificao falha. Para mesclar dois estados de arrays de variveis locais, pares correspondentes de variveis so comparados. Se dois tipos no forem idnticos, ento, a menos que ambos sejam do tipo reference, o verificador registra que a varivel local possui um valor no utilizvel. Se ambos contm valores reference, o estado mesclado contm uma referncia para uma instncia da primeira super-classe comum aos dois tipos. Se o analisador de fluxo de dados executado sem reportar erros em um mtodo, ento o mtodo considerado verificado com sucesso pelo Passo 3 do processo de verificao do arquivo de classe.

6.9. Manipuladores de Excees


Cdigos para mquinas virtuais Java produzidos por compiladores Sun sempre geram tratamento de excees da seguinte forma: as regies de cdigo protegidas por deferentes manipuladores de exceo so totalmente disjuntas ou uma um subconjunto da outra. Jamais pode existir uma interseco dessas duas regies; o cdigo que trata uma exceo nunca poder estar dentro da regio de cdigo protegida; a nica forma de entrar em um tratamento de exceo causando uma exceo.

Tais restries no so verificadas pelo verificador de arquivo de classe, pois, elas no proporcionam ameaa integridade da JVM. Caso todos os caminhos no-excepcionais ao manipulador de excees conduzam existncia de um objeto na pilha de operandos, e caso todos os outros critrios do verificador sejam satisfeitos, o verificador permitir a passagem do cdigo.

6.10. Formato de Arquivo CLR


De acordo com Meijer (2001) e Microsoft (2001), o formato de arquivo do framework .NET (PE File Format) especifica basicamente instrues MSIL e meta-dados. A CLR depende das seguintes informaes sobre cada mtodo, definidas em um arquivo PE: as instrues que compem o corpo do mtodo, incluindo todos os tratadores de exceo; a assinatura do mtodo, que especifica o tipo de retorno, e o nmero, ordem, conveno de passagem de parmetros, e tipos de dados primitivos de cada argumentos de entrada. A assinatura tambm especifica a conveno de chamada nativa, que no afeta a conveno de chamada virtual MSIL, mas, apenas o cdigo nativo; o array de tratamento de exceo (exception handling array). Esse array mantm informao que delimita os alcances nos quais excees so filtradas e capturadas; o tamanho da pilha de avaliao que o mtodo ir requerer; o tamanho do array de variveis locais que o mtodo ir requerer; um zero init flag que indica se o array de variveis locais e o memory pool devem ser inicializados pela CLR; os tipos de todas as variveis locais na forma de uma assinatura do array de variveis locais.

Arquitetura de Mquinas Virtuais

52

Alm disso, o formato de arquivo capaz de indicar o grau de portabilidade do arquivo. H dois tipos de restries que podem ser descritas: restrio para um tamanho natural especfico (32-bit ou 64-bit) para inteiros; restrio para um endian (ordenao de bytes em uma palavra de mquina) especfico.

Determinando quais restries esto presentes na execuo do cdigo, o carregador de classe CLR pode prevenir que cdigo no-portvel seja executado em uma arquitetura que ele no possa suportar.

7. Execuo de Programas
7.1. Execuo de Programas JVM
De acordo com Lindholm (1996) e Venners (1996, 2000), tipos Java (classe e interface), que em conjunto formam um programa Java, so representados de acordo com o formato do arquivo de classe Java, que constitui a forma binria padro para a representao de tipos. Uma questo relevante no estudo de uma mquina virtual diz respeito ao tempo de vida de um tipo (ou programa), partindo da entrada inicial do tipo na mquina virtual, e seguindo at sua sada final. O tempo de vida envolve os processos de carga, ligao e inicializao, que ocorrem no tempo de vida inicial, os processos de instanciao de objeto, coleta de lixo (garbage collection) e finalizao, que ocorrerem no tempo de vida principal, e o processo de descarga, que ocorre no tempo de vida final. A JVM torna tipos disponveis para um programa em execuo atravs dos processos de carga, ligao e inicializao de tipos.

Figura: tempo de vida inicial de um tipo (classe ou interface) Java. Fonte: Venners (2000).

7.2. Carga de Tipos


Carga refere-se ao processo de encontrar e levar para dentro da mquina virtual a forma binria de um tipo com um nome particular, possivelmente processando-o instantaneamente, mas, tipicamente

Arquitetura de Mquinas Virtuais

53

recuperando uma representao binria previamente computada do cdigo fonte por um compilador. O processo de carga divide-se em trs sub-processos: produo de um stream de dados binrios que representa um tipo; anlise (parse) do stream de dados binrios em estruturas de dados internas na rea de mtodo; criao de uma instncia da classe Class que representa o tipo.

O stream de dados binrios pode aderir ao formato de arquivo de classe Java, mas, pode tambm, alternativamente, seguir outro formato, pois, apesar de todas as implementaes JVM terem que reconhecer o formato de arquivo de classe Java padro, implementaes individuais podem tambm reconhecer outros formatos binrios. A especificao de JVM no determina como dados binrios para um tipo devem ser produzidos. Algumas maneiras potenciais so: carregar um arquivo de classe Java do sistema de arquivo local; transferir um arquivo atravs da rede; extrair um arquivo de classe de um arquivo de compresso; compilar um arquivo fonte Java instantaneamente (on-the-fly) no formato de arquivo de classe.

Tendo os dados binrios para um tipo, a JVM deve process-los para uma extenso suficiente, de forma que ela possa criar uma instncia de classe Class. Alm disso, a JVM deve fazer o parse dos dados binrios em estruturas de dados internas dependentes de implementao. A instncia de classe Class, o produto final do processo de carga, atua como uma interface entre o programa e as estruturas de dados internas, de forma que, para acessar informao sobre um tipo que est armazenado nas estruturas de dados internas, o programa invoca mtodos na instncia Class para aquele tipo. Portanto, os processos de parse dos dados binrios para um tipo em estruturas de dados internas na rea de mtodo e instanciao de um objeto Class na rea heap definem, em conjunto, a criao do tipo. Tipos so carregados atravs do carregador de classe bootstrap ou atravs de carregadores de classe definidos pelo usurio. O carregador bootstrap, parte da implementao JVM, carrega tipos de uma forma dependente de implementao. J os carregadores definidos pelos usurios, instncias de sub-classes de ClassLoader, carregam classes de forma customizada. Em tempo de execuo, um programa Java pode instalar objetos class loader que carregam classes de maneiras customizadas, como, por exemplo, transferindo classes atravs de uma rede. A JVM considera que quaisquer classes que ela carrega atravs do carregador primordial (bootstrap) so confiveis. Ao contrrio, ela suspeita das classes que ela carrega atravs de objetos class loader. Por padro, ela as considera no-confiveis. O carregador primordial (bootstrap) parte intrnseca da mquina virtual, enquanto os objetos class loader no, eles so escritos em Java, compilados em arquivos de classe, carregados na mquina virtual e instanciados como qualquer outro objeto.

Arquitetura de Mquinas Virtuais

54

Figura: arquitetura do carregador de classes da mquina virtual. Fonte: Venners (2000).

Carregadores de classe podem armazenar em cache representaes binrias de tipos, carregar tipos antecipadamente sua eventual utilizao, ou carregar tipos conjuntamente em grupos relacionados. Mas, se um carregador encontrar problemas durante a carga antecipada de um tipo, por exemplo, arquivo de classe danificado, mal formado, ou faltante, ele dever esperar at que a classe seja ativamente utilizada pelo programa pela primeira vez, para reportar o erro.

7.3. Ligao de Tipos


Ligao o processo de combinar uma forma binria de um tipo ao estado de execuo da JVM, de forma que ele possa ser executado. Trs sub-processos compem o processo de ligao: verificao; preparao; resoluo.

A verificao consiste em garantir que o tipo obedece s semnticas da linguagem Java e que ele no violar a integridade da mquina virtual. Projetistas de implementao JVM podem decidir como e quando verificar tipos, devido flexibilidade da especificao de JVM, que lista todas as excees que uma JVM pode disparar e sob quais condies ela deve dispar-las, mas que em muitos casos no dita precisamente como e quando uma condio de erro deve ser detectada. Apesar disso, alguns tipos de verificaes so provveis de ocorrerem em momentos semelhantes na maior parte das implementaes JVM. Por exemplo, durante a carga, a JVM deve fazer o parse do stream de dados binrios que representa o tipo e construir estruturas de dados internas, sendo necessrias verificaes para garantir que: os dados binrios apresentam o formato esperado, cada componente esteja no local correto e com tamanho adequado, o arquivo no muito curto ou longo, dentre outras. Todo o processo de verificao de qualquer tipo de problema com tipos carregados faz parte da categoria de verificao e est logicamente na fase de verificao, apesar de poder ocorrer durante a fase de carga. Outro exemplo de verificao que ocorre durante a carga garantir que toda classe (exceto a classe Object) tem uma super-classe, pois, quando uma JVM carrega uma classe, ela deve garantir que todas as super-classes da classe tambm foram carregadas.

Arquitetura de Mquinas Virtuais

55

Um exemplo de verificao que em muitas implementaes ocorre realmente na fase de verificao a checagem de referncias simblicas. O processo de ligao dinmica envolve a localizao de classes, interfaces, campos e mtodos referenciados por referncias simblicas, e a substituio das referncias simblicas por referncias diretas. Quando uma mquina virtual procura por uma entidade simbolicamente referenciada, ela deve garantir que a entidade existe. Se a mquina virtual verifica que a entidade existe, ela deve ento checar se o tipo que faz a referncia tem permisso de acesso entidade. Essas verificaes fazem parte logicamente da fase de verificao, mas, na maior parte dos casos ocorrem durante a resoluo. Verificaes que garantem que classes so compatveis binariamente podem ocorrer durante a fase oficial de verificao, tais como, checar que classes finais no so sub-classes, checar que mtodos finais no so contornados (by-passed), checar que declaraes de mtodos incompatveis no acontecem entre o tipo e seus super-tipos. Uma das tarefas mais complicadas a verificao de bytecodes. Todas as mquinas virtuais devem verificar a integridade dos bytecodes para todo mtodo que elas executam. As implementaes JVM podem utilizar tcnicas e momentos diferentes para realizar a verificao de bytecodes, por exemplo, verificando instrues individuais conforme cada uma delas executada. Entretanto, o conjunto de instrues JVM foi projetado de forma a possibilitar a gerao de streams de bytecodes que podem ser verificados todos de uma vez por um analisador de fluxo de dados. A fase de preparao do processo de ligao pode ocorrer aps a carga e a verificao de uma classe. A JVM aloca memria para as variveis da classe e as inicializam com valores padres iniciais determinados pelo tipo da varivel (elas so inicializadas com seus valores iniciais apropriados somente na fase de inicializao, pois, nenhum cdigo JVM executado durante a fase de preparao). Durante a preparao, implementaes JVM podem tambm alocar memria para estruturas de dados que tm o objetivo de melhorar a performance do programa em execuo. Um exemplo a tabela de mtodo, que contm um ponteiro para os dados para todo mtodo em uma classe, incluindo aqueles herdados de suas super-classes. Uma tabela de mtodo possibilita que um mtodo herdado seja invocado em um objeto sem uma busca de super-classes no ponto de invocao. Finalmente, a fase de resoluo do processo de ligao consiste na localizao de classes, interfaces, campos e mtodos referenciados simbolicamente a partir de uma constant pool de tipo, e substituio das referncias simblicas por diretas. A fase de resoluo opcional, podendo ser postergada at que cada referncia simblica seja utilizada pela primeira vez pelo programa, podendo, dessa forma evitar resolues desnecessrias.

7.4. Inicializao de Tipos


O passo final requerido para deixar um tipo pronto para sua primeira utilizao ativa a inicializao, que consiste no processo de atribuir s variveis da classe seus valores iniciais apropriados, ou seja, aqueles valores desejados pelo programador. Tais valores so especificados por meio de um inicializador de varivel de classe, ou seja, o processo de inicializao de uma classe consiste em executar seus mtodos inicializadores estticos. Todos os inicializadores de um tipo so coletados pelo compilador e embarcados em um mtodo especial, que pode ser invocado exclusivamente pela JVM, com o propsito de inicializar as variveis com seus valores apropriados. A inicializao de uma classe consiste de duas etapas: inicializao das super-classes diretas da classe; execuo do inicializador da classe. Para inicializar as super-classes diretas, os mesmos dois passos devem ser seguidos; como

Arquitetura de Mquinas Virtuais

56

conseqncia, a primeira classe que ser inicializada ser sempre a Object, e em seguida, todas as demais classes abaixo na hierarquia de herana para a classe que estiver sendo ativamente utilizada, sempre com as super-classes sendo inicializadas antes das sub-classes. A especificao de JVM proporciona flexibilidade para as temporizaes de carga e ligao, mas define de forma rgida a temporizao de inicializao, demandando que as implementaes de JVM inicializem tipos em sua primeira utilizao ativa, que pode acontecer em situaes tais como: criao de uma nova instncia de uma classe; invocao de um mtodo esttico declarado por uma classe; utilizao de um campo esttico declarado por uma classe ou interface; inicializao de uma subclasse de uma classe; designao de uma classe como a classe inicial.

Quaisquer utilizaes de um tipo alm das situaes citadas acima so consideradas passivas, e no disparam uma inicializao de tipo. A regra de inicializar na primeira utilizao ativa dirige o mecanismo de carga, ligao e inicializao de tipos, visto que, na primeira utilizao, um tipo deve ser inicializado. Entretanto, antes de ser inicializado, ele deve ser carregado, e ento ligado. Considerando a flexibilidade da especificao de JVM, implementaes JVM podem proceder com a carga e a ligao antecipadamente.

7.5. Objetos
7.5.1. Instanciao Existem quatro maneiras de instanciar uma classe explicitamente: com o operador new; invocando o mtodo newInstance() em um objeto Class ou reflect.Constructor; invocando clone() em qualquer objeto existente; desserializando um objeto atravs do mtodo getObject() da classe ObjectInputStream.

Alm dos quatro modos listados previamente para instanciao explicita de objetos, h diversas situaes nas quais objetos sero instanciados implicitamente, sem a utilizao dos quatro recursos (mtodos e operador) listados acima. Objetos String so, provavelmente, os primeiros a serem implicitamente inicializados em qualquer programa Java, pois, tais objetos so empregados para manter os argumentos de linha de comando, um para cada argumento. Referncias para esses objetos so enviadas no array de strings enviado como parmetro ao mtodo main() de todo programa. Existem ainda duas formas de uma classe ser instanciada implicitamente, que envolvem o processo de carga de classe. Primeiro, para todo tipo que uma JVM carrega, ela implicitamente inicializa um novo objeto Class para representar o tipo. Segundo, quando a JVM carrega uma classe que contm entradas CONSTANT_String_info no seu constant pool, ela pode instanciar novos objetos String para representar os literais strings constantes. Memria alocada para todas as variveis declaradas na classe do objeto e em todas as suas super-classes, incluindo variveis ocultas. Ao instanciar um objeto, a JVM primeiramente aloca memria na rea heap para manter as variveis instanciadas do objeto. Aps ter alocado a rea heap para um novo objeto, a JVM imediatamente inicializa as variveis para valores iniciais padro. Aps a inicializao com valores padro, a JVM pode atribuir s variveis instanciadas seus valores iniciais apropriados. A JVM utiliza trs tcnicas, dependendo da tcnica de instanciao de

Arquitetura de Mquinas Virtuais

57

classe empregada. Se o objeto estiver sendo criado atravs de uma invocao ao mtodo clone(), a JVM copia os valores das variveis instanciadas do objeto sendo clonado no novo objeto. Se o objeto estiver sendo desserializado, a JVM inicializa as variveis instanciadas no-transientes do objeto a partir de valores lidos de um stream de entrada. De outra forma, a JVM invoca o mtodo de inicializao de instncia no objeto, que responsvel por instanciar as variveis com seus valores apropriados iniciais. O compilador Java gera pelo menos um mtodo de inicializao de instncia para cada classe compilada. O mtodo de inicializao de instncia chamado de <init> no arquivo de classe Java, de forma que, para cada construtor de classe gerado um mtodo <init>. Caso a classe no declare um mtodo construtor explicitamente, o compilador gera um construtor padro nulo. Mtodo <init> podem conter trs tipos de cdigo: invocaes de outros mtodos <init>; bytecodes que implementam inicializadores de variveis de instncia; bytecodes para o corpo de construtores.

Para toda classe, exceto a classe Object, um mtodo <init> deve iniciar com uma invocao de outro mtodo <init> pertencente mesma classe ou super-classe direta. 7.5.2. Finalizao Implementaes JVM devem possuir alguma estratgia de gerenciamento automtico de memria para a rea heap, sendo empregado para tanto um coletor de lixo (garbage collector). Programas podem alocar memria para objetos atravs de maneiras explicitas ou implcitas, mas no podem explicitamente desalocar memria. Quando um objeto torna-se no mais referenciado pelo programa, a JVM pode coletar lixo, ou seja, desalocar sua posio de memria para reutilizao. Implementaes podem decidir quando coletar lixo de objetos no mais referenciados, e mesmo se iro desalocar rea ocupada por objetos no mais referenciados, ou seja, o emprego de garbage collection em implementaes JVM opcional, de acordo com a especificao de JVM. Se uma classe declara um mtodo finalizador, nomeado finalize(), o coletor de lixo executar tal mtodo antes de liberar o espao de memria ocupado por uma instncia que tornar-se no mais referenciada. Caso o objeto torne-se de novo referenciado (ressurreio) como resultado da execuo do cdigo finalizador, e ento se torna novamente no-referenciado posteriormente, o coletor de lixo ficar impedido de invocar automaticamente o finalizador novamente, pois, o coletor de lixo pode invocar um finalizador de objeto no mximo uma vez.

7.6. Descarga de Tipos


O tempo de vida de uma classe na JVM similar ao de um objeto. A JVM cria e inicializa objetos, possibilita que o programa utilize os objetos, e opcionalmente, coleta o lixo dos objetos aps eles no serem mais referenciados por certo perodo de tempo pelo programa. Similarmente, a mquina virtual carrega, liga e inicializa classes, permitindo aos programas utilizarem as classes, e opcionalmente, descarrega as classes aps certo perodo de tempo no qual elas no tenham sido mais referenciadas pelo programa. Garbage collection e descarga de classes so importantes na JVM, pois, programas podem ser dinamicamente estendidos em tempo de execuo por meio da carga de tipos atravs de carregadores de classe definidos pelo usurio. Todos os tipos carregados ocupam espao de memria na rea de mtodo. Se um programa carrega tipos continuamente, o espao disponvel de memria na rea de mtodo ficar crtico. Se

Arquitetura de Mquinas Virtuais

58

alguns dos tipos carregados so necessrios apenas temporariamente, o espao de memria ocupado por eles pode ser liberado descarregando os tipos aps eles no serem mais necessrios. O modo por meio do qual uma JVM pode assumir que um tipo carregado dinamicamente no mais necessrio ao programa similar ao modo empregado no caso de objetos: se o programa no tem mais referencias ao tipo, ento o tipo no poder afetar a execuo futura do programa, sendo considerado no-alcanvel, e poder ser descarregado. J os tipos carregados atravs do carregador bootstrap sero sempre alcanveis e nunca ser descarregada durante a execuo do programa. Apenas tipos carregados atravs de carregadores de classe definidos pelo usurio podem tornar-se no-alcanveis e serem descarregados pela JVM. Um tipo no-alcanvel se sua instncia Class considerada no-alcanvel atravs do processo normal de coleta de lixo da heap. Uma instncia Class carregada dinamicamente considerada alcanvel, primeiramente, se o programa possuir uma referncia explcita para ela, ou, se houver um objeto alcanvel na rea heap cujos dados de tipo na rea de mtodo refere instncia Class. Implementaes podem localizar dados de tipo para uma classe de objeto na rea de mtodo utilizando apenas uma referncia ao objeto. Por isso, a imagem de um objeto na heap inclui algum tipo de ponteiro para os seus dados de tipo na rea de mtodo. Por meio dos dados de tipo, a JVM pode localizar as instncias Class para a classe de objeto, bem como todas as suas super-classes.

Figura: alcanando instncias Class atravs de um objeto alcanvel. Fonte: Venners (2000).

7.7. Execuo de Programas CLR


7.7.1. Carga de Classes Segundo Meijer (2001) e Microsoft (2001), o carregador de classe CLR carrega a implementao de uma classe, expressa em MSIL, OptIL, ou cdigo nativo, na memria, checa que ela consistente com suposies feitas sobre ela por outras classes previamente carregadas, e a prepara para execuo. Para realizar essa tarefa, o carregador de classe garante que certa informao conhecida, incluindo a quantidade e o formato do espao que instncias do tipo requerem. Alm disso, o carregador de classe determina se referncias feitas pelo tipo carregado esto disponveis em tempo de execuo, e se referncias ao tipo carregado so consistentes.

Arquitetura de Mquinas Virtuais

59

O carregador de classe checa alguns requisitos de consistncia que so vitais para o mecanismo de segurana da CLR. Essas verificaes constituem um processo de verificao mnimo e obrigatrio que precede a fase de verificao MSIL, que mais rigorosa (e opcional), assim como acontece com a JVM. Alm disso, o carregador de classe suporta segurana pelo provimento de algumas das credenciais requeridas para validao de identidade de cdigo. Diferentemente da JVM, a CLR permite apenas um carregador de classe, o seu prprio, ou seja, ela no suporta carregadores escritos por usurios. 7.7.2. Verificao Programas typesafe referenciam apenas memria que foi alocada para sua utilizao, e eles acessam objetos apenas atravs de suas interfaces pblicas. Essas restries permitem aos objetos compartilharem com segurana um espao de endereamento singular, e elas garantem que verificaes de segurana providas pelas interfaces dos objetos no sejam desviadas. O mecanismo de segurana CLR pode efetivamente proteger cdigo contra acesso noautorizado somente se houver alguma maneira de verificar que o cdigo typesafe. Para satisfazer essa necessidade, a CLR utiliza a informao contida em assinaturas de tipo para ajudar a determinar se o cdigo MSIL typesafe. Ela verifica se os meta-dados so formados corretamente, e realiza anlise de fluxo de controle para garantir que determinadas condies estruturais e de comportamento so satisfeitas. A CLR declara em tempo de execuo que um programa foi verificado com sucesso somente se ele typesafe. Utilizada em conjunto com a tipagem forte de meta-dados e MSIL, essa fase de verificao pode garantir a segurana de tipo dos programas escritos em MSIL. A CLR requer que cdigo seja verificado antes que possa ser executado, a menos que uma verificao de segurana especfica, controlada administrativamente, determine que o cdigo pode ser completamente confivel. 7.7.3. Verificaes de Segurana Alm do processo de verificao requerido pela segurana de acesso a cdigo, a CLR prov suporte que possibilita que verificaes de segurana declarativas e imperativas possam ocorrer. Verificaes de segurana declarativas acontecem automaticamente sempre que um mtodo chamado. As permisses requeridas para acessar o mtodo so armazenadas nos meta-dados do componente. Em tempo de execuo, chamadas a mtodos que so marcados como exigentes de permisses especficas so interceptadas para determinar se o invocador tem as permisses requeridas. Verificaes de segurana imperativas acontecem quando funes de segurana, tais como, checar uma permisso de acesso a cdigo, ou conceder o direito de utilizar uma permisso especificada, so invocadas do cdigo que est sendo protegido. A CLR suporta esse tipo de verificao de segurana pelo provimento de mtodos confiveis, que possibilitam a determinao da identidade de cdigo, e a localizao e o armazenamento na pilha das permisses. 7.7.4. Profiling e Debugging A CLR prov a habilidade de depurar (debugging), ou seja, observar e modificar o comportamento, e delinear (profiling), ou seja, medir a utilizao de recursos, programas em execuo. Ambas as atividades dependem de informao produzida pelo compilador de linguagem fonte e

Arquitetura de Mquinas Virtuais

60

atualizadas pelo compilador JIT. A CLR prov uma API para depurao que manipula o registro e a notificao de eventos no programa em execuo. Isso permite que um depurador possa controlar a execuo de um programa, incluindo a definio e manipulao de breakpoints, a interceptao de excees, a modificao de fluxo de controle, e o exame e a modificao do estado de programa. Alm disso, a CLR prov uma API para utilizao por ferramentas de profiling. A API suporta profiling de cdigo nativo gerenciado com a insero de provas de profiling no cdigo. 7.7.5. Interoperao A CLR realiza transies entre cdigos gerenciados e no-gerenciados de duas maneiras: interoperao com clientes e servios COM (Component Object Model) existentes, chamada COM Interop; interoperao com DLL nativas previamente compiladas, chamada platform invoke.

Onde for necessrio, por exemplo, por causa de diferenas de formato de dados, a CLR fornece procedimentos de ordenao (marshaling) que copiam e/ou reformatam informao atravs das fronteiras.

Arquitetura de Mquinas Virtuais

61

8. Compilao
A JVM designada a suportar a linguagem de programao Java. A linguagem Java contm alguns recursos como: um compilador de cdigo-fonte Java para um conjunto de instrues JVM (javac). O termo "compilar" utilizado algumas vezes para referir a traduo de um conjunto de instruo da JVM para um conjunto de instruo de uma CPU especfica. Um exemplo o compilador "Just In Time" (JIT) que gera instrues especficas da plataforma somente depois da JVM ter carregado seu cdigo. Neste captulo ser apresentado como um compilador Java utiliza a JVM e compreender a operao da JVM.

8.1. Uso de constantes e variveis locais, e de construes de controle


O mtodo abaixo ser um exemplo para anlise de uso das constantes, variveis locais e construes de controle: void spin() { int i; for (i = 0; i < 100; i++) { ; // Loop body is empty } } o cdigo compilado : Mtodo void spin()
0 1 2 5 8 9 11 14 iconst_0 istore_1 goto 8 iinc 1 1 iload_1 bipush 100 if_icmplt 5 return // empilha constante int 0 // armazena em local 1 (i=0) // primeira vez no incrementa // incrementa local 1de 1 (i++) // empilha local 1 (i) // empilha constante int (100) // compare, d laos se < (i < 100) // retorna void quando feito

A JVM orientada a empilhamento, pois a maioria das operaes possui um ou mais operandos na pilha do frame atual, ou empilha resultados de retorno de operaes na pilha. Um novo frame criado cada vez que um mtodo Java invocado, e com ele criada uma pilha de operandos e conjunto de variveis locais para uso deste mtodo. Portanto, h momentos em que h muitos frames e tambm muitas pilhas de operando por linha do controle, correspondendo a muitas invocaes do mtodo. Somente a pilha de operandos no frame atual ativa. O conjunto de instruo da JVM distingue tipos do operando usando bytecodes distintos para operaes em seus vrios tipos de dados. O mtodo spin opera somente sobre valores do tipo int (iconst_0 ,istore_1 ,iinc ,iload_1 ,if_icmplt). Uso de Constantes As duas constantes dentro spin, 0 e 100, so empilhadas na pilha de operandos usando duas instrues diferentes: 0 empilhado usando iconst_0 - uma instruo iconst_<i> sabe est o que est empilhando, no necessita armazenar um operando, nem necessita buscar ou descodificar um operando.

Arquitetura de Mquinas Virtuais

62

100 empilhado usando uma instruo do bipush, que a busca ao valor como um operando imediato e descodifica o operando.

Uso de Variveis Locais O int i armazenado como a varivel local 1 da JVM porque a maioria de instrues operam sobre os valores do operando, pois empilham melhor que diretamente em variveis locais. As instrues que transferem valores entre variveis locais e a pilha do operandos so comuns no cdigo compilado da JVM. Estas operaes tm tambm o suporte especial do conjunto de instruo. Em spin, os valores so transferidos entre a pilha e as variveis locais usando as instrues istore_1 e iload_1, cada uma opera implicitamente sobre a varivel local 1. A instruo istore_1 seleciona int da pilha do operando e armazena-o na varivel local 1. A instruo iload_1 transfere o valor na varivel local 1 para pilha do operando. Construes de Controle O lao (for) de spin realizado principalmente pelas instrues 5, 8, 9 e 11. 5 8 9 11 iinc 1 1 iload_1 bipush 100 if_icmplt 5 // incrementa local 1 de 1 (i++) // empilha varivel local 1 (i) // empilha constante int (100) // compara e faz o laos se < (i < 100)

A instruo do bipush empilha o valor 100 na pilha do operando como int, ento a instruo if_icmplt desempilha e compara-o com i. Se a comparao suceder (a varivel i menos do que 100), o controle transferido ao ndice 5 e a iterao seguinte for do lao comea. Se no, o controle passa instruo que segue o if_icmplt. Se o exemplo do mtodo spin usasse um tipo de dados diferente para o i, como por exemplo double, o cdigo compilado necessariamente mudaria para refletir o tipo de dado diferente: void dspin() { double i; for (i = 0.0; i < 100.0; i++) { ; // Loop body is empty } } o cdigo compilado : Mtodo void dspin()
0 1 2 5 6 7 8 9 10 13 14 17 dconst_0 dstore_1 goto 9 dload_1 dconst_1 dadd dstore_1 dload_1 ldc2_w #4 dcmpg iflt 5 return // empilha constante double 0.0 // armazena nas variveis locals 1 and 2 (i = 0.0) // primeira vez no incrementa // empilha double na pilha de operandos // empilha constante double 1 na pilha // adiciona // armazena resultados em locais 1 and 2 // empilha local // double 100.000000 // no h instruo if_dcmplt // compare, loop if < (i < 100.000000) // retorna void quando feito

Arquitetura de Mquinas Virtuais

63

Note que dentro do mtodo dspin os valores double usam duas palavras (two-word) de armazenamento tanto na pilha do operandos como nas variveis locais. Isto tambm vale para valores do tipo long. Alm disso, sempre necessrio capturar as palavras two-word em pares e em sua ordem original. A mquina virtual de Java no fornece suporte igual para todos os tipos de dados: no completamente orthogonal. A mquina virtual de Java fornece suporte mais direto para dados do tipo int. Isto em parte porque a pilha do operando da mquina virtual de Java e as variveis locais possuem largura de uma palavra, dada tambm pela maior freqncia de int para os dados em programas tpicos de Java. A falta de suporte direto para byte, char, e short dentro da JVM no prejudicial, porque estes tipos so promovidos internamente a int. O nico custo adicional o de truncar os valores int das operaes s escalas vlidas.

8.2. Aritmtica
A mquina virtual de Java faz geralmente aritmtica em sua pilha do operando ( exceo da instruo iinc, que diretamente incrementa o valor de uma varivel local). Os operandos para operaes aritmticas so colocados da pilha do operando, e os resultados das operaes so empilhados tambm na pilha do operando.

8.3. Alcanando o Constant Pool


Muitas constantes numricas, tais como objetos, campos e mtodos so alcanados atravs do constant pool da classe atual. Os dados dos tipos int, long, float, e double, bem como referncias aos exemplos de String so controlados usando o ldc, o ldc_w, e as instrues de ldc2_w. As instrues do ldc e do ldc_w so usadas para alcanar valores de uma palavra no pool de constante, e ldc2_w usado alcanar valores de duas palavras. A instruo do ldc_w usada no lugar do ldc somente quando h um grande nmero elementos constantes do pool e um ndice maior necessrio para alcanar um elemento. A instruo de ldc2_w usada para alcanar todos os elementos de duas palavras. As constantes dos tipos byte char, ou short, assim como valores int pequenos, podem ser compilados usando as instrues bipush, sipush ou iconst_<i >. Determinadas constantes de pontos flutuantes podem ser compiladas usando as instrues fconst_<f> e dconst_<d>. Em todos estes casos a compilao direta.

8.4. Mais Construes de Controle


Um lao while compilado de uma maneira bvia, embora as instrues especficas de transferncia de controle da JVM variem pelo tipo de dados. Como usual, mais uma construo suportada por dados do tipo int: void whileInt() { int i = 0; while (i < 100) { i++; } } o cdigo compilado :

Arquitetura de Mquinas Virtuais

64

Mtodo void whileInt()


0 1 2 5 8 9 11 14 Iconst_0 Istore_1 goto 8 iinc 1 1 Iload_1 Bipush 100 if_icmplt 5 Return

Note que o teste while (executada usando a instruo do if_icmplt) est no fundo do cdigo de JVM para lao, o que obriga o uso de uma instruo goto para comear ao teste antes da primeira iterao do lao. Se esse teste falhar, e no entrar no corpo do lao, esta instruo ser desperdiada. Entretanto, os laos while so usados tipicamente quando seu corpo espera funcionar para muitas iteraes. Para iteraes subseqentes, pr este teste no final do lao conserva uma instruo JVM cada iterao em torno do lao: se o teste estivesse no alto do lao, o corpo do lao necessitaria uma instruo goto para voltar ao comeo. As construes do controle que envolvem outros tipos de dados so compiladas de maneira similar, mas devem usar as instrues disponveis para aqueles tipos de dados. Isto conduz ao cdigo um tanto menos eficiente porque mais instrues de JVM so necessrias: void whileDouble() { double i = 0.0; while (i < 100.1) { i++; } } o cdigo compilado : Mtodo void whileDouble()
0 1 2 5 6 7 8 9 10 13 14 17 dconst_0 dstore_1 goto 9 dload_1 dconst_1 dadd dstore_1 dload_1 ldc2_w #4 dcmpg iflt 5 return

// empilha Constant double 100.1 // fazer a comparao e a ligao //duas instrues...

8.5. Recebendo Argumentos


Se n argumentos so passados para a instncia de um mtodo, por conveno, eles so recebidos em variveis locais numeradas 1 a n do frame criado para a invocao do novo mtodo. Os argumentos so recebidos na ordem que foram passados. Por exemplo:

Arquitetura de Mquinas Virtuais

65

int addTwo(int i, int j) { return i + j; } o cdigo compilado : Mtodo int addTwo(int,int)


0 1 2 3 iload_1 iload_2 iadd ireturn // empilhe valor local 1 (i) // empilhe valor local 2 (j) // adicione; e deixe o resultado int na pilha de operandos // retorna resultado int

Pela conveno, para o mtodo instanciado passada referncia da varivel local zero. O exemplo acessvel em Java atravs da palavra-chave this. Os mtodos de classe static no tm uma instncia, ento para eles, este uso da varivel local zero desnecessrio. Um mtodo classe comea usando variveis locais no ndice zero. Se o mtodo addTwo fosse um mtodo classe, seus argumentos seriam passados em uma maneira similar primeira verso: static int addTwoStatic(int i, int j) { return i + j; } o cdigo compilado : Mtodo int addTwoStatic(int,int)
0 1 2 3 iload_0 iload_1 iadd ireturn

A nica diferena que os argumentos do mtodo parecem comeando na varivel local 0 melhor que em 1.

8.6. Invocando Mtodos


A invocao de um mtodo normal executada usando a instruo invokevirtual, que pega como seu argumento um ndice no runtime constant pool, dando o nome qualificado do tipo classe do objeto, o nome do mtodo para invocar, e o descriptor desse mtodo. Para invocar o mtodo addTwo, definido mais cedo como um mtodo instanciado, escrever: int add12and13() { return addTwo(12, 13); } o cdigo compilado : Mtodo int add12and13()
0 1 3 aload_0 bipush 12 bipush 13 // empilhe valor local 0 (this) // empilha constante int (12) // empilha constante int constante 13

Arquitetura de Mquinas Virtuais 5 8 #4 invokevirtual ireturn // mtodo Example.addtwo(II)I // retorna int na parte superior de pilha // int o resultado de addTwo()

66

A invocao ajustada primeiramente empilhando a referncia this na pilha de operandos. Ento os argumentos de invocao do mtodo, os valores int 12 e 13, so empilhados. Quando o frame para o mtodo addTwo criado, os argumentos passados ao mtodo transformam-se nos valores iniciais das variveis locais do frame novo. Isto , reference para this e os dois argumentos, empilhados na pilha de operandos por quem invocou, transformaro nos valores iniciais das variveis locais 0, 1, e 2 do mtodo invocado. Finalmente, addTwo invocado. Quando retorna, seu valor de retorno int colocado na pilha de operandos do frame do invocador, o mtodo add12and13. O valor do retorno posto assim no lugar a ser retornado imediatamente ao invocador de add12and13. O retorno de add12and13 assegurado pela instruo ireturn de add12and13. A instruo do ireturn pega o valor retornado perto addTwo, na pilha de operandos do frame atual, e coloca-o na pilha de operandos do frame do invocador. Retorna ento o controle ao invocador, colocando o frame do invocador como corrente. A mquina virtual de Java fornece instrues do retorno distintas para muitos de seus tipos numricos e tipos de dados referenciados, assim como uma instruo de retorno para mtodos com nenhum valor do retorno. O mesmo jogo das instrues de retorno usado para todas as variedades de invocaes de mtodo. O operando da instruo invokevirtual (no exemplo, no ndice constante #4 do pool) no o posicionamento do mtodo na instncia classe. O compilador de Java no sabe a disposio interna de uma instncia classe. Gera referncias simblicas aos mtodos de uma instncia, que so armazenados no constant pool. Os itens do runtime Constant Pool so resolvidos na hora da execuo para determinar a posio real do mtodo. O mesmo conjunto de instrues de retorno usado para todas as variedades de mtodo de invocao. Compilar uma invocao de um mtodo da classestatic() como compilar uma invocao de um mtodo instncia, exceto do this no ser passado pelo invocador. Os argumentos do mtodo sero recebidos comeando com varivel local 0. A instruo invokestatic usada sempre para invocar mtodos da classe. A instruo invokespecial deve ser usada invocar mtodos de iniciao de instncia <init>(). usada tambm ao invocar mtodos nas superclasses (super) e ao invocar mtodos private. Por exemplo, como nas classes Near e Far: class Near { int it; public int getItNear() { return getIt(); } private int getIt() { return it; } } class Far extends Near { int getItFar() { return super.getItNear(); } }

Arquitetura de Mquinas Virtuais

67

o mtodo Near.getItNear (que invoca um mtodo private) torna-se Mtodo int getItNear()
0 1 4 aload_0 invokespecial #5 ireturn // Method Near.getIt()I

o mtodo Far.getItFar (que invoca um mtodo dos superclass) torna-se Mtodo int getItFar()
0 1 4 aload_0 invokespecial #4 ireturn // Method Near.getItNear()I

Note que mtodos chamados usando a instruo invokespecial sempre passam this ao mtodo invocado como seu primeiro argumento. Sendo usual receber na varivel local 0.

8.7. Trabalhar com Instncias de Classe


Uma vez que uma instncia de classe foi criada e suas variveis instanciadas, incluindo as variveis de classe e todas de suas superclasses, estes assumiram valores padres e um mtodo de iniciao da instncia da classe (<init>) invocado. Lembre-se que no nvel da JVM, um construtor aparece como um mtodo com um nome especial fornecido pelo compilador - <init>. Este mtodo especial visto como o mtodo da iniciao do mtodo. Os mtodos de iniciao de mltiplas instncias, correspondentes aos construtores mltiplos, podem existir para uma dada classe. Exemplo: Object create() { return new Object(); } o cdigo compilado : Mtodo java.lang.Object create()
0 3 4 7 new #1 dup invokespecial #4 areturn // Class java.lang.Object // Method java.lang.Object.<init>()V

As instncias de classe so passadas e retornadas (como tipos referncia) como valores numricos, embora o tipo reference tenha seu prprio complemento de instrues: int i; // Uma instncia de varivel MyObj example() { MyObj o = new MyObj(); return silly(o); } MyObj silly(MyObj o) { if (o != null) { return o;

Arquitetura de Mquinas Virtuais

68

} else { return o; } } o cdigo compilado : Mtodo MyObj example()


0 3 4 7 8 9 10 13 new #2 dup invokespecial #5 astore_1 aload_0 aload_1 invokevirtual #4 areturn // Class MyObj // Method MyObj.<init>()V

// Method Example.silly(LMyObj;)LMyObj;

Mtodo MyObj silly(MyObj)


0 1 4 5 6 7 aload_1 ifnull 6 aload_1 areturn aload_1 areturn

Os campos de uma instncia de classe (variveis instanciadas) so acessados usando as instrues getfield e putfield. Se i for uma varivel instanciada do tipo int, os mtodos setIt e getIt, definidos como void setIt(int value) { i = value; } int getIt() { return i; } o cdigo compilado : Mtodo void setIt(int)
0 1 2 5 aload_0 iload_1 putfield #4 return // Field Example.i I

Mtodo int getIt()


0 1 4 aload_0 getfield #4 ireturn // Field Example.i I

Como operandos de instrues de invocao do mtodo, os operandos das instrues putfield e getfield (o ndice #4 do constant pool) no so deslocados nos campos da instncia da classe. O compilador gera referncias simblicas aos campos de uma instncia, que so armazenados no runtime

Arquitetura de Mquinas Virtuais

69

constant pool. Os itens do pool so resolvidos na hora para determinar o deslocamento real do campo.

8.8. Arrays
Os arrays na JVM so tambm objetos. Os arrays so criados e manipulados usando um conjunto distinto de instrues. A instruo newarray usada para criar um array do tipo numrico. O cdigo: void createBuffer() { int buffer[]; int bufsz = 100; int value = 12; buffer = new int[bufsz]; buffer[10] = value; value = buffer[11]; } o cdigo pode ser compilado: Mtodo void createBuffer()
0 2 3 5 6 7 9 10 11 13 14 15 16 18 19 20 bipush 100 istore_2 bipush 12 istore_3 Iload_2 newarray int astore_1 Aload_1 bipush 10 iload_3 iastore aload_1 bipush 11 iaload istore_3 return // empilha bufsz // armazena bufsz na varivel local 2 // empilha valor // armazena valor na varivel local 3 // empilha bufsz... //.. e cra um novo array de inteiros // armazena novo arrqy // empilha constante 10 // armazena i // armazena valor em buffer[10 ] // armazena i // empilha constante 11 // armazena valor em buffer[11 ] //... e armazena-o no valor

A instruo newarray usada para criar um array unidimensional de referncias do objeto: void createThreadArray() { Thread threads[]; int count = 10; threads = new Thread[count]; threads[0] = new Thread(); } o cdigo compilado : Mtodo void createThreadArray()
0 2 3 bipush 10 istore_2 iload_2 // Empilha 10... // ...e iniciliza contador // empilha contados, usado pelo newarray

Arquitetura de Mquinas Virtuais 4 7 8 9 10 13 14 17 18 anewarray class #1 astore_1 aload_1 iconst_0 new #1 dup invokespecial #5 aastore return // crier new array da classe Thread // armazena new array nas threads // armazena valor de threads na pilha // armazena 0 na pilha // cria instncia da classe Thread // faz duplicao de reference... // ...passa para o mtodo de inicializao // mtodo java.lang.Thread.<init>()V // armazena nova Thread no array at 0

70

A instruo newarray pode tambm ser usada criar a primeira dimenso de um array multidimensional. Alternativamente, a instruo multianewarray pode ser usada para criar diversas dimenses de uma vez. Por exemplo, o array tridimensional seguinte: int[][][] create3DArray() { int grid[][][]; grid = new int[10][5][]; return grid; } o cdigo compilado : Mtodo int create3DArray()[][][]
0 2 3 bipush 10 iconst_5 multianewarra y #1 dim #2 // empilha 10 (uma dimenso) // empilha 5 (duas dimenses) // classe [[[I, a three // dimenso do array; // somente cria primeiro e Segundo // dimenses // armazena novo array... // ...ento prepara retorno

7 8 9

astore_1 aload_1 areturn

O primeiro operando da instruo multianewarray o ndice do Runtime Constant Poolpara o tipo da classe array a ser criado. O segundo o nmero de dimenses desse tipo array a realmente ser criado. A instruo multianewarray pode ser usada para criar todas as dimenses do tipo, como mostra o cdigo para o mtodo create3DArray. Note que o array multidimensional apenas um objeto, que carregado e retornado por uma instruo de aload_1 e de areturn, respectivamente. Todas os arrays tm associados comprimentos, que so acessados atravs da instruo arraylength.

8.9. Compilando Switches


Compilao de switch usa as instrues tableswitch e lookupswitch. A instruo tableswitch usada quando as instncias de switch podem ser representadas como ndices em uma tabela de deslocamento. O default do switch usado se o valor da expresso switch cair fora da escala de ndices vlidos. Por exemplo,

int chooseNear(int i) {int chooseNear(int i) {

Arquitetura de Mquinas Virtuais

71

switch (i) { case 0: case 1: case 2: default: } } o cdigo compilado : Mtodo int chooseNear(int)
0 1 iload_1 tableswitch 0 to 2: 0: 28 1: 30 2: 32 default:34 iconst_0 ireturn iconst_1 ireturn iconst_2 ireturn iconst_m1 ireturn

return 0; return 1; return 2; return -1;

28 29 30 31 32 33 34 35

// armazena na varivel local 1 (argumento i) // indices vlidos so de 0 a 2 // se 0, continua em 28 // se 1, continua em 30 // se 2, continua em 32 // seno, continua em 34 // i 0; empilha int 0... // ...e retorna i // i 1; empilha int 1... // ...e retorna i // i 3; empilha int 2... // ...e retorna i // seno empilha -1... // ...e retorna i

As instrues tableswitch e lookupswitch da JVM operam somente sobre dados int, porque as operaes sobre byte char, ou short, os valores so promovidos internamente a int. Um switch, cuja expresso avalia um daqueles tipos, compilado como se fossem definidos int. Se o mtodo chooseNear fosse escrito usando o tipo short, as mesmas instrues JVM seriam geradas como quando usado o tipo int. Outros tipos numricos devem ser estreitados ao int para uso em um switch. Onde os casos de switch so escassos, a representao da tabela da instruo de instrues tableswitch torna-se ineficiente em termos de espao. A instruo lookupswitch pode ser usada preferivelmente. A instruo lookupswitch pareia as chaves (os valores case das etiquetas) com as posies na tabela. Quando uma instruo lookupswitch executada, o valor da expresso do switch comparado de encontro com s chaves na tabela. Se uma das chaves combinar o valor da expresso, a execuo continua no deslocamento associado. Se nenhuma chave combinar, a execuo continua como default. Por exemplo, o cdigo compilado para int chooseFar(int i) { switch (i) { caso -100: return -1; caso 0: return 0; caso 100: return 1; default: return -1; } } parece como o cdigo chooseNear, exceto pelo uso da instruo do lookupswitch:

Arquitetura de Mquinas Virtuais

72

Mtodo int chooseFar(int)


0 1 iload_1 lookupswitch 3: -100: 36 0: 38 100: 40 default:42 36 37 38 39 40 41 42 43 iconst_m1 ireturn iconst_0 ireturn iconst_1 ireturn const_m1 ireturn

A JVM especifica que a tabela da instruo lookupswitch deve ser classificada pela chave de modo que as execues possam usar as buscas mais eficientes a que uma varredura linear. Mesmo assim, a instruo lookupswitch deve procurar suas chaves por uma melhor associao que executa simplesmente uma verificao de limites e posiciona em uma tabela como tableswitch. Assim, uma instruo do tableswitch provavelmente mais eficiente do que um lookupswitch onde as consideraes do espao permitem escolha.

8.10. Operaes na Pilha de Operandos


A JVM tem um grande complemento de instrues que manipulam os ndices da pilha de operandos como valores sem tipo. Estes so teis por causa da importncia da JVM executar uma manipulao profunda de sua pilha do operando. Por exemplo: public long nextIndex() { return index++; } private long index = 0; o cdigo compilado : Mtodo long nextIndex()
0 1 2 5 6 7 8 11 aload_0 dup getfield #4 dup2_x1 lconst_1 ladd putfield #4 lreturn // esxreve this(0) na pilha de operando // faz cpia dele // uma das cpia de this consumida, armazena ndice na pilha acima de this // O long no topo da pilha inserido na pilha atravs do this // Um long 1 armazenado na pilha // O ndice incrementado // e o resultado armazendo no campo // O valor original do ndice deixado sobre o topo da pilha, para ser retornado

Note que a JVM nunca permite que suas instrues de manipulao da pilha de operandos modificar ou mover valores individuais pilha de operandos.

8.11. Manipulando Excees


As excees so lanadas em programas de Java atravs da palavra-chave throw. Sua

Arquitetura de Mquinas Virtuais

73

compilao simples: void cantBeZero(int i) throws TestExc { if (i == 0) { throw new TestExc(); } } o cdigo compilado : Mtodo void cantBeZero(int)
0 1 4 7 8 11 12 iload_1 ifne 12 new #1 dup invokespecial #7 athrow return // armazena argumento 1(i) na pilha // se i==0, localizar instncia e lanar // criar instncia de TestExc // uma referncia vai para o construtor // mtodo TestExc.<init>()V // segunda referncia lanada // nunca comece aqui se lanar TestExc

A Compilao de Java try-catch direto. Por exemplo: void catchOne() { try { tryItOut(); } catch (TestExc e) { handleExc(e); } } o cdigo compilado : Bloco void catchOne()
0 1 4 5 6 7 8 11 aload_0 #6 invokevirtual return astore_1 aload_0 aload_1 #5 invokevirtual return // incio do try do mtodo // mtodo Example.tryItOut()V // extremidade do bloco try; retorno normal // valor lanado armazenado na varivel local 1 // carrega this na pilha // valor lanado carregado na pilha // invocar o mtodo do alimentador: // exemplo.handleExc(LTestExc;)V // retorno aps a manipulao TestExc

Tabela da exceo:
De 0 A 4 Alvo 5 Tipo Classe TestExc

Olhando mais no detalhe, o bloco try compilado apenas como se no estivesse presente: Bloco void catchOne()
0 aload_0 1 #4 invokevirtual 4 return // incio do try do mtodo // mtodo Example.tryItOut()V // extremidade try do bloco; retorno do normal

Arquitetura de Mquinas Virtuais

74

Se nenhuma exceo for lanada durante a execuo do bloco try, o comportamento ser como se no houvesse try: tryItOut invocado e catchOne retorna. O bloco try a seguir o cdigo JVM que executa uma nica catch:
5 6 7 8 11 astore_1 aload_0 aload_1 #5 invokevirtual return // valor lanado armazenado na varivel local 1 // carrega this na pilha // valorlanado carregado na pilha // invoca o mtodo do alimentador: // exemplo.handleExc(LTestExc;)V // retorno aps a manipulao TestExc

Tabela da exceo: De 0 A 4 Alvo 5 Tipo Classe TestExc

A invocao de handleExc, tambm compilado como uma invocao normal do mtodo. Entretanto, a presena do catch faz com que o compilador gere uma entrada da tabela da exceo. A tabela de exceo para o mtodo catchOne tem uma entrada correspondente a um argumento (uma instncia da classe TestExc) que o catch de catchOne pode manipular. Se algum valor de que uma instncia de TestExc for lanado durante a execuo das instrues entre ndices 0 e 4 (inclusivo) de catchOne, o controle transferido ao cdigo JVM ndice 5, que executa o bloco catch. Se o valor que lanado no for uma instncia de TestExc, a clusula catch do catchOne no pode manipul-lo. Portanto, o valor re-lanado ao invocador de catchOne. O try pode ter clusulas catch mltiplas: void catchTwo() {void catchTwo() { try { tryItOut(); } catch (TestExc1 e) { handleExc(e); } catch (TestExc2 e) { handleExc(e); } } As clusulas mltiplas try-catch so compiladas por simplesmente adicionar ao cdigo JVM cada catch uma aps a outra, adicionando entradas tabela da exceo: Bloco void catchTwo()}
0 1 4 5 6 7 8 11 12 13 aload_0 #5 invokevirtual return astore_1 aload_0 aload_1 #7 invokevirtual return astore_1 aload_0 // incio do try do mtodo // mtodo Example.tryItOut()V / /extremidade try do bloco; retorno do normal // comeo do alimentador para TestExc1; // valor lanado armazenado na varivel local 1 // carrega this na pilha // valor lanado carregado na pilha // invoca o mtodo do alimentador: // exemplo.handleExc(LTestExc1;)V // retorno aps a manipulao TestExc1 // comeo do alimentador para TestExc2; // valorlanado armazendo na varivel local 1 // carrega this na pilha

Arquitetura de Mquinas Virtuais 14 15 18 aload_1 #7 invokevirtual return // valor lanado carregado na pilha // invoca o mtodo do alimentador: // exemplo.handleExc(LTestExc2;)V // retorno aps a manipulao TestExc2

75

Tabela da exceo: De A Alvo Tipo 4 5 Classe TestExc1 0 4 12 Classe TestExc2 0

Se durante a execuo da clusula try (entre os ndices 0 e 4) um valor lanado que combina a um ou mais catch dos blocos (o valor uma instncia de um ou de mais parmetros), o primeiro catch selecionado. O controle transferido JVM para o bloco dessa catch. Se o valor lanado no combinar o parmetro de algumas catch de catchTwo, a JVM relana o valor sem invocar o cdigo em alguma catch de catchTwo. Desta forma, try-catch so compiladas muito bem como uma indicao try e mltiplas clusulas catch: void nestedCatch() { try { try { tryItOut(); } catch (TestExc1 e) { handleExc1(e); } } catch (TestExc2 e) { handleExc2(e); } } o cdigo compilado : Bloco void nestedCatch()
0 1 4 5 6 7 8 11 12 13 14 15 18 aload_0 #8 invokevirtual return astore_1 aload_0 aload_1 #7 invokevirtual return astore_1 aload_0 aload_1 #6 invokevirtual return // incio do try do mtodo // mtodo Example.tryItOut()V // extremidade try do bloco; retorno do normal // comeo do alimentador para TestExc1; // valor lanado armazenado na varivel local 1 // carrega this na pilha // valor lanado carregado na pilha // invoca o mtodo do alimentador: // exemplo.handleExc1(LTestExc1;)V // retorno aps a manipulao TestExc1 // comeo do alimentador para TestExc2; // valor lanado armazenado na varivel local 1 // carrega this na pilha // valorlanado armazenado na pilha // invocar o mtodo do alimentador: // exemplo.handleExc2(LTestExc2;)V // retorno aps a manipulao TestExc2

Tabela da exceo:
De 0 A 4 Alvo 5 Tipo Classe TestExc1

Arquitetura de Mquinas Virtuais 0 12 12 Classe TestExc2

76

O catch representado somente na tabela da exceo. Quando uma exceo lanada, o primeiro catch que contm o local da exceo e com um parmetro combinando selecionado para segur-lo. Por exemplo, se a invocao de tryItOut (no ndice 1) lanou uma instncia de TestExc1, ele seria segurado pelo catch que invoca handleExc1. normal que a exceo ocorra dentro dos limites do catch exterior (executar TestExc2), e mesmo que esse catch exterior possa de outra maneira segurar o valor lanado.

8.12. Compilar finalmente


Compilao de um try-finally similar a do try-catch. Antes do controle ser transferido para fora do try, uma transferncia normal ou abrupta, porque uma exceo ser lanada, e a clusula finally pode j ter sido executada. Um exemplo simples: void tryFinally () { try { tryItOut(); } finally { wrapItUp(e); } } o cdigo compilado Bloco void tryFinally()
0 1 4 7 8 9 12 13 14 15 16 19 aload_0 #6 invokevirtual jsr 14 retorno astore_1 jsr 14 aload_1 athrow astore_2 aload_0 #5 invokevirtual retorno 2 // incio do try do mtodo / /mtodo Example.tryItOut()V // bloco finally da chamada // extremidade try do bloco // comeo do alimentador para algum throw // bloco finally da chamada // valor lanado // e relanado o valor ao invocador // comeo finally do bloco // carrega this na pilha // mtodo Example.wrapItUp()V // retorno do bloco finally

Tabela da exceo:
De 0 A 4 Alvo 8 Tipo alguns

H quatro maneiras para que o controle passe fora do try: caindo para o final desse bloco; retornando; executando um break ou continuando sua execuo; ou lanando uma exceo. Se os retornos tryItOut ocorrerem sem levantar uma exceo, o controle transferido ao bloco finally usando uma instruo do jsr. A instruo do jsr 14 no ndice 4 executa uma chamada de sub-rotina ao cdigo para o bloco finally no ndice 14 (o bloco finally compilado como uma sub-rotina encaixada). Quando o bloco finally termina, a instruo do ret 2 retorna o controle instruo seguinte. Mais detalhadamente, a chamada de sub-rotina trabalha da seguinte forma: A instruo jsr

Arquitetura de Mquinas Virtuais

77

empilha o endereo da instruo seguinte (retorno no ndice 7) na pilha de operandos antes de saltar. A instruo astore_2 que o alvo do salto armazena o endereo na pilha do operando na varivel local 2. O cdigo para o bloco finally (neste caso o aload_0 e as instrues invokevirtual) executando. Assume-se que a execuo desse cdigo termina normalmente, a instruo ret recupera o endereo da varivel local 2 e recomea a execuo nesse endereo. A instruo ret executada, e tryFinally retorna normalmente. Um try com finally compilado para ter um manipulador de exceo especial, um que pode manipular toda exceo lanada dentro de um try. Se tryItOut lana uma exceo, a tabela de exceo para tryFinally ie pesquisada por um manipulador apropriado de exceo. O manipulador especial encontrado, fazendo com que a execuo continue no ndice 8. A instruo astore_1 no ndice 8 armazena o valor lanado na varivel local 1. A seguinte instruo jsr faz uma chamada de sub-rotina ao cdigo do bloco finally. Supondo que o cdigo retorna normalmente, a instruo aload_1 no ndice 12 empilha o valor lanado para trs da pilha de operandos, e a seguinte instruo do athrow relana o valor. Compilar try com catch e finally mais complexo: void tryCatchFinally() { try { tryItOut(); } catch (TestExc e) { handleExc(e); } finally { wrapItUp(); } } o cdigo compilado
Bloco void tryCatchFinally() 0 aload_0 1 #4 invokevirtual 4 16 goto 7 astore_3 8 9 10 13 16 19 20 aload_0 aload_3 #6 invokevirtual 16 goto jsr 26 return astore_1 // incio do try do mtodo // mtodo Example.tryItOut()V // salto finally a obstruir // comeo do alimentador para TestExc; // valor lanado armazendo na varivel local 3 // armazena this na pilha // valor lanado na pilha // invoca mtodo do alimentador: // exemplo.handleExc(LTestExc;)V // bloco finally da chamada // retorno aps a manipulao TestExc // comeo do alimentador para excees // excepo de TestExc, ou excees // jlanado ao parar TestExc // bloco finally da chamada // valor jogado impulso, // e ralanado o valor ao invocador // comeo do bloco finally // armazena this na pilha // mtodo Example.wrapItUp()V

21 24 25 26 27 28 31

jsr 26 aload_1 athrow astore_2 aload_0 #5 invokevirtual return 2

// retorno do bloco finally

Arquitetura de Mquinas Virtuais

78

Tabela da exceo: De A Alvo Tipo 0 4 7 Classe TestExc 0 16 20 alguns

Se try terminar normalmente, a instruo goto no ndice 4 salta a chamada de sub-rotina para o bloco finally no ndice 16. O bloco finally no ndice 26 executado, o controle retorna instruo do retorno no ndice 19, e tryCatchFinally retorna normalmente. Se tryItOut lana uma instncia de TestExc, o primeiro manipulador aplicvel de exceo (innermost) na tabela da exceo escolhido para manipular a exceo. O cdigo para esse manipulador de exceo, comea no ndice 7, passa o valor lanado para handleExc, e em seu retorno faz a mesma chamada de sub-rotina ao bloco finally no ndice 26, como no caso normal. Se uma exceo no for lanada por handleExc, tryCatchFinally retorna normalmente. Se tryItOut lana um valor que no uma instncia TestExc, ou se o prprio handleExc lanar uma exceo, a condio manipular pela segunda entrada na tabela da exceo, que manipula qualquer valor lanado entre os ndices 0 e 16. Esse manipulador de exceo transfere o controle ao ndice 20, onde o valor lanado primeiramente armazenado na varivel local 1. O cdigo para o bloco finally no ndice 26 chamado como uma sub-rotina. Se retornar, o valor lanado recuperado da varivel local 1 e relana usando a instruo do athrow. Se um valor novo for lanado durante a execuo de finally, a clusula finally aborta e o tryCatchFinally retorna abruptamente, lanando o valor novo a seu invocador.

8.13. Sincronizao
A mquina virtual de Java fornece suporte explcito a sincronizao com suas instrues monitorenter e monitorexit. Para cigo escrito em Java entretanto, a maneira mais comum de sincronizao o mtodo synchronized. Um mtodo synchronized no executado normalmente usando o monitorenter e o monitorexit. distinguido simplesmente no pool de constante pelo ACC_SYNCHRONIZED, que verificada pelas instrues de invocao do mtodo. Ao invocar um mtodo em que ACC_SYNCHRONIZED selecionado, a thread atual adquire um monitor, invoca o mtodo prprio, e libera o monitor se o mtodo invocation termina normalmente ou abruptamente. Durante o tempo em que a thread possui o monitor, nenhuma outra thread pode adquiri-lo. Se uma exceo for lanada durante a invocao do mtodo synchronized, e o mtodo synchronized no segurar a exceo, o monitor para o mtodo est liberado automaticamente antes que a exceo seja relanada para fora do mtodo synchronized. As instrues monitorenter e do monitorexit existem para suportar synchronized. Por exemplo: void onlyMe(Foo f) { synchronized(f) { doSomething(); } } o cdigo compilado :
Mtodo void onlyMe(Foo) 0 aload_1 1 astore_2 2 aload_2 3 monitorenter 4 aload_0 5 #5 invokevirtual // armazena f na pilha de operandos // armazena-o na varivel local 2 // varivel local 2 da carga (f) na pilha // entre no monitor associado com f // que prende o monitor, passagem this e // chamada Example.doSomething()V

Arquitetura de Mquinas Virtuais 8 9 10 11 12 13 aload_2 monitorexit return aload_2 monitorexit athrow // varivel local 2 da carga (f) na pilha // sada que o monitor associou com f // retorno normalmente // caso que d lanamento, termina aqui acima // seja certo retirar o monitor, // ento relana o valor ao invocador Datilografe alguns

79

Tabela da exceo: De A Alveje a 4 8 11

9. Linhas de Execuo e Monitores


9.1. Sincronizao
Segundo Lindholm (1996) e Venners (1996, 2000), um monitor Java suporta dois tipos de sincronizao de linhas de execuo (threads): excluso mtua; cooperao.

A excluso mtua possibilita que mltiplas threads trabalhem independentemente com recursos e dados compartilhados sem interferirem entre si. Ela suportada na JVM atravs de locks de objetos. A cooperao possibilita que mltiplas threads trabalhem juntas em busca de um objetivo comum. Ela suportada na JVM atravs dos mtodos de espera (wait) e notificao (notify) da classe Object. Monitores so associados a dados e cdigos. Uma regio de monitor (monitor region) cdigo que necessita ser executado como uma operao indivisvel, ou seja, uma thread deve ser capaz de executar uma regio de monitor do incio ao fim sem que outra thread concorrentemente execute uma regio de monitor do mesmo monitor. A nica maneira de uma thread conseguir entrar em um monitor pela chegada no incio de uma das regies de monitor associadas ao monitor. E, a nica maneira de uma thread conseguir executar uma regio de monitor pela aquisio do monitor. Quando uma thread chega no incio de uma regio de monitor, ela colocada em um conjunto de entrada para o monitor associado. Se nenhuma outra thread estiver esperando no conjunto de entrada, e nenhuma thread tem a posse do monitor, a thread adquire o monitor e continua executando a regio de monitor. Quando ela finaliza a execuo da regio de monitor, ela sai e libera o monitor. Entretanto, caso uma thread chegue no incio de uma regio de monitor que est protegida por um monitor j possudo por outra thread, a thread deve esperar no conjunto de entrada. Quando a thread que possui o monitor sai, a nova thread deve competir com quaisquer outras threads que tambm estiverem esperando no conjunto de entrada. Apenas uma thread vencer a competio e adquirir o monitor. A primeira forma de sincronizao (excluso mtua) refere execuo de regies de monitor por threads mltiplas de forma mutuamente exclusiva. Em qualquer instante, apenas uma thread pode estar executando uma regio de monitor de um monitor, sendo importante quando threads mltiplas esto compartilhando dados e outros recursos. Se duas threads no esto trabalhando com dados ou recursos comuns, elas no podem interferir entre si e, portanto, no necessrio que executem em um modo mutuamente exclusivo. Entretanto, mesmo em uma implementao JVM que no fatia o tempo (time slice), uma threads de mais alta prioridade que nunca bloqueada interferir com quaisquer threads de prioridade mais baixa, mesmo que nenhuma thread compartilhe dados. A thread de maior prioridade monopolizar o processador, e as de prioridade menores nunca obtero tempo de processador (CPU time). Nesse caso, um monitor

Arquitetura de Mquinas Virtuais

80

que no protege dados pode ser utilizado para coordenar essas threads para garantir que todas obtenham algum tempo de CPU. Apesar disso, na maior parte dos casos um monitor protege dados que so acessados atravs de regies de monitor. Em casos onde os dados podem ser acessados apenas atravs de regies de monitor, o monitor estabelece acesso mutuamente exclusivo aos dados. A outra forma de sincronizao suportada por monitores na JVM a cooperao. Enquanto a excluso mtua impede que threads interfiram na execuo de outras quando estas compartilham dados e recursos, a cooperao auxilia as threads a trabalharem por um objetivo comum. A cooperao importante quando uma thread necessita que alguns dados estejam em estados particulares, e outra thread responsvel por conduzir os dados para tais estados. Por exemplo, uma thread de leitura pode estar lendo um buffer que uma thread de escrita est preenchendo. A thread de leitura precisa que o buffer no esteja no estado vazio antes que ela inicie sua atividade, caso contrrio ela ter que esperar. A thread de escrita responsvel por entrar com os dados no buffer, de forma que, uma vez que ela tenha executado sua atividade, a thread de leitura poder executar sua atividade. O tipo de monitor empregado pela JVM chamado de Espera e Notifica (Wait and Notify) ou Sinaliza e Continua (Signal and Continue). Nesse tipo de monitor, uma thread que possui o monitor pode suspender a si prpria dentro do monitor executando um comando wait. Ao executar um wait a thread libera o monitor e entra em um conjunto de espera. Ela permanecer suspensa no conjunto de espera at que outra execute um comando notify no monitor. Quando uma thread executa um notify, ela continua com a posse do monitor at que ela o libere por meio de um wait ou completando a regio de monitor. Aps a thread que executou o notify liberar o monitor, a thread que estava no conjunto de espera ir ressuscitar e readquirir o monitor. O segundo nome, Sinaliza e Continua, utilizado, pois, aps uma thread executar um comando notify (Sinaliza), ela mantm posse do monitor e continua executando a regio de monitor (Continua). Aps algum tempo a thread libera A figura abaixo demonstra o tipo de monitor utilizado por uma JVM. Ela mostra o monitor como trs retngulos; no centro, um retngulo mais largo contm uma thread, o proprietrio do monitor. Na esquerda, um retngulo pequeno contm o conjunto de entrada. Na direita, outro retngulo pequeno contm o conjunto de espera. As threads ativas so mostradas como crculos cinza escuro. As threads suspendidas so mostradas como crculos cinza claro.

Figura: um monitor Java. Fonte: Venners (2000).

Na figura so mostradas as diversas portas numeradas atravs das quais threads devem passar.

Arquitetura de Mquinas Virtuais

81

Quando uma thread chega no incio de uma regio de monitor, ela entra no monitor atravs da porta de nmero 1, e encontra-se no retngulo que hospeda o conjunto de entrada. Se nenhuma thread correntemente possui o monitor e nenhuma outra est esperando no conjunto de entrada, a thread passa imediatamente atravs da porta de nmero 2, e torna-se a proprietria do monitor. Como proprietria, a thread continua executando a regio de monitor. Se, por outro lado, existe outra thread reivindicando a posse do monitor, a nova thread dever esperar no conjunto de entrada, possivelmente juntamente com outras threads que j estavam esperando no conjunto de entrada. A nova thread no conjunto de entrada bloqueada e, portanto, no executa qualquer atividade na regio de monitor. A figura mostra trs threads suspensas no conjunto de entrada e quatro no conjunto de espera. Essas threads permanecero onde estiverem at que o proprietrio do monitor o libere. Para liberar o monitor, a thread deve completar a regio de monitor que ela est executando, saindo pela porta nmero 5, ou, executar um comando wait, saindo pela porta de nmero 3. Caso a thread que possui o monitor no execute um notify antes de liberar o monitor, e nenhuma das threads de espera foi notificada e est esperando para ser ressuscitada, ento somente as threads no conjunto de entrada competiro pela aquisio do monitor. Caso contrrio, as threads do conjunto de entrada tero que competir com threads do conjunto de espera. Se uma threads do conjunto de entrada vence a competio, ela passa atravs da porta 2 e torna-se a nova proprietria do monitor. Se uma thread do conjunto de espera vence a competio, ela sai do conjunto e readquire o monitor conforme passa atravs da porta de nmero 4. Threads no podem sair do conjunto de espera sem automaticamente tornarem-se novamente proprietrias do monitor. Na JVM, threads podem, opcionalmente, especificar um timeout quando elas executam um comando wait. Se uma thread especificar um timeout, e nenhuma outra thread executar um notify antes do timeout expirar, a thread de espera recebe uma notificao automtica da mquina virtual. Aps o timeout expirar, a thread de espera ser ressuscitada. A JVM prov dois tipos de comandos de notificao: notify e notify all. Um comando notify seleciona uma thread arbitrria do conjunto de espera e a marca para eventual ressurreio. Um comando notify all marca todas as threads correntemente no conjunto de espera para eventual ressurreio. O critrio da JVM para seleo da prxima thread dos conjuntos de espera e entrada pode ser decidido por implementadores de JVM. Alm disso, dentre as flexibilidades da especificao de JVM, tambm podemos citar o modo de escolha: de uma thread do conjunto de espera aps a execuo de um comando notify; da ordem de ressurreio de threads do conjunto de espera aps a execuo de um comando notify all; da ordem de permisso de aquisio do monitor a threads do conjunto de entrada; de uma entre as threads suspendidas no conjunto de espera contra o conjunto de entrada aps a execuo de um comando notify. A escolha do modo de implementao dos conjuntos de entrada e espera depende das necessidades de projeto. Implementaes JVM podem utilizar filas (FIFO), filas de prioridade, pilhas (LIFO), ou qualquer outro esquema de seleo. O emprego de algoritmos de seleo e tratamento de prioridades deve sempre considerar questes de espera circular (deadlock) e espera infinita (starvation).

9.2. Travamento de Objetos


Algumas das reas de dados de tempo de execuo da JVM so compartilhadas entre todas as threads, enquanto outras so privadas a threads individuais. Como a heap e a rea de mtodo so compartilhadas por todas as threads, necessrio

Arquitetura de Mquinas Virtuais

82

coordenar acesso de mltiplas threads a dois tipos de dados: variveis de instncia, que so armazenadas na heap; variveis de classe, que so armazenadas na rea de mtodo.

A coordenao de acesso a variveis locais, que residem ns pilhas Java no necessria, pois, dados nas pilhas so privados thread a qual a pilha pertence. Em uma mquina virtual, todo objeto e classe esto logicamente associados com um monitor. Para objetos, o monitor associado protege as variveis de instncia do objeto. E, para classes, o monitor associado protege as variveis de classe da classe em questo. Se um objeto no possui variveis de instncia, ele continuar tendo um monitor associado, que, entretanto no proteger dados. Para implementar a capacidade de excluso mtua de monitores, a JVM associa uma trava (lock), tambm conhecida como mutex ou token, a cada objeto e classe. Uma trava como um privilgio que apenas uma thread pode possuir em cada instante. As threads no precisam obter uma trava para acessar variveis de instncia ou de classe. Se uma thread obtm uma trava, ento nenhuma outra poder obter outra trava no mesmo item at que a thread que obteve uma trava antes a libere. O travamento de classes realizado da mesma forma que o travamento de objetos. Quando a JVM carrega um arquivo de classe, ela cria uma instncia da classe Class. Dessa forma, o travamento de uma classe, de fato trata-se do travamento do objeto da classe Class associado. Uma thread na JVM faz uma requisio de travamento quando ela chega no incio de uma regio de monitor. Dois tipos de regies de monitor so empregados: comandos sincronizados e mtodos sincronizados. Cada regio de monitor est associada com uma referncia de objeto. Quando uma thread chega na primeira instruo de uma regio de monitor, ela pode obter uma trava no objeto referenciado. A thread no poder executar o cdigo at obter a trava. Uma vez que ela tenha obtido a trava, ela entra no bloco de cdigo protegido. Quando a thread sai do bloco, ela libera a trava no objeto associado. O programador Java nunca trava explicitamente um objeto. Essa atividade interna JVM. Em um programa as regies de monitor so identificadas por meio da escrita de comando e mtodos sincronizados. Quando a JVM executa o programa, ela automaticamente trava um objeto ou classe sempre que encontrar uma regio de monitor.

9.3. Suporte no Conjunto de Instrues


Para identificar regies de monitor, a linguagem Java proporciona duas maneiras: comandos e mtodos sincronizados. Esses mecanismos, que implementam o aspecto de excluso mtua da sincronizao, so suportados pelo conjunto de instrues da JVM. 9.3.1. Comandos Sincronizados No caso de comandos sincronizados, os comandos contidos em um bloco sincronizado (definido na linguagem Java por meio da palavra chave synchronized) no so executados at que uma trava seja adquirida. A trava pode ser adquirida no objeto corrente, ou em um objeto referenciado, caso o parmetro de sincronizao corresponda a uma referncia a outro objeto, ou ainda em uma classe, caso uma a referncia seja para uma instncia da classe Class. Dois opcodes, monitorenter and monitorexit, so utilizados para blocos de sincronizao dentro de mtodos:

Arquitetura de Mquinas Virtuais

83

a instruo monitorenter desempilha um valor objectref, e adquiri a trava associada com o objeto referenciado pelo valor (objectref) desempilhado; a instruo monitorexit desempilha um valor objectref, e libera a trava associada com o objeto referenciado pelo valor (objectref) desempilhado.

Quando a JVM encontra uma instruo com o opcode monitorenter, ela obtm a trava para o objeto referenciado por objectref na pilha. Se a thread j possui uma trava para o objeto, um contador associado trava incrementado. Cada vez que uma instruo monitorexit executada para a thread no objeto, o contador e decrementado, e quando o contador alcana zero, o monitor liberado. 9.3.2. Mtodos Sincronizados Para sincronizar um mtodo completo, necessrio incluir a palavra chave synchronized como um dos qualificadores do mtodo na linguagem de programao Java. A mquina virtual Java no utiliza qualquer opcode especial para invocar ou retornar de mtodos sincronizados. Quando a JVM resolve a referencia simblica para um mtodo, ela determina se o mtodo sincronizado. Caso se trate de um mtodo sincronizado, a JVM adquiri uma trava antes de invocar o mtodo. Para um mtodo de instncia, a JVM adquire a trava associada com o objeto no qual o mtodo est sendo invocado. Para um mtodo de classe, a JVM adquire a trava associada com a classe qual o mtodo pertence (ela trava o objeto Class apropriado). Quando um mtodo sincronizado termina, seja retornando ou disparando uma exceo, a mquina virtual Java libera a trava.

Arquitetura de Mquinas Virtuais

84

10. Referncias Bibliogrficas


FUJITSU. PicoJava-II Specification, 199-. Disponvel em: <http://www.fujitsu.com/global/services/microelectronics/product/micom/java/picospec/> GORDON, A; SYME, D. Typing a Multi-Language Intermediate Code. In: Proceedings POPL01, 248260, 2001. GOUGH, J. Parameter Passing for the Java Virtual Machine. In: Proceedings of the Australasian Computer Science Conference, 1998. GOUGH, J. Stacking Them Up: A Comparison of Virtual Machines. In: Proceedings ACSAC 2001, 5561. IEEE Computer Society, 2001. GOUGH, J; CORNEY, D. Evaluating the Java Virtual Machine as a Target for Languages other than Java. In: Proceedings Joint Modula Languages Conference, 2000. HP. Fast VM Architecture. Disponvel em: <http://www.hp.com/java/performance/FastVM.html>. KAFFE. Kaffe Archietcture Report. Disponvel em: <http://www.kaffe.org>. KENNEDY, A; SYME, D. Design and Implementation of Generics for the .NET Common Language Runtime. In: Proceedings PLDI01, 2001. LATTE. Latte: An Open-Source Java Virtual Machine and Just-in-Time Compiler. Disponvel em: <http://latte.snu.ac.kr/>. LINDHOLM, T; YELLIN, F. Java Virtual Machine Specification. Addison-Wesley. 2. ed. 1996. MEYER, J; DOWNING, T. Java Virtual Machine. O'Reilly. 1. ed. 1997. MEIJER, E. Technical Overview of the Common Language Runtime. Brisbane, Australia, 2001. Disponvel em: <http://research.microsoft.com/~emeijer/Papers/CLR.pdf>. MICROSOFT. CLI Specification. ECMA TG3. 2001. Disponvel em: <http://msdn.microsoft.com/net/ecma/>. PERL FOUNDATION. Parrot Code Virtual Machine. Disponvel em: <http://www.parrotcode.org>. PILLA. A Microarquitetura picoJava-II, Brasil, 1999. Disponvel em: <http://www.inf.ufrgs.br/procpar/disc/cmp135/trabs/992/picoJava/node1.html> SILVA. JVM Java Virtual Machine. SHIEL, S; BAYLEY, I. A Translation-Facilitated Comparison between the Common Language Runtime and the JavaVirtual Machine. Oxford Brooks. 2005. SUN. PicoJava-II Programmers Reference Manual. Sun Microsystems Inc. 1999. Disponvel em: <http://solutions.sun.com/embedded/databook/pdf/manuals/805-2800-06.pdf>.

Arquitetura de Mquinas Virtuais

85

SUN. The Java HotSpot Virtual Machine. Technical White Paper. Sun Microsystems. 2001. Disponvel em: <http://java.sun.com/docs/white/>. TOLKSDORF, R. Programming Languages for the Java Virtual Machine. Disponvel em: <http://grunge.cs.tuberlin.de/tolk/vmlanguages.html>. VENNERS, B. Inside the Java Virtual Machine. McGraw-Hill. 2. ed. 2000. VENNERS, B. Under the Hood. Java World On-Line Magazine. 1996. Disponvel em: <http://www.javaworld.com/javaworld/jw-12-1997/jw-12-hood.html>.

Arquitetura de Mquinas Virtuais

86

Apndice A.

Conjunto de Instrues JVM Completo

Este Apndice contm a completa arquitetura do conjunto de instrues da JVM, com o objetivo de exemplificar um conjunto de instrues de uma mquina virtual. O conjunto da JVM foi escolhido pelo fato de a JVM ser de certa forma uma referncia para as mquinas virtuais existentes, tendo se baseado nos conceitos genricos subjacentes de mquina virtual, estendendo-os para suportar o paradigma da orientao por objetos. Por isso, grande parte das implementaes de mquinas virtuais comtemporneas baseia-se na JVM. As instrues JVM representadas neste Apndice seguem o formato de descrio de instruo, indicado na JVM Specification (Lindholm, 1996), e apresentado a seguir: mnemnico Operao Formato Opcode Pilha

Descrio da instruo mnemnico operando1 operando2 opcode ..., valor1, valor2 -> ..., valor3

Cada campo do formato representa um byte. O mnemnico o nome da instruo. O opcode a representao numrica da instruo, sendo que, apenas a representao numrica est de fato presente no cdigo JVM em um arquivo de classe. Deve-se atentar para o fato de que h operandos gerados em tempo de compilao e embutidos em instrues JVM, bem como, operandos calculados em tempo de execuo e supridos na pilha de operandoss. Apesar de poderem ser supridos de diversas reas, todos esses operandos representam valores a serem operados pela instruo JVM sendo executada. Ao obter implicitamente muitos de seus operandos a partir de sua pilha de operandos, ao invs de represent-los explicitamente em seu cdigo compilado como bytes de operandos adicionais, nmeros de registradores, dentre outros, o cdigo JVM fica compacto. Algumas instrues constituem membros de uma famlia de instrues relacionadas. Nesse caso, somente o mnemnico da famlia aparece no formato de instruo, sendo listados todos os opcodes dos membros da famlia. Os efeitos de uma execuo de instruo na pilha de operandos so representados textualmente, com a pilha crescendo da esquerda para a direita e cada valor representado separadamente, de forma que a representao: ..., valor1, valor2 -> ..., valor3, mostra uma operao que comea tendo o valor2 no topo da pilha com o valor1 logo abaixo. Como resultado da execuo da instruo, ambos os valores so desempilhados. O valor3 resultante, que foi calculado pela instruo, empilhado. O restante da pilha, representado por ... no afetado pela execuo da instruo em questo.

Instrues JVM
As instrues JVM so listadas a seguir: aaload Operao Formato Opcode Pilha

Carrega reference do array aaload 50 (0x32) ..., arrayref, index -> ..., value

Arquitetura de Mquinas Virtuais

87

aastore Operao Formato Opcode Pilha aconst_null Operao Formato Opcode Pilha aload Operao Formato Opcode Pilha aload_<n> Operao Formato Opcode

Armazena reference no array aastore 83 (0x53) ..., arrayref, index -> ..., value

Empilha null aconst_null 1 (0x1) ... -> ..., null

Carrega reference da varivel local aload 25 (0x19) ... -> ..., objectref

Pilha anewarray Operao Formato Opcode Pilha areturn Operao Formato Opcode Pilha arraylength Operao Formato

Carrega reference da varivel local. <n> deve ser um ndice para o array de variveis locais do quadro corrente. aload_<n> aload_0 = 42 (0x2a) aload_1 = 43 (0x2b) aload_2 = 44 (0x2c) aload_3 = 45 (0x2d) ... -> ..., objectref

Cria novo array de reference anewarray indexbyte1 indexbyte2 189 (0xbd) ..., count -> ..., arrayref

Retorna reference do mtodo areturn 176 (0xb0) ... -> objectref [empty]

Obtm tamanho do array arraylength

Arquitetura de Mquinas Virtuais

88

Opcode Pilha astore Operao Formato Opcode Pilha astore_<n> Operao Formato Opcode

190 (0xbe) ..., arrayref -> ..., length

Armazena reference na varivel local astore 58 (0x3a) ..., objectref -> ...

Pilha athrow Operao Formato Opcode Pilha baload Operao Formato Opcode Pilha bastore Operao Formato Opcode Pilha bipush Operao Formato Opcode Pilha caload

Armazena reference na varivel local. <n> deve ser um ndice para o array de variveis locais do quadro corrente. astore_<n> astore_0 = 75 (0x4b) astore_1 = 76 (0x4c) astore_2 = 77 (0x4d) astore_3 = 78 (0x4e) ..., objectref -> ...

Dispara exceo athrow 191 (0xbf) ..., objectref -> objectref

Carrega byte ou boolean do array baload 51 (0x33) ..., arrayref, index -> ..., value

Armazena byte ou boolean no array bastore 84 (0x54) ..., arrayref, index -> ..., value

Empilha byte bipush byte 16 (0x10) ... -> ..., value

Arquitetura de Mquinas Virtuais

89

Operao Formato Opcode Pilha castore Operao Formato Opcode Pilha checkcast Operao Formato Opcode Pilha d2f Operao Formato Opcode Pilha d2i Operao Formato Opcode Pilha d2l Operao Formato Opcode Pilha dadd Operao Formato Opcode Pilha daload Operao

Carrega char do array caload 52 (0x34) ..., arrayref, index -> ..., value

Armazena char no array castore 85 (0x55) ..., arrayref, index -> ..., value

Checa se objeto do tipo determinado checkcast indexbyte1 indexbyte2 192 (0xc0) ..., objectref -> ..., objectref

Converte double para float d2f 144 (0x90) ..., value -> ..., result

Converte double para int d2i 142 (0x8e) ..., value -> ..., result

Converte double para long d2l 143 (0x8f) ..., value -> ..., result

Adiciona double dadd 99 (0x63) ..., value1, value2 -> ..., result

Carrega doble do array

Arquitetura de Mquinas Virtuais

90

Formato Opcode Pilha dastore Operao Formato Opcode Pilha dcmp<op> Operao Formato Opcode Pilha dconst_<d> Operao Formato Opcode Pilha ddiv Operao Formato Opcode Pilha dload Operao Formato Opcode Pilha dload_<n> Operao Formato Opcode

daload 49 (0x31) ..., arrayref, index -> ..., value

Armazena double no array dastore 82 (0x52) ..., arrayref, index, value -> ...

Compara double. Se um dos valores um NaN (NotANumber), dcmpg empilha 1 e dcmpl -1. dcmp<op> dcmpg = 152 (0x98) dcmpl = 151 (0x97) ..., value1, value2 -> ..., result

Empilha constante double <d> (0.0 ou 1.0) dconst_<d> dconst_0 = 14 (0xe) dconst_1 = 15 (0xf) ..., -> ..., <d>

Divide double ddiv 111 (0x6f) ..., value1, value2 -> ..., result

Carrega double da varivel local dload index 24 (0x18) ... -> ..., value

Carrega double da varivel local. <n> deve ser um ndice para o array de variveis locais do quadro corrente. dload_<n> dload_0 = 38 (0x26) dload_1 = 39 (0x27) dload_2 = 40 (0x28) dload_3 = 41 (0x29)

Arquitetura de Mquinas Virtuais

91

Pilha dmul Operao Formato Opcode Pilha dneg Operao Formato Opcode Pilha drem Operao Formato Opcode Pilha dreturn Operao Formato Opcode Pilha dstore Operao Formato Opcode Pilha dstore_<n> Operao Formato Opcode

... -> ..., value

Multiplica double dmul 107 (0x6b) ..., value1, value2 -> ..., result

Nega double dneg 119 (0x77) ..., value -> ..., result

Calcula o resto de diviso de double drem 115 (0x73) ..., value1, value2 -> ..., result

Retorna double do mtodo dreturn 175 (0xaf) ..., value -> [empty]

Armazena double na varivel local dstore index 57 (0x39) ..., value -> ...

Pilha dsub Operao

Armazena double na varivel local. <n> deve ser um ndice para o array de variveis locais do quadro corrente. dstore_<n> dstore_0 = 71 (0x47) dstore_1 = 72 (0x48) dstore_2 = 73 (0x49) dstore_3 = 74 (0x4a) ..., value -> ...

Subtrai double

Arquitetura de Mquinas Virtuais

92

Formato Opcode Pilha dup Operao Formato Opcode Pilha dup_x1 Operao Formato Opcode Pilha dup_x2 Operao Formato Opcode Pilha dup_2 Operao Formato Opcode Pilha dup2_x1 Operao Formato Opcode Pilha

dsub 103 (0x67) ..., value1, value2 -> ..., result

Duplica topo da pilha dup 89 (0x59) ..., value -> ... , value, value

Duplica topo da pilha e insere o valor duplicado duas posies abaixo do topo da pilha dup_x1 90 (0x5a) ..., value2, value1 -> ..., value1, value2, value1

Duplica topo da pilha e insere o valor duplicado duas (forma 2) ou trs (forma 1) posies abaixo do topo da pilha. Insere a duas posies do topo se um dos valores do tipo long ou double. dup_x2 91 (0x5b) Forma 1: ..., value3, value2, value1 -> ..., value1, value3, value2, value1 Forma 2: ..., value2, value1 -> ..., value1, value2, value1

Duplica um (forma 2) ou dois (forma 1) valores do topo da pilha. Duplica um se o valor do tipo long ou double. dup_2 92 (0x5c) Forma 1: ..., value2, value1 -> ..., value2, value1, value2, value1 Forma 2: ..., value -> ..., value, value

Duplica um (forma 2) ou dois (forma 1) valores do topo da pilha e insere o valor duplicado duas ou trs posies abaixo do topo da pilha. Duplica um e insere a duas posies do topo se o valor do tipo long ou double. dup2_x1 93 (0x5d) Forma 1: ..., value3, value2, value1 -> ..., value2, value1, value3, value2, value1 Forma 2: ..., value2, value1 -> ..., value1, value2, value1

dup2_x2

Arquitetura de Mquinas Virtuais

93

Operao

Formato Opcode Pilha

Duplica um (forma 2 e 4) ou dois (forma 1 e 3) valores do topo da pilha e insere o valor duplicado duas, trs ou quatro posies abaixo do topo da pilha. Assume a forma 2 se um dos valores dos dois valores do topo da pilha do tipo long ou double e a forma 4 se os dois valores so do tipo long ou double. dup2_x2 94 (0x5e) Forma 1: ..., value4, value3, value2, value1 -> ..., value2, value1, value4, value3, value2, value1 Forma 2: ..., value3, value2, value1 -> ..., value1, value3, value2, value1 Forma 3: ..., value3, value2, value1 -> ..., value2, value1, value3, value2, value1 Forma 4: ..., value2, value1 -> ..., value1, value2, value1

f2d Operao Formato Opcode Pilha f2i Operao Formato Opcode Pilha f2l Operao Formato Opcode Pilha fadd Operao Formato Opcode Pilha faload Operao Formato Opcode Pilha fastore

Converte float para double f2d 141 (0x8d) ..., value -> ..., result

Converte float para int f2i 139 (0x8b) ..., value -> ..., result

Converte float para long f2l 140 (0x8c) ..., value -> ..., result

Adiciona float fadd 98 (0x62) ..., value1, value2 -> ..., result

Carrega float do array faload 48 (0x30) ..., arrayref, index -> ..., value

Arquitetura de Mquinas Virtuais

94

Operao Formato Opcode Pilha fcmp<op> Operao Formato Opcode Pilha fconst_<f> Operao Formato Opcode Pilha fdiv Operao Formato Opcode Pilha fload Operao Formato Opcode Pilha fload_<n> Operao Formato Opcode

Armazena float no array fastore 81 (0x51) ..., arrayref, index, value -> ...

Compara float. Se um dos valores um NaN (NotANumber), fcmpg empilha 1 e fcmpl -1. fcmp<op> fcmpg = 150 (0x96) fcmpl = 149 (0x95) ..., value1, value2 -> ..., result

Empilha constante float <f> (0.0, 1.0 ou 2.0) fconst_<f> fconst_0 = 11 (0xb) fconst_1 = 12 (0xc) fconst_2 = 13 (0xd) ..., -> ..., <f>

Divide float fdiv 110 (0x6e) ..., value1, value2 -> ..., result

Carrega float da varivel local fload index 23 (0x17) ... -> ..., value

Pilha fmul Operao

Carrega float da varivel local. <n> deve ser um ndice para o array de variveis locais do quadro corrente. fload_<n> fload_0 = 34 (0x22) fload_1 = 35 (0x23) fload_2 = 36 (0x24) fload_3 = 37 (0x25) ... -> ..., value

Multiplica float

Arquitetura de Mquinas Virtuais

95

Formato Opcode Pilha fneg Operao Formato Opcode Pilha frem Operao Formato Opcode Pilha freturn Operao Formato Opcode Pilha fstore Operao Formato Opcode Pilha fstore_<n> Operao Formato Opcode

fmul 106 (0x6a) ..., value1, value2 -> ..., result

Nega float fneg 118 (0x76) ..., value -> ..., result

Calcula o resto de diviso de float frem 114 (0x72) ..., value1, value2 -> ..., result

Retorna float do mtodo freturn 114 (0x72) ..., value -> [empty]

Armazena float na varivel local dstore index 56 (0x38) ..., value -> ...

Pilha fsub Operao Formato Opcode Pilha

Armazena float na varivel local. <n> deve ser um ndice para o array de variveis locais do quadro corrente. fstore_<n> fstore_0 = 67 (0x43) fstore_1 = 68 (0x44) fstore_2 = 69 (0x45) fstore_3 = 70 (0x46) ..., value -> ...

Subtrai float fsub 102 (0x66) ..., value1, value2 -> ..., result

Arquitetura de Mquinas Virtuais

96

getfield Operao Formato Opcode Pilha getstatic Operao Formato Opcode Pilha goto Operao Formato Opcode Pilha goto_w Operao Formato Opcode Pilha i2b Operao Formato Opcode Pilha i2c Operao Formato Opcode Pilha i2d Operao Formato Opcode Pilha i2f

Obtm campo de objeto getfield indexbyte1 indexbyte2 180 (0xb4) ..., objectref -> ..., value

Obtm campo esttico de classe getstatic indexbyte1 indexbyte2 178 (0xb2) ... -> ..., value

Desvia incondicionalmente goto branchbyte1 branchbyte2 167 (0xa7) Nenhuma alterao

Desvia incondicionalmente (ndice amplo) goto_w branchbyte1 branchbyte2 branchbyte3 branchbyte4 200 (0xc8) Nenhuma alterao

Converte int para byte i2b 145 (0x91) ..., value -> ..., result

Converte int para char i2c 146 (0x92) ..., value -> ..., result

Converte int para double i2d 135 (0x87) ..., value -> ..., result

Arquitetura de Mquinas Virtuais

97

Operao Formato Opcode Pilha i2l Operao Formato Opcode Pilha i2s Operao Formato Opcode Pilha iadd Operao Formato Opcode Pilha iaload Operao Formato Opcode Pilha iand Operao Formato Opcode Pilha iastore Operao Formato Opcode Pilha iconst_<i> Operao

Converte int para float i2f 134 (0x86) ..., value -> ..., result

Converte int para long i2l 133 (0x85) ..., value -> ..., result

Converte int para short i2s 147 (0x93) ..., value -> ..., result

Adiciona int iadd 96 (0x60) ..., value1, value2 -> ..., result

Carrega int do array iaload 46 (0x2e) ..., arrayref, index -> ..., value

AND booleano int iand 126 (0x7e) ..., value1, value2 -> ..., result

Armazena int no array iastore 79 (0x4f) ..., arrayref, index, value -> ...

Empilha constante int <i> (-1, 0, 1, 2, 3, 4 ou 5)

Arquitetura de Mquinas Virtuais

98

Formato Opcode

Pilha idiv Operao Formato Opcode Pilha if_acmp<cond> Operao Formato Opcode Pilha if_icmp<cond> Operao Formato Opcode

iconst_<i> iconst_m1 = 2 (0x2) iconst_0 = 3 (0x3) iconst_1 = 4 (0x4) iconst_2 = 5 (0x5) iconst_3 = 6 (0x6) iconst_4 = 7 (0x7) iconst_5 = 8 (0x8) ..., -> ..., <i>

Divide int idiv 108 (0x6c) ..., value1, value2 -> ..., result

Desvia se comparao de reference obtm sucesso if_acmp<cond> branchbyte1 branchbyte2 if_acmpeq = 165 (0xa5) if_acmpne = 166 (0xa6) ..., value1, value2 -> ...

Pilha if<cond> Operao Formato Opcode

Desvia se comparao de int obtm sucesso if_icmp<cond> branchbyte1 branchbyte2 if_icmpeq = 159 (0x9f) if_icmpne = 160 (0xa0) if_icmplt = 161 (0xa1) if_icmpge = 162 (0xa2) if_icmpgt = 163 (0xa3) if_icmple = 164 (0xa4) ..., value1, value2 -> ...

Pilha ifnonnull

Desvia se comparao de int e zero obtm sucesso if<cond> branchbyte1 branchbyte2 ifeq = 153 (0x99) ifne = 154 (0x9a) iflt = 155 (0x9b) ifge = 156 (0x9c) ifgt = 157 (0x9d) ifle = 158 (0x9e) ..., value -> ...

Arquitetura de Mquinas Virtuais

99

Operao Formato Opcode Pilha ifnull Operao Formato Opcode Pilha iinc Operao Formato Opcode Pilha iload Operao Formato Opcode Pilha iload_<n> Operao Formato Opcode

Desvia se reference no nula ifnonnull branchbyte1 branchbyte2 199 (0xc7) ..., value -> ...

Desvia se reference nula ifnull branchbyte1 branchbyte2 198 (0xc6) ..., value -> ...

Incrementa varivel local com constante iinc index const 132 (0x84) Nenhuma alterao

Carrega int da varivel local iload index 21 (0x15) ... -> ..., value

Pilha imul Operao Formato Opcode Pilha ineg Operao Formato Opcode Pilha

Carrega int da varivel local. <n> deve ser um ndice para o array de variveis locais do quadro corrente. iload_<n> iload_0 = 26 (0x1a) iload_1 = 27 (0x1b iload_2 = 28 (0x1c) iload_3 = 29 (0x1d) ... -> ..., value

Multiplica int imul 104 (0x68) ..., value1, value2 -> ..., result

Nega int ineg 116 (0x74) ..., value -> ..., result

Arquitetura de Mquinas Virtuais

100

instanceof Operao Formato Opcode Pilha invokeinterface Operao Formato Opcode Pilha invokespecial Operao Formato Opcode Pilha invokestatic Operao Formato Opcode Pilha invokevirtual Operao Formato Opcode Pilha ior Operao Formato Opcode Pilha irem Operao Formato Opcode Pilha

Determina se objeto de tipo determinado instanceof indexbyte1 indexbyte2 193 (0xc1) ..., objectref -> ..., result

Invoca mtodo de interface invokeinterface indexbyte1 indexbyte2 count 0 185 (0xb9) ..., objectref, [arg1, [arg2 ...]] -> ...

Invoca mtodo especial (superclasse, privado, inicializao de instncia). invokespecial indexbyte1 indexbyte2 183 (0xb7) ..., objectref, [arg1, [arg2 ...]] -> ...

Invoca mtodo esttico de classe invokstatic indexbyte1 indexbyte2 184 (0xb8) ..., [arg1, [arg2 ...]] -> ...

Invoca mtodo de instncia invokevirtual indexbyte1 indexbyte2 182 (0xb6) ..., objectref, [arg1, [arg2 ...]] -> ...

OR booleano int ior 128 (0x80) ..., value1, value2 -> ..., result

Calcula o resto de diviso int irem 112 (0x70) ..., value1, value2 -> ..., result

Arquitetura de Mquinas Virtuais

101

ireturn Operao Formato Opcode Pilha ishl Operao Formato Opcode Pilha ishr Operao Formato Opcode Pilha istore Operao Formato Opcode Pilha istore_<n> Operao Formato Opcode

Retorna int do mtodo ireturn 172 (0xac) ..., value -> [empty]

Deslocamento lgico de value1 int esquerda por x bits, onde x o valor dos 5 bits baixos do value2. ishl 120 (0x78) ..., value1, value2 -> ..., result

Deslocamento aritmtico (com extenso de sinal) de value1 int direita por x bits, onde x o valor dos 5 bits baixos do value2. ishr 122 (0x7a) ..., value1, value2 -> ..., result

Armazena int na varivel local istore index 54 (0x36) ..., value -> ...

Pilha isub Operao Formato Opcode Pilha iushr

Armazena int na varivel local. <n> deve ser um ndice para o array de variveis locais do quadro corrente. istore_<n> istore_0 = 59 (0x3b) istore_1 = 60 (0x3c) istore_2 = 61 (0x3d) istore_3 = 62 (0x3e) ..., value -> ...

Subtrai int isub 100 (0x64) ..., value1, value2 -> ..., result

Arquitetura de Mquinas Virtuais

102

Operao Formato Opcode Pilha ixor Operao Formato Opcode Pilha jsr Operao Formato Opcode Pilha jsr_w Operao Formato Opcode Pilha l2d Operao Formato Opcode Pilha l2f Operao Formato Opcode Pilha l2i Operao Formato Opcode Pilha ladd

Deslocamento lgico de value1 int direita por x bits, onde x o valor dos 5 bits baixos do value2. iushr 124 (0x7c) ..., value1, value2 -> ..., result

XOR booleano int ixor 130 (0x82) ..., value1, value2 -> ..., result

Desvio de sub-rotina jsr branchbyte1 branchbyte2 168 (0xa8) ... -> ..., address

Desvio de sub-rotina (com ndice largo) jsr_w branchbyte1 branchbyte2 branchbyte3 branchbyte4 201 (0xc9) ... -> ..., address

Converte long para double l2d 138 (0x8a) ..., value -> ..., result

Converte long para float l2f 137 (0x89) ..., value -> ..., result

Converte long para int l2i 136 (0x88) ..., value -> ..., result

Arquitetura de Mquinas Virtuais

103

Operao Formato Opcode Pilha laload Operao Formato Opcode Pilha land Operao Formato Opcode Pilha lastore Operao Formato Opcode Pilha lcmp Operao Formato Opcode Pilha lconst_<l> Operao Formato Opcode Pilha ldc Operao Formato Opcode Pilha ldc_w

Adiciona long ladd 97 (0x61) ..., value1, value2 -> ..., result

Carrega long do array laload 47 (0x2f) ..., arrayref, index -> ..., value

AND booleano long land 127 (0x7f) ..., value1, value2 -> ..., result

Armazena long no array lastore 80 (0x50) ..., arrayref, index, value -> ...

Compara long lcmp 148 (0x94) ..., value1, value2 -> ..., result

Empilha constante long <l> (0 ou 1) lconst_<l> lconst_0 = 9 (0x9) lconst_1 = 10 (0xa) ..., -> ..., <l>

Empilha item da constant pool ldc index 18 (0x12) ... -> ..., value

Arquitetura de Mquinas Virtuais

104

Operao Formato Opcode Pilha ldc2_w Operao Formato Opcode Pilha ldiv Operao Formato Opcode Pilha lload Operao Formato Opcode Pilha lload_<n> Operao Formato Opcode

Empilha item da constant pool (ndice amplo) ldc_w indexbyte1 indexbyte2 19 (0x13) ... -> ..., value

Empilha long ou double da constant pool (ndice amplo) ldc2_w indexbyte1 indexbyte2 20 (0x14) ... -> ..., value

Divide long ldiv 109 (0x6d) ..., value1, value2 -> ..., result

Carrega long da varivel local lload index 22 (0x16) ... -> ..., value

Pilha lmul Operao Formato Opcode Pilha lneg Operao Formato Opcode Pilha

Carrega long da varivel local. <n> deve ser um ndice para o array de variveis locais do quadro corrente. lload_<n> lload_0 = 30 (0x1e) lload_1 = 31 (0x1f) lload_2 = 32 (0x20) lload_3 = 33 (0x21) ... -> ..., value

Multiplica long lmul 105 (0x69) ..., value1, value2 -> ..., result

Nega long lneg 117 (0x75) ..., value -> ..., result

Arquitetura de Mquinas Virtuais

105

lookupswitch Operao Acessa jump table por emparelhamento (matching) de chave e salta. De zero a trs bytes nulos so inseridos aps opcode de forma que defaultbyte1 comece em um endereo que um mltiplo de quatro bytes a partir do incio do mtodo corrente. Aps o padding segue uma srie de valores sinalizados de 32 bits: default, npairs, e ento pares npairs de valores sinalizados de 32 bits, onde cada par consiste de um int match e offset sinalizado de 32 bits. A tabela de pares match-offset da instruo deve ser ordenada em ordem numrica crescente por match. A chave, desempilhada da pilha de operandos deve ser int, e comparada com os valores match. Se algum casar, ento o endereo alvo calculado adicionando o offset correspondente ao endereo da instruo corrente. Formato lookupswitch <0-3_byte_pad> defaultbyte1 defaultbyte2 defaultbyte3 defaultbyte4 npairs1 npairs2 npairs3 npairs4 <match-offset_pairs> Opcode 171 (0xab) Pilha ..., key -> ... lor Operao Formato Opcode Pilha lrem Operao Formato Opcode Pilha lreturn Operao Formato Opcode Pilha lshl Operao Formato Opcode Pilha lshr

OR booleano long lor 129 (0x81) ..., value1, value2 -> ..., result

Calcula o resto de diviso de long lrem 113 (0x71) ..., value1, value2 -> ..., result

Retorna long do mtodo lreturn 173 (0xad) ..., value -> [empty]

Deslocamento lgico de value1 long esquerda por x bits, onde x o valor dos 6 bits baixos do value2 int. lshl 121 (0x79) ..., value1, value2 -> ..., result

Arquitetura de Mquinas Virtuais

106

Operao Formato Opcode Pilha lstore Operao Formato Opcode Pilha lstore_<n> Operao Formato Opcode

Deslocamento aritmtico (com extenso de sinal) de value1 long direita por x bits, onde x o valor dos 6 bits baixos do value2 int. lshr 123 (0x7b) ..., value1, value2 -> ..., result

Armazena long na varivel local lstore index 55 (0x37) ..., value -> ...

Pilha lsub Operao Formato Opcode Pilha lushr Operao Formato Opcode Pilha lxor Operao Formato Opcode Pilha monitorenter Operao Formato

Armazena long na varivel local. <n> deve ser um ndice para o array de variveis locais do quadro corrente. lstore_<n> lstore_0 = 63 (0x3f) lstore_1 = 64 (0x40) lstore_2 = 65 (0x41) lstore_3 = 66 (0x42) ..., value -> ...

Subtrai long lsub 101 (0x65) ..., value1, value2 -> ..., result

Deslocamento lgico de value1 long direita por x bits, onde x o valor dos 6 bits baixos do value2 int. lushr 125 (0x7d) ..., value1, value2 -> ..., result

XOR booleano long lxor 131 (0x83) ..., value1, value2 -> ..., result

Entra em monitor para objeto monitorenter

Arquitetura de Mquinas Virtuais

107

Opcode Pilha monitorexit Operao Formato Opcode Pilha multianewarray Operao

194 (0xc2) ..., objectref -> ...

Sai de monitor para objeto monitorexit 195 (0xc3) ..., objectref -> ...

Formato Opcode Pilha new Operao Formato Opcode Pilha newarray Operao Formato Opcode Pilha nop Operao Formato Opcode Pilha pop Operao Formato Opcode Pilha pop2

Cria um array multidimensional. O operando dimensions representa o nmero de dimenses do novo array. A pilha de operandos deve conter valores de dimenses que representam o nmero de componentes em uma dimenso do array. multianewarray indexbyte1 indexbyte2 dimensions 197 (0xc5) ..., count1, [count2, ...] -> ... , arrayref

Cria objeto new indexbyte1 indexbyte2 187 (0xbb) ... -> ..., objectref

Cria array newarray atype 188 (0xbc) ..., count -> ..., arrayref

No faz nada nop 0 (0x0) Sem alterao

Desempilha topo da pilha pop 87 (0x57) ..., value -> ...

Arquitetura de Mquinas Virtuais

108

Operao Formato Opcode Pilha putfield Operao Formato Opcode Pilha putfield Operao Formato Opcode Pilha ret Operao Formato Opcode Pilha return Operao Formato Opcode Pilha saload Operao Formato Opcode Pilha sastore Operao Formato Opcode Pilha sipush

Desempilha um (forma 2) ou dois (forma 1) operandos do topo da pilha. A forma 2 ocorre quando o valor long ou double. pop2 88 (0x58) Forma 1: ..., value2, value1 -> ... Forma 2: ..., value -> ...

Preenche campo em objeto putfield indexbyte1 indexbyte2 181 (0xb5) ..., objectref, value -> ...

Preenche campo esttico em classe putstatic indexbyte1 indexbyte2 179 (0xb3) ..., value -> ...

Retorna de sub-rotina ret index 169 (0xa9) Sem alterao

Retorna de mtodo com tipo de retorno void return 177 (0xb1) ... -> [empty]

Carrega short do array saload 53 (0x35) ..., arrayref, index -> ..., value

Armazena short no array sastore 86 (0x56) ..., arrayref, index, value -> ...

Arquitetura de Mquinas Virtuais

109

Operao Formato Opcode Pilha swap Operao Formato Opcode Pilha

Empilha short sipush byte1 byte2 17 (0x11) ... -> ..., value

Troca os dois operandos do topo da pilha swap 95 (0x5f) ..., value2, value1 -> ..., value1, value2

tableswitch Operao Acessa jump table por ndice e salta. De zero a trs bytes nulos so inseridos aps opcode de forma que defaultbyte1 comece em um endereo que um mltiplo de quatro bytes a partir do incio do mtodo corrente. Aps o padding segue uma srie de valores sinalizados de 32 bits: default, low e high, e ento outra srie de valores sinalizados de 32 bits, onde cada valor consiste de um offset sinalizado de 32 bits formado por high - low + 1. O ndice int desempilhado da pilha de operandos. Se o ndice menor que low ou maior que high, o endereo alvo calculado adicionando default ao endereo da instruo corrente. Formato tableswitch <0-3_byte_pad> defaultbyte1 defaultbyte2 defaultbyte3 defaultbyte4 lowbyte1 lowbyte2 lowbyte3 lowbyte4 highbyte1 highbyte2 highbyte3 highbyte4 <jump_offsets> Opcode 170 (0xaa) Pilha ..., index -> ... wide Operao

Formato Opcode Pilha

Estende ndice de variveis locais por bytes adicionais. Na forma 1 <opcode> pode ser iload, fload, aload, lload, dload, istore, fstore, astore, lstore, dstore, ou ret. A forma 2 aplica-se apenas instruo iinc. Em ambas as formas, o opcode wide seguido no cdigo compilado pelo opcode da instruo modificada. Dois bytes no sinalizados indexbyte1 e indexbyte2 seguem o opcode modificado e so montados em um ndice no sinalizado de 16 bits para uma varivel local no quadro corrente. O ndice calculado deve ser um ndice dentro do array de variveis locais do quadro corrente. Forma 1: wide <opcode> indexbyte1 indexbyte2 Forma 2: wide iinc indexbyte1 indexbyte2 constbyte1 constbyte2 196 (0xc4) O mesmo que a instruo modificada

Arquitetura de Mquinas Virtuais

110

Apndice B.

Mquinas Virtuais implementadas em Hardware

A arquitetura picoJava um microprocessador de baixo custo (aproximadamente US$ 50,00) dedicado execuo de bytecodes Java sem a necssidade de um interpretador ou de um compilador JIT (JustInTime compiler). O picoJava executa o conjunto de instrues Java diretamente. Como resultado, aplicaes Java so 3 vezes menores (em tamanho de cdigo), requer 5 vezes menos memria e 20 vezes mais rpido que interpretadores Java em uma CPU padro. Essa arquitetura no inclui interface lgica de memria ou I/O. Ao contrrio disso, os desenvolvedores podem adicionar sua prpria lgica para customizar memria e I/O. O ncleo picoJava pode acelerar alguns aspectos da JVM, como, por exemplo, garbage collection, entretanto, uma quantidade significante de software deve ser desenvolvida para produzir uma JVM completa, pois, o ncleo picoJava no a JVM completa em silcio, mas sim um projeto de microprocessador otimizado para executar uma implementao JVM pequena, conforme indica Sun (1999).

Os chips picoJava, microJava e UltraJava


Conforme citado por Silva (200-), a Sun Microeletronics produziu os chips picoJava, microJava e UltraJava capazes de exeutar diretamenet bytescodes, acelerando em milhares de vezes a velocidade de execuo. Isto permitiu o desenvolvimento vivel de aplicativos cada vez mais complexos, abrangentes e viveis. picoJava Projetado para equipamentos eletrnicos bsicos (telefones celulares, impressoras e outros perifricos). Oferece para a indstria a melhor relao preo / performance. Disponvel para ser ser licenciado a parti de meados de 1996. microJava Baseado no ncleo do picoJava, adicionando caractersticas especficas (I/O, memria, funes de comunicao e controle). Ideal para dispositivos baseados em rede (controladores e equipamentos utilizados por empresas de telecomunicao) e jogos simples. Disponveis a partir do primeiro semestre de 1997. UltraJava Processador mais rpido (performance de 3 a 5 vezes melhor que da microJava) Ideal para trabalhos com grficos, imagens 3D e aplicaes que usam intensamente recursos de multimdia. Disponvel no final de 1997.

Caractersticas
De acordo com Fujitsu (199-), as principais caractersticas do picoJava II so as seguintes: Processador de 32 bit's; Alta velocidade Suporta cdigo C++ (desde que compilado para bytecode) Pipeline de 6 estgios Folding de at quatro instrues em paralelo. Cache de instrues: 0 16 Kbyte

Arquitetura de Mquinas Virtuais

111

Cache de dados: 0 16 Kbyte

Conjunto de instrues
Segundo Pilla (1999), o conjunto de instrues da arquitetura picoJava derivado daquele definido para execuo em mquinas virtuais: Ele consiste em 226 instrues de tamanho variado entre 1 e 3 bytes. Esse conjunto dividido nos seguintes grupos: Tipo Diagnstico Leitura e escrita de registradores Leitura e armazenamentos arbitrrios Suporte ao sistema em software Suporte linguagem Tamanho 1 Tamanho 2 Tamanho 3 Nmero byte bytes bytes total 0 8 0 8 0 49 0 49 0 26 9 35 2 5 1 8 2 98 15 115

Esse conjunto de instrues dito estendido por possui as instrues da mquina virtual mais um conjunto especfico da microarquitetura. As instrues estendidas no podem ser utilizadas em programas Java legais. So de uso exclusivo do microprocessador e apenas atividades do sistema podero utilizar estes bytecodes. Desta forma, fica garantida a portabilidade dos programas entre vrios chips Java diferentes. O desenvolvimento do conjunto de instrues para a microarquitetura picoJava-II seguiu um caminho completamente diferente do adotado nas arquiteturas RISC . Enquanto que os desenvolvedores de processadores RISC esto preocupados em diminuir a complexidade do hardware resultante, usando um conjunto de instrues de tamanho fixo (em geral, 32 bits) e instrues simples, os arquitetos de picoJava-II preocupam-se mais com a execuo do software, resultando numa maior complexidade de hardware mas que permite a eliminao dos compiladores JIT e a obteno de bons ndices de desempenho para programas Java. O tamanho da palavra na microarquitetura picoJava-II de 16 bits.

Arquitetura de Mquinas Virtuais

112

Pipeline de Instrues
O pipeline do picoJava II composto por seis estgios:

Estgio de Busca: este estgio busca instrues tanto da cache de instrues ou da memria externa. Situa-se dentro da prpria Unidade de Cache de Instrues. Estgio de Decodificao:situando-se na Unidade de Folding de Instrues, este estgio encarrega-se de agrupar e pr-codificar instrues. Este estgio caracteriza-se pela necessidade de preparar microcdigo para a execuo posterior. Estgio de Registradores: estgio encarregado de buscar os operandos da cache de pilha e determinar condies de uso de instrues de leitura, condies de bypass e condies de falhas na cache de pilha. Encontra-se baseado na Unidade de Controle de Registradores. Estgio de Execuo: utiliza a ULA para executar tanto instrues lgicas e aritmticas como calcular endereos de leituras e armazenamentos da Unidade de Cache de Dados. Em caso de instrues de desvio, calcula o endereo do desvio e a condio na qual o desvio est dependendo. As instrues de ponto flutuante so enviadas para a Unidade de Ponto Flutuante para execuo. Estgio de Cache: neste estgio, dados da cache de dados so acessadas. Estgio de Escrita: os resultados so escritos para a pilha de cache.

Apenas o primeiro estgio, de Busca, est inserido na Unidade de Cache de Instrues. Os demais estgios encontram-se na Unidade de Instrues. Este pipeline executa tanto instrues como microcdigo, que so instrues que demandam mais que um ciclo para executar.

Unidades da microarquitetura
Unidade de cache de instrues (ICU): Busca instrues e as despacha para a decodificao na Unidade de Inteiros, realizando o papel do estgio de Busca do pipeline de instrues. A cache de instrues presente nesta unidade possui mapeamento direto, com linhas de 16 bytes cada. Atualmente, a cache de instrues pode apresentar 1, 2, 4, 8 ou 16 Kbytes, ou no estar presente. O buffer de instrues possui capacidade para 16 bytes. A Unidade de Cache de Instrues possui capacidade para escrever 8 bytes e despachar at 7 bytes por ciclo para a Unidade de Inteiros. possvel adicionar ainda uma megacell de cache de instrues organizada logicamente como 2048 entradas de 64 bits, ou seja, 4 palavras por entrada. Esta megacell funciona como uma cache de nvel 2 e pode ser desligada quando inativa, de forma a economizar energia. Unidade de folding de Instrues: Determina quantas instrues podem ser despachadas em um ciclo, de acordo com as instrues e o tamanho da informao da Unidade de Cache de Instrues. O mecanismo de folding foi concebido j na microarquitetura picoJava, devido observao que o acesso apenas ao topo da pilha era muito restritivo e prejudicava o potencial de ciclos por instrues (CPI). Este

Arquitetura de Mquinas Virtuais

113

mecanismo permite o acesso direto a qualquer posio na pilha em um nico ciclo. Para tanto, os 7 bytes superiores do buffer de instrues so examinados, determinando quantas instrues podem ser agrupadas, at um mximo de quatro instrues. Aps isto, as instrues so decodificadas e o resultado enviado para o estgio de Registradores. Alm disto, o sinal de deslocamento enviado para o buffer de instrues, indicando o nmero de bytes consumidos. Duas leituras de operandos podem ser despachadas pela Unidade de Folding de Instrues por ciclo, sendo uma operao e um resultado de armazenamento. A lgica de folding pode ainda emular a execuo de um RISC. Na figura abaixo, uma operao de folding consome quatro instrues consecutivas e as transforma em apenas uma.

Unidade de inteiros (IU): Executa todas as instrues definidas na Especificao da Mquina Virtual Java, com excesso das instrues de ponto flutuante. Alm destas instrues, so implementadas instrues especiais, chamadas de bytecodes estendidos, que suportam as funes de sistema como armazenamento e leitura de posies arbitrrias de memria, gerenciamento de cache e acesso aos registradores internos. Estas instrues no esto disponveis aos usurios, apenas podendo serem executadas pelo sistema operacional. Uma caracterstica interessante da Unidade de Inteiros que todas as instrues passam por ela, inclusive aquelas de ponto flutuante. Quando uma instruo de ponto flutuante encontrada, ela redirecionada para a Unidade de Ponto Flutuante. A Unidade de Inteiros tambm busca e armazena dados na Unidade de cache de dados. Estas caractersticas esto mais direcionadas economia de hardware, criando um gargalo em potencial para a execuo de mltiplas instrues em simultneo. Outra caracterstica, encontrada em arquiteturas baseadas em pilha, que a Unidade de Inteiros no possui registradores de uso geral visveis ao programador. Uma cache de pilha utilizada para o armazenamento dos operandos a serem utilizados, tornando a microarquitetura mais prxima da

Arquitetura de Mquinas Virtuais

114

estrutura da linguagem Java, que utiliza intensamente pilhas como estruturas no nvel de bytecodes. A Unidade de Inteiros possui, ainda, uma ROM com microcdigo, utilizada para executar algumas instrues da Mquina Virtual Java . Unidade de Ponto Flutuante: E as instrues matemticas que utilizam nmeros de ponto flutuante e, portanto, no podem ser executadas na Unidade de Inteiros. Esta unidade otimizada para o uso de instrues de preciso simples e para ocupar uma rea menor no chip . As instrues de preciso dupla tambm so implementadas, mas demoram aproximadamente de duas a quatro vezes mais ciclos que instrues de preciso simples. A construo da Unidade de Ponto Flutuante utiliza um caminho de dados de 32 bits para uma mquina microcodificada. A cada ciclo, o seqenciador de microcdigo coloca uma micropalavra no caminho de dados e monitora a condio de desvio retornada para determinar a prxima palavra. possvel observar que as dependncias de controle so limites importantes para a mquina de microcdigo, pois cada microinstruo depende da anterior - h uma condio de desvio a cada microinstruo. A Unidade de Ponto Flutuante segue a norma IEEE-754, suportando underflow gradual. Desta forma, a mantissa torna-se no-normalizada, levando a erros menores quando manuseando nmeros muito pequenos. possvel no utilizar a Unidade de Ponto Flutuante em uma implementao, por motivos de economia de rea ou energia. Para tanto, as instrues de ponto flutuante devem ser capturadas por interrupes de software e tratadas em microcdigo.

Unidade de cache de dados (DCU):


Executa as requisies oriundas do pipeline de instrues ou do gerenciador de driblle, dando prioridade ao pipeline. A cache de dados consiste em uma cache 2-associativa, write-back, com cada linha tendo 16 bytes. O tamanho da cache pode ser configurada em 0, 1, 2, 4, 8, e 16 KBytes. O tamanho padro utilizado na microarquitetura picoJava-II de 16 KBytes. Unidade de Gerenciamento de Pilha (SMU): Como a Mquina Virtual Java utiliza intensamente estruturas de pilhas, a microarquitetura picoJava utiliza arquitetura de cache diferente da usual, em formato de pilha. Desta forma, frames podem ser criados para cada mtodo invocado na Mquina Virtual Java. Cada frame possui os parmetros para o mtodo, as variveis locais e informaes de estado do prprio frame, que podem ser utilizadas no retorno do mtodo, como o contador de programa e o monitor corrente. A implementao deste mecanismo se justifica devido ao grande nmero de invocaes de mtodos do Java e utilizao de construes mais sofisticadas, com mtodos virtuais, que exigem um mecanismo eficiente para seu tratamento. O funcionamento da cache de pilha baseado em um buffer circular (prxima figura), que cresce ou diminui de forma previsvel para evitar estouros. Os pontos de underflow e overflow so utilizados pelo mecanismo de dribblign da Unidade de Cache de Dados para determinar a movimentao de dados entre a cache de pilha e o resto da hierarquia de memria. O resultado uma cache que funciona de forma previsvel e que no introduz bolhas no pipeline de instrues, funcionando como uma janela de registradores virtual.

Arquitetura de Mquinas Virtuais

115

A implementao da cache de pilha d-se atravs de uma memria RAM assncrona ou de um conjunto de registradores, com trs portas de leitura e duas de escrita. As portas podem ser acessadas de forma independente. A Unidade de Inteiros utiliza duas portas de leitura e uma porta de escrita. A escrita possui prioridade sobre a leitura de uma mesma posio e duas escritas simultneas sobre a mesma posio uma situao indefinida. Duas marcas so utilizadas para gerenciar e abstrair a limitao de tamanho da pilha. A pilha cresce no sentido anti-horrio e diminui no sentido horrio. As entradas da pilha que j foram escritas na memria podem ser sobrescritas, criando assim espao para novas entradas sempre que necessrio. Assim, quando a pilha cresce ultrapassando uma marca de overflow, um mecanismo disparado para salvar entradas na memria. As entradas mais antigas ainda no escritas na memria so as primeiras a serem salvas, evitando desta forma uma condio de overflow na pilha. A situao contrria, de underflow, evitada atravs de um mecanismo que, quando ultrapassada uma marca de underflow, comea a buscar as entradas na cache de dados. Este mecanismo permite que a cache de pilha possua uma alta previsibilidade, caracterstica essencial para alguns sistemas, em especial de tempo real. Para evitar a perda de desempenho normalmente associada a arquiteturas de pilha, a microarquitetura picoJava utiliza um mecanismo de folding de instrues. Unidade de Interface com o Barramento (BIU): Executa as funes de interface do picoJava com o mundo externo. Esta unidade gera requisies para a memria e para dispositivos de entrada e sada. As unidades de entrada e sada encontram-se mapeadas na memria. Portanto, todas as requisies passam pela memria e o core o nico acessando o barramento de memria e no necessita arbitrar seu uso. Devido s suas caractersticas, a lgica necessria para a Unidade de Interface com o Barramento simples. As tarefas desenvolvidas pela Unidade de Interface com o Barramento incluem: Gerar requisies de escrita e leitura para a memria; Prover confirmao para os controladores das caches de instrues e de dados, para que estes possam eliminar dados que tenham sido escritos na memria; Gerenciar erros gerados no barramento de memria. O controle exercido sobre as caches garante que apenas uma requisio da cache de instrues e uma da cache de dados possam estar ativas ao mesmo tempo. O algoritmo para arbitrar estas situaes o seguinte:

Arquitetura de Mquinas Virtuais

116

As requisies da cache de dados possuem uma prioridade superior s requisies da cache de instrues. Dois argumentos, tipe e size, indicam para o rbitro o nmero de confirmaes a serem esperadas de uma transferncia. A mquina de estados do rbitro reinicializada quando um sinal externo recebido (pj_reset). Em requisies back-to-back, o rbitro pode iniciar a segunda requisio no prximo tick do relgio, aps a primeira transferncia estar completa ou aps a ltima confirmao. Uma confirmao com erro em um ciclo termina uma transferncia.

Unidade de Desligamento, Clock e Varredura (PCSU): Essa unidade muito importante para a microarquitetura picoJava. Devido s finalidades para as quais foi desenvolvida, focando fortemente em sistemas embarcados, a economia de energia torna-se uma das preocupaes dos projetistas. Esta unidade controla: As funes de desligamento; O funcionamento do clock interno; A reinicializao do sistema; As funes de teste do sistema. Na microarquitetura picoJava h dois modos de consumo disponveis: o Modo Normal e o Modo Standby. No Modo Normal, as unidades conservam tanta energia quanto possvel, atravs das seguintes operaes: A Unidade de Cache de Instrues gera o sinal de desligamento enquanto espera por dados que no podem ser armazenados na cache ou que no esto disponveis por falhas na mesma. Quando a unidade resume uma operao, este sinal ento desligado. A Unidade de Cache de Dados gera o sinal de desligamento se todas as condies so alcanadas: No h instrues relacionadas Unidade de Cache de Dados nos estgios de Execuo ou Cache do pipeline de instrues; No h ciclos de preenchimento da cache ativos; Linhas invlidas no esto sendo trocadas; A Unidade de Cache de Dados no est executando a instruo zero_line; No h requisies pendentes quando uma instruo bloqueada est resente; No h armazenamentos pendentes. O Modo Standby pode ser assumido atravs da execuo da instruo de desligamento, priv_powerdown. Quando isto ocorre, a Unidade de Desligamento, Clock e Varredura executa as seguintes aes: Envia um sinal de desligamento para todas as unidades e espera pela confirmao das mesmas. Entra no Modo Standby e indica o estado de standby para o resto do sistema, atravs do pino pj_standby_out O sistema sai do Modo Standby se recebe uma interrupo em determinadas portas. Neste caso, o sistema leva quatro ciclos para voltar ao seu clock normal.

You might also like