38
Mitsuo Takaki Java Bytecode Software Básico

Mitsuo Takaki

  • Upload
    august

  • View
    25

  • Download
    1

Embed Size (px)

DESCRIPTION

Java Bytecode. Software Básico. Mitsuo Takaki. Java Bytecode. O que é Bytecode Formato de um arquivo .class Principais comandos Motivações para aprender bytecode Principais Dificuldades. Java Bytecode. O que é Bytecode Formato de um arquivo .class Principais comandos - PowerPoint PPT Presentation

Citation preview

Page 1: Mitsuo Takaki

Mitsuo Takaki

Java BytecodeSoftware Básico

Page 2: Mitsuo Takaki

Java Bytecode

1.O que é Bytecode

2.Formato de um arquivo .class

3.Principais comandos

4.Motivações para aprender bytecode

5.Principais Dificuldades

Page 3: Mitsuo Takaki

Java Bytecode

1.O que é Bytecode

2.Formato de um arquivo .class

3.Principais comandos

4.Motivações para aprender bytecode

5.Principais Dificuldades

Page 4: Mitsuo Takaki

Passos de Compilação de Java

A compilação de um código java segue os seguintes passos: Recebe um código Java (alto nível). Compila para uma linguagem intermediária (baixo

nível). Este procedimento é conhecido como tradução.

Após esta compilação, o código é interpretado.

Page 5: Mitsuo Takaki

Passos de Compilação de Java

.java Compilador .class JVM

com

pila

inte

rpre

ta

Page 6: Mitsuo Takaki

O que é Java Bytecode?

Java Bytecode é a linguagem intermediária à qual um código java é modificado.

Utiliza apenas comandos simplificados e baseados em pilha.

Muito semelhante a Assembly. Linguagem baseada em pilha.

Cada opcode tem o tamanho de 1 byte (origem do nome bytecode).

Page 7: Mitsuo Takaki

Motivações

A interpretação de um código Java exigiria uma maior complexidade do interpretador. Menor velocidade de interpretação.

Durante a compilação, otimizações são feitas. Códigos mais eficientes são gerados.

Portabilidade É possível executar o código em várias plataformas por

ser interpretado.

Page 8: Mitsuo Takaki

Motivações

Simplificações são realizadas: Short, char e boolean se tornam inteiros. Laços são simplificados

For, while, do...while são iguais, apenas se comportam de forma diferente.

Page 9: Mitsuo Takaki

Códigos Equivalentes

Dois códigos podem realizar uma mesma tarefa usando diferentes linguagens.

Desta forma, é possível manter a semântica do programa original, apenas seu código é simplificado.

Page 10: Mitsuo Takaki

Códigos Equivalentes

int foo(int a) {

if (a == 0) {

return 0;

} else {

return 1;

}

}

int foo(int a):

0: ILOAD_1

1: IFEQ 4

2: BIPUSH 1

3: IRETURN

4: BIPUSH 0

5: IRETURN

Page 11: Mitsuo Takaki

Códigos Equivalentes

int foo() {

int result = 0;

while (result < 2) {

result++;

}

return result;

}

int foo():

0: BIPUSH 0

1: ISTORE_1

2: GOTO 4

3: IINC 1,1

4: ILOAD_1

5: BIPUSH 2

6: IF_ICMPGE 3

7: ILOAD_1

8: IRETURN

Page 12: Mitsuo Takaki

Java Bytecode

1.O que é Bytecode

2.Formato de um arquivo .class

3.Principais comandos

4.Motivações para aprender bytecode

5.Principais Dificuldades

Page 13: Mitsuo Takaki

Formato de um Arquivo .class

O arquivo compilado (.class) armazena as informações específica da classe. Métodos (privado, protegido, publico). Campos. Atributos. Constant Pool. ...

Page 14: Mitsuo Takaki

Formato de um Arquivo .class

Page 15: Mitsuo Takaki

Constant Pool

Local onde estão armazenadas todas as constantes. Nome das classes usadas. Nome dos métodos. Valores iniciais. ...

Page 16: Mitsuo Takaki

Inner Class

As inner class, apesar de estarem dentro de uma classe, após a compilação são “extraidas” e um .class é criado para as mesmas.

– É criado algo como: HelloWorld$1.class

Page 17: Mitsuo Takaki

Java Bytecode

1.O que é Bytecode

2.Formato de um arquivo .class

3.Principais comandos

4.Motivações para aprender bytecode

5.Principais Dificuldades

Page 18: Mitsuo Takaki

Principais Comandos

Aritméticos (inteiros): IADD – soma. ISUB – subtração. IMUL – multiplicação. IDIV – divisão. ...

Page 19: Mitsuo Takaki

Principais Comandos

Pilha: BIPUSH – empilha uma constante (inteiro). POP – remove da pilha (independente de tipo). LDC – empilha uma constant (string ou double). ...

Page 20: Mitsuo Takaki

Principais Comandos

Mudança de fluxo: IFEQ, IFNE, IFLT, IFLE, IFGT, IFGE

Compara um inteiro que está na pilha com zero. Caso o resultado seja verdadeiro, modifica o fluxo para o

endereço especificado como parâmetro. GOTO

Mudança de fluxo incondicional (modifica o fluxo sem nenhuma verificação).

Page 21: Mitsuo Takaki

Principais Comandos

Chamada de métodos: INVOKESTATIC, INVOKEINTERFACE,

INVOKEVIRTUAL, INVOKESPECIAL. Chama um método de acordo com o seu modificador

(estático, método de uma interface, método de uma instância)

Page 22: Mitsuo Takaki

Parâmetros

Alguns comandos usam parâmetros na pilha. INVOKEVIRTUAL precisa que a referência do

objeto esteja na pilha.

Além disto, alguns comandos podem possuir mais de um parâmetro. IINC 1, 1 – soma o valor 1 a variável com índice 1.

Page 23: Mitsuo Takaki

Java Bytecode

1.O que é Bytecode

2.Formato de um arquivo .class

3.Principais comandos

4.Motivações para aprender bytecode

5.Principais Dificuldades

Page 24: Mitsuo Takaki

Por que aprender bytecode?

Para se ter proficiência em Java, não é necessário aprender bytecode. Da mesma forma que para aprender uma

linguagem de alto nível, não é necessário aprender linguagem de máquina.

Existem poucas bibliotecas que permitem a manipulação de bytecode. BCEL, biblioteca da Apache, não está mais sendo

desenvolvida e possui muitos bugs.

Page 25: Mitsuo Takaki

Por que aprender bytecode?

Apenas em casos específicos será necessário o conhecimento de bytecode. No desenvolvimento de sistemas, dificilmente será

necessário conhecer alguma coisa sobre bytecode.

O compilador de Java já realiza otimizações eficientes. Escrever manualmente um código bytecode

possivelmente será menos eficiente que um código gerado pelo compilador.

Page 26: Mitsuo Takaki

Motivações

Manipular bytecode permite introduzir novas funcionalidades a códigos “fechados” (instrumentação). Alguns sistemas são disponibilizados sem código

fonte, a modificação destes códigos se torna impossível sem a manipulação de bytecode.

Debugging. É possível introduzir traces no código para

identificação de bugs e análise de fluxo.

Page 27: Mitsuo Takaki

Motivações

Análise de cobertura de testes unitários. Ferramentas que analizam a cobertura de testes de

unidade utilizam instrumentação para a inserção de traces no código.

Modificação de operadores de fluxo de controle. É possível escrever geradores automáticos de teste

de mutação.

Page 28: Mitsuo Takaki

Ferramentas que Usam Manipulação de Bytecode

• AspectJ

– Ferramenta de Orientação a Aspectos.

• EclEmma

– Mede cobertura dos testes.

• JAD (JAva Decompiler)

– Descompila classes Java.

Page 29: Mitsuo Takaki

Java Bytecode

1.O que é Bytecode

2.Formato de um arquivo .class

3.Principais comandos

4.Motivações para aprender bytecode

5.Principais Dificuldades

Page 30: Mitsuo Takaki

Principais Dificuldades - Loops

• Devido as suas simplificações, não é possível distinguir um while, do...while e for.

• Por padrão, um loop é toda estrutura de mudança de fluxo condicional que possui um fluxo no sentido inverso.

Page 31: Mitsuo Takaki

Principais Dificuldades - Loops

• Todo loop é composto por um operador de fluxo condicional.

– Condição de parada.

• É difícil identificar o inicio e o fim de loop.

Page 32: Mitsuo Takaki

Principais Dificuldades - Loops

• Para identificar um loop é necessário realizar uma análise do fluxo do programa.

• Ai ser encontrado um operador de mudança de fluxo condicional que mude o fluxo no sentido contrário, foi encontrado o fim do bloco do loop.

• O operador de condição de parada sempre aponta para o inicio do bloco.

Page 33: Mitsuo Takaki

Principais Dificuldades - Loops

int foo():

0: BIPUSH 0

1: ISTORE_1

2: GOTO 4

3: IINC 1,1

4: ILOAD_1

5: BIPUSH 2

6: IF_ICMPGE 3

7: ILOAD_1

8: IRETURN

Corpo do loop

Condição de parada

Page 34: Mitsuo Takaki

Modificando um Loop

int foo():

0: BIPUSH 0

1: ISTORE_1

2: GOTO 4

3: IINC 1,1

4: ILOAD_1

5: BIPUSH 2

6: IF_ICMPGE 3

7: ILOAD_1

8: IRETURN

ILOAD_1BIPUSH 2

IADDISTORE_1

Page 35: Mitsuo Takaki

Modificando um Loop

int foo():

0: BIPUSH 0

1: ISTORE_1

2: GOTO 4

3: IINC 1,1

4: ILOAD_1

5: BIPUSH 2

6: IF_ICMPGE 3

7: ILOAD_1

8: IRETURN

Page 36: Mitsuo Takaki

Modificando um Loop

int foo():

0: BIPUSH 0

1: ISTORE_1

2: GOTO 11

3: ILOAD_1

4: BIPUSH 2

5: IADD

6: ISTORE_1

7: IINC 1,1

8: ILOAD_1

9: BIPUSH 2

10: IF_ICMPGE 3

11: ILOAD_1

12: IRETURN

Atualiza endereços do operadores de mudança de fluxo.

Page 37: Mitsuo Takaki

Principais Dificuldades - Ifs

• Nem todo operador condicional de mudança de fluxo pode ser automáticamente traduzido como um if.

– Como visto anteriormente, este pode ser a condição de parada de um loop.

• Em um caso de if...else não existem 2 operadores, apenas um.

Page 38: Mitsuo Takaki

Principais Dificuldades - Ifs

void foo(int x, int y) {

if (x > y) {

...

} else {

...

}

}

void foo(int x, int y):

0: ILOAD_1

1: ILOAD_2

2: IF_ICMPLE 5

3: bloco do if

4: GOTO 6

5: bloco do else

6: RETURN