O JVM StackMapTable Passado e Presente

JVM Java 6 versão introduzida após os arquivos de classe no diagrama de pilha (StackMapTable).

  • Efeito
    , a fim de melhorar a eficiência do processo de verificação na verificação de tipo JVM

estrutura FIG pilha está localizado atributo Código (atributo Código refere classfile) da tabela de atributos (tabela de atributos) estrutura. StackMapTable conter, no máximo atributo um nos códigos atributo byte no código.
Após a versão Java 7 como parte obrigatória da pilha do arquivo de código byte. Originalmente programadores não precisa se preocupar com os detalhes do compilador JIT JVM, você não sabe teoria de compiladores ou fluxo de dados, detalhes do fluxo de controle. No entanto, uma pilha de força, para ser gerado se o código de bytes A, deve ser conhecido com precisão para cada instrução de código de bytes correspondentes ao tipo de variáveis locais e operando pilha. Isso ocorre porque Java7 em tempo de compilação para fazer algumas coisas durante a verificação feito, e esse é o tipo de inspecção, que está incluído no diagrama de pilha conteúdo.

Mas a validação do tempo de carregamento de classe de Java executado apenas uma vez, e foi responsável pela maior parte do tempo da operação é o consumo de IO, em vez do processo de verificação. Mesmo agora, com a pilha do processo de verificação ainda será executado, há um diagrama de pilha é apenas uma parte das poupanças de tempo de verificação. E designers também deve ser compatível JVM implementação de verificação não diagrama de pilha, porque Java7 a versão anterior não é diagrama de pilha obrigatória do conceito, no entanto Java8 continua diagrama de estrutura pilha bytecode.

malmente, você não precisa saber muito sobre a Tabela stackmap ao usar ASM. ASM pode gerar automaticamente esta tabela para você a menos que você inicializar o classwriter com COMPUTE_FRAMEflags.For detalhado definição da tabela, você pode consultar a especificação JVM (Depois Java7?). O único lugar que conheço para a tabela de stackmap é a verificação bytecode quando um carregador de classe está prestes a carregar um bytecode, ou você quer ver o legal de bytecode você gerou. Neste caso, verificador leva as entradas na tabela para fazer a correção de bytecodes (por exemplo, o tipo de consistência, os destinos de salto e assim por diante). Confira neste link http://stackoverflow.com/questions/25109942/is-there-a-better-explanation-of-stack-map-frames se você quiser detalhes explicação.

Vamos olhar um exemplo de uma estrutura combinada da pilha da fig.

código Java é a seguinte:

package bytecode;

public class Coffee {
 
    int bean;
 
    public void getBean(int var) {
        if (var > 0) {
            this.bean = var;
        } else {
            throw new IllegalArgumentException();
        }
    }
 
}

Use detalhado para ver a estrutura do arquivo de classe é a seguinte: olhar para o foco StackMapTable, diagrama de pilha contém duas entradas.

public class com.lijingyao.bytecode.Coffee
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #6.#18         // java/lang/Object."<init>":()V
   #2 = Fieldref           #5.#19         // com/lijingyao/bytecode/Coffee.bean:I
   #3 = Class              #20            // java/lang/IllegalArgumentException
   #4 = Methodref          #3.#18         // java/lang/IllegalArgumentException."<init>":()V
   #5 = Class              #21            // com/lijingyao/bytecode/Coffee
   #6 = Class              #22            // java/lang/Object
   #7 = Utf8               bean
   #8 = Utf8               I
   #9 = Utf8               <init>
  #10 = Utf8               ()V
  #11 = Utf8               Code
  #12 = Utf8               LineNumberTable
  #13 = Utf8               getBean
  #14 = Utf8               (I)V
  #15 = Utf8               StackMapTable
  #16 = Utf8               SourceFile
  #17 = Utf8               Coffee.java
  #18 = NameAndType        #9:#10         // "<init>":()V
  #19 = NameAndType        #7:#8          // bean:I
  #20 = Utf8               java/lang/IllegalArgumentException
  #21 = Utf8               com/lijingyao/bytecode/Coffee
  #22 = Utf8               java/lang/Object
{
  int bean;
    descriptor: I
    flags:


  public com.lijingyao.bytecode.Coffee();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 6: 0


  public void getBean(int);
    descriptor: (I)V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=2
         0: iload_1
         1: ifle          12
         4: aload_0
         5: iload_1
         6: putfield      #2                  // Field bean:I
         9: goto          20
        12: new           #3                  // class java/lang/IllegalArgumentException
        15: dup
        16: invokespecial #4                  // Method java/lang/IllegalArgumentException."<init>":()V
        19: athrow
        20: return
      LineNumberTable:
        line 10: 0
        line 11: 4
        line 13: 12
        line 15: 20
      StackMapTable: number_of_entries = 2
        frame_type = 12 /* same */
        frame_type = 7 /* same */
}

A estrutura da tabela constante piscina pode ser visto classfile propriedades estruturais UTF-8 # 15 designa estrutura StackMapTable. Pode ser visto nas últimas poucas linhas getBean (int)
específicos estrutura StackMapTable, esta é a pilha da fig. Do acima exposto, encontrado StackMapTable contém attribute_name_index, attribute_length, estrutura number_of_entries e entradas. Number_of_entries que representa o número de pilha moldura mapa, isto é, o número de entradas, pode ser visto, neste exemplo, há dois "frame_type" isto é, = 2. As duas entradas são = 12 é o frame_type / * Mesmo / =. 7 e a frame_type / Mesmo /. Cada entrada representa o elemento StackMapFrame de um método. Que contém um código byte offset (indicando que a posição da estrutura correspondente ao código de bites) e a tabela de variáveis local a esse deslocamento (variáveis locais), a pilha de operandos (operando entrada da pilha) Tipo de autenticação necessária (ps: a tabela de variáveis local e na pilha de operandos pode referir-se a introdução de http://blog.csdn.net/lijingyao8206/article/details/46562933). O primeiro método é uma StackMapFrame cada implícitos (entradas [0]), e é calculada pelo método descrito do verificador de tipos. Aqui vemos = 12 frame_type / Same, * / na verdade, é o segundo método StackMapFrame, mas é StackMapFrame exibido. Cada mapa pilha entradas de quadro na tabela são dependentes do elemento anterior, cada um dos quais é usado para representar o deslocamento incremental. Portanto, a ordem de entrada é muito importante.

Aqui para acrescentar que as instruções de bytecode e conceitos parâmetros, instruções de bytecode, os mnemônicos opcode representados por um comprimento de bytes (o Opcode) e sua configuração posterior necessidade de operação vários parâmetros. Algumas instruções não precisa necessariamente parâmetros. Mas aqui cuidado para não confundir um conceito, parâmetros e operandos (oprends) não é um conceito aqui é o mesmo. Onde os argumentos (parâmetros) valores são estáticos, compilar o bytecode é armazenado no compilada, e o operando pilha Oprends valores (operando) descritos na primeira corrida de valores de conhecer a estrutura de dados. Eu não sei não é clara, mas encontrei um monte de artigos e traduções estão confundindo conjunto de instruções "parâmetros" e operando pilha "operando". De facto, com base num parâmetro de bytes inteiro assinado, utilizado para apontar para saltar endereços de destino, se mais do que um byte, a fim de armazenar dois parâmetros, ou os dois parâmetros em armazenamento endian tal maneira. Tais como: alvo endereço de instrução + = Goto endereço de instrução (parâmetro 1 << 8 | 2 parâmetros).

Uma vez que a estrutura do mapa quadro de pilha em pilha FIG entradas são usadas para identificar o deslocamento pode ser calculada de acordo com cada quadro de exibição deslocamento de uma estrutura periódica é apresentada de acordo com a fórmula offset_delta + 1. I.e. getBean exemplo de um método para compensar este cálculo, as entradas primeiro item exibido no presente exemplo: frame_type = 12, onde 12 é o desfasamento de código de um byte (offset_delta) moldura é. O deslocamento para o elemento seguinte é offset_delta + 1 + offset do quadro actual do elemento anterior. Assim, vemos

1: ifle 12
nesta linha, o parâmetro ifle instruções absolutos expressão bytecode é 12, de modo que o código de bytes compensar entradas do primeiro elemento é StackMapFrame offset_delta = 12, a empatia

9: 20 Goto
Este parâmetro bytecode instruções Goto linha 20 é, de facto, Goto 12 + 1 + 7, isto é, a instrução de código de bites é compensado 20 Goto. Portanto, gravando o deslocamento StackMapTable para garantir a ordem byte, e não são duplicados. Pode ser encontrada, mas a fase de verificação verificação de tipo JVM StackMapTable acrescenta algumas instruções de bytecode para a informação compensar calculado pelo incremento, o método simplifica a inspecção de todos os bytes de deslocamentos de código.

Frame_type / * mesmo * / Este Exemplo representa o actual quadro StackMapFrame e um quadro anterior têm as mesmas variáveis locais, e a pilha de operandos actual está vazia.
Neste trabalho, combinado com JVM 8 especificação, se errado, por favor me corrigir.

Publicado 404 artigos originais · ganhou elogios 1022 · Vistas 500.000 +

Acho que você gosta

Origin blog.csdn.net/qq_33589510/article/details/105248897
Recomendado
Clasificación