Arquivo de classe Java - Java class file

Arquivo de classe Java
Tipo de mídia da Internet aplicativo / java-vm, aplicativo / x-httpd-java
Desenvolvido por Sun Microsystems

Um arquivo de classe Java é um arquivo (com a extensão de nome de arquivo .class ) contendo bytecode Java que pode ser executado na Java Virtual Machine (JVM) . Um arquivo de classe Java geralmente é produzido por um compilador Java a partir de arquivos de origem da linguagem de programação Java ( arquivos .java ) contendo classes Java (como alternativa, outras linguagens JVM também podem ser usadas para criar arquivos de classe). Se um arquivo de origem tiver mais de uma classe, cada classe será compilada em um arquivo de classe separado.

As JVMs estão disponíveis para muitas plataformas e um arquivo de classe compilado em uma plataforma será executado em uma JVM de outra plataforma. Isso torna os aplicativos Java independentes da plataforma .

História

Em 11 de dezembro de 2006, o formato do arquivo de classe foi modificado em Java Specification Request (JSR) 202.

Layout e estrutura do arquivo

Seções

Existem 10 seções básicas para a estrutura do arquivo de classe Java:

  • Número mágico : 0xCAFEBABE
  • Versão do formato de arquivo de classe : as versões secundária e principal do arquivo de classe
  • Pool constante : pool de constantes para a classe
  • Sinalizadores de acesso : por exemplo, se a classe é abstrata, estática, etc.
  • Esta classe : o nome da classe atual
  • Superclasse : o nome da superclasse
  • Interfaces : quaisquer interfaces da classe
  • Campos : quaisquer campos da classe
  • Métodos : quaisquer métodos da classe
  • Atributos : quaisquer atributos da classe (por exemplo, o nome do arquivo-fonte, etc.)

Número mágico

Os arquivos de classe são identificados pelo seguinte cabeçalho de 4 bytes (em hexadecimal ): (as primeiras 4 entradas na tabela abaixo). A história deste número mágico foi explicada por James Gosling referindo-se a um restaurante em Palo Alto : CA FE BA BE

"Costumávamos almoçar em um lugar chamado St Michael's Alley. De acordo com a lenda local, no passado obscuro, os Grateful Dead costumavam se apresentar lá antes de se tornarem grandes. Era um lugar bem descolado que era definitivamente um Grateful Dead Kinda Place. Quando Jerry morreu, eles até ergueram um pequeno santuário budista. Quando costumávamos ir lá, nos referíamos ao lugar como Café Dead. Em algum lugar ao longo da linha, percebeu-se que era um número HEX. estava reformulando algum código de formato de arquivo e precisava de alguns números mágicos : um para o arquivo de objeto persistente e outro para classes. Usei CAFEDEAD para o formato de arquivo de objeto e no grepping para palavras hexadecimais de 4 caracteres que cabem depois de "CAFE "(parecia ser um bom tema) Eu bati no BABE e decidi usá-lo. Naquela época, não parecia muito importante ou destinado a ir a qualquer lugar a não ser a lata de lixo da história. Então CAFEBABE se tornou o arquivo da classe formato, e CAFEDEAD era o formato de objeto persistente. Mas a facilidade de objeto persistente falhou sim, e junto com ele foi o uso do CAFEDEAD - ele foi eventualmente substituído pelo RMI .

Layout geral

Como o arquivo de classe contém itens de tamanho variável e também não contém deslocamentos de arquivo embutidos (ou ponteiros), ele é normalmente analisado sequencialmente, do primeiro byte até o final. No nível mais baixo, o formato do arquivo é descrito em termos de alguns tipos de dados fundamentais:

  • u1 : um inteiro sem sinal de 8 bits
  • u2 : um inteiro sem sinal de 16 bits na ordem de bytes big-endian
  • u4 : um inteiro não assinado de 32 bits na ordem de bytes big-endian
  • tabela : uma matriz de itens de comprimento variável de algum tipo. O número de itens na tabela é identificado por um número de contagem precedente (a contagem é u2), mas o tamanho em bytes da tabela só pode ser determinado examinando cada um de seus itens.

Alguns desses tipos fundamentais são então reinterpretados como valores de nível superior (como strings ou números de ponto flutuante), dependendo do contexto. Não há imposição de alinhamento de palavras e, portanto, nenhum byte de preenchimento é usado. O layout geral do arquivo de classe é mostrado na tabela a seguir.

deslocamento de byte Tamanho tipo ou valor Descrição
0 4 bytes u1 =
0xCA hex
número mágico (CAFEBABE) usado para identificar o arquivo em conformidade com o formato de arquivo da classe
1 u1 =
0xFE hex
2 u1 =
0xBA hex
3 u1 =
0xBE hex
4 2 bytes u2 número da versão secundária do formato de arquivo da classe que está sendo usado
5
6 2 bytes u2 número da versão principal do formato de arquivo de classe que está sendo usado.

Java SE 17 = 61 (0x3D hex),
Java SE 16 = 60 (0x3C hex),
Java SE 15 = 59 (0x3B hex),
Java SE 14 = 58 (0x3A hex),
Java SE 13 = 57 (0x39 hex),
Java SE 12 = 56 (0x38 hex),
Java SE 11 = 55 (0x37 hex),
Java SE 10 = 54 (0x36 hex),
Java SE 9 = 53 (0x35 hex),
Java SE 8 = 52 (0x34 hex),
Java SE 7 = 51 (0x33 hex),
Java SE 6.0 = 50 (0x32 hex),
Java SE 5.0 = 49 (0x31 hex),
JDK 1.4 = 48 (0x30 hex),
JDK 1.3 = 47 (0x2F hex),
JDK 1.2 = 46 (0x2E hex),
JDK 1.1 = 45 (0x2D hex).
Para obter detalhes sobre os números das versões anteriores, consulte a nota de rodapé 1 em The JavaTM Virtual Machine Specification 2ª edição

7
8 2 bytes u2 contagem de pool constante, número de entradas na seguinte tabela de pool constante. Essa contagem é pelo menos um maior que o número real de entradas; veja a discussão a seguir.
9
10 cpsize (variável) tabela mesa de pool constante, uma matriz de entradas de pool constante de tamanho variável, contendo itens como números literais, strings e referências a classes ou métodos. Indexado a partir de 1, contendo ( contagem de pool constante - 1) número de entradas no total (consulte a nota).
...
...
...
10+ cpsize 2 bytes u2 sinalizadores de acesso, uma máscara de bits
11+ cpsize
12+ cpsize 2 bytes u2 identifica esta classe, indexe no pool constante para uma entrada do tipo "Classe"
13+ cpsize
14+ cpsize 2 bytes u2 identifica a superclasse , indexa no pool constante para uma entrada do tipo "Classe"
15+ cpsize
16+ cpsize 2 bytes u2 contagem de interface, número de entradas na seguinte tabela de interface
17+ cpsize
18+ cpsize isize (variável) tabela tabela de interface: uma matriz de comprimento variável de índices de pool constantes que descrevem as interfaces implementadas por esta classe
...
...
...
18+ cpsize + iSize 2 bytes u2 contagem de campos, número de entradas na tabela de campos a seguir
19+ cpsize + iSize
20+ cpsize + iSize fsize (variável) tabela tabela de campos, matriz de campos de comprimento variável

cada elemento é uma estrutura field_info definida em https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.5

...
...
...
20+ cpsize + iSize + fsize 2 bytes u2 contagem de métodos, número de entradas na seguinte tabela de métodos
21+ cpsize + iSize + fsize
22+ cpsize + iSize + fsize msize (variável) tabela tabela de métodos, matriz de métodos de comprimento variável

cada elemento é uma estrutura method_info definida em https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.6

...
...
...
22+ cpsize + iSize + fsize + msize 2 bytes u2 contagem de atributos, número de entradas na seguinte tabela de atributos
23+ cpsize + iSize + fsize + msize
24+ cpsize + iSize + fsize + msize asize (variável) tabela tabela de atributos, matriz de atributos de comprimento variável

cada elemento é uma estrutura attribute_info definida em https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7

...
...
...

Representação em uma linguagem de programação semelhante a C

Como C não oferece suporte a vários arrays de comprimento variável dentro de uma estrutura, o código a seguir não compilará e servirá apenas como uma demonstração.

struct Class_File_Format {
   u4 magic_number;

   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 attributes_count;   
   attribute_info attributes[attributes_count];
}

A piscina constante

A mesa de pool constante é onde a maioria dos valores constantes literais são armazenados. Isso inclui valores como números de todos os tipos, strings, nomes de identificadores, referências a classes e métodos e descritores de tipo. Todos os índices, ou referências, a constantes específicas na tabela de pool de constantes são dados por números de 16 bits (tipo u2), onde o valor de índice 1 se refere à primeira constante na tabela (o valor de índice 0 é inválido).

Devido às escolhas históricas feitas durante o desenvolvimento do formato do arquivo, o número de constantes na tabela de pool constante não é realmente o mesmo que a contagem de pool constante que precede a tabela. Primeiro, a tabela é indexada começando em 1 (em vez de 0), mas a contagem deve ser interpretada como o índice máximo mais um. Além disso, dois tipos de constantes (longas e duplas) ocupam dois slots consecutivos na tabela, embora o segundo desses slots seja um índice fantasma que nunca é usado diretamente.

O tipo de cada item (constante) no pool de constantes é identificado por uma tag de byte inicial . O número de bytes após esta tag e sua interpretação dependem do valor da tag. Os tipos de constantes válidos e seus valores de tag são:

Byte de tag Bytes adicionais Descrição da constante Versão introduzida
1 2+ x bytes
(variável)
Sequência UTF-8 (Unicode): uma sequência de caracteres prefixada por um número de 16 bits (tipo u2) indicando o número de bytes na sequência codificada que segue imediatamente (que pode ser diferente do número de caracteres). Observe que a codificação usada não é realmente UTF-8 , mas envolve uma ligeira modificação da forma de codificação padrão Unicode. 1.0.2
3 4 bytes Inteiro: um número de complemento de dois de 32 bits com sinal no formato big-endian 1.0.2
4 4 bytes Float: um número de ponto flutuante IEEE 754 de precisão única de 32 bits 1.0.2
5 8 bytes Longo: um número de complemento de dois de 64 bits com sinal no formato big-endian (ocupa dois slots na mesa de pool constante) 1.0.2
6 8 bytes Duplo: um número de ponto flutuante IEEE 754 de precisão dupla de 64 bits (leva dois slots na tabela de pool constante) 1.0.2
7 2 bytes Referência de classe: um índice dentro do pool constante para uma string UTF-8 contendo o nome de classe totalmente qualificado (em formato interno ) (big-endian) 1.0.2
8 2 bytes Referência de string: um índice dentro do pool constante para uma string UTF-8 (big-endian também) 1.0.2
9 4 bytes Referência de campo: dois índices dentro do pool constante, o primeiro apontando para uma referência de classe, o segundo para um descritor de nome e tipo. (big-endian) 1.0.2
10 4 bytes Referência de método: dois índices dentro do pool constante, o primeiro apontando para uma referência de classe, o segundo para um descritor de nome e tipo. (big-endian) 1.0.2
11 4 bytes Referência do método de interface: dois índices dentro do pool constante, o primeiro apontando para uma referência de classe, o segundo para um descritor de nome e tipo. (big-endian) 1.0.2
12 4 bytes Descritor de nome e tipo: dois índices para strings UTF-8 dentro do pool de constantes, o primeiro representando um nome (identificador) e o segundo um descritor de tipo especialmente codificado. 1.0.2
15 3 bytes Identificador de método: esta estrutura é usada para representar um identificador de método e consiste em um byte do descritor de tipo, seguido por um índice dentro do pool de constantes. 7
16 2 bytes Tipo de método: esta estrutura é usada para representar um tipo de método e consiste em um índice dentro do pool de constantes. 7
17 4 bytes Dinâmico: é usado para especificar uma constante calculada dinamicamente produzida pela invocação de um método de bootstrap. 11
18 4 bytes InvokeDynamic: é usado por uma instrução invokedynamic para especificar um método de bootstrap, o nome da invocação dinâmica, o argumento e os tipos de retorno da chamada e, opcionalmente, uma sequência de constantes adicionais chamadas de argumentos estáticos para o método de bootstrap. 7
19 2 bytes Módulo: é usado para identificar um módulo. 9
20 2 bytes Pacote: é usado para identificar um pacote exportado ou aberto por um módulo. 9

Existem apenas dois tipos de constantes integrais, inteiros e longos. Outros tipos integrais que aparecem na linguagem de alto nível, como booleano, byte e short devem ser representados como uma constante inteira.

Nomes de classes em Java, quando totalmente qualificados, são tradicionalmente separados por pontos, como "java.lang.Object". No entanto, nas constantes de referência de classe de baixo nível, aparece um formulário interno que usa barras, como "java / lang / Object".

As strings Unicode, apesar do moniker "string UTF-8", não são realmente codificadas de acordo com o padrão Unicode, embora seja semelhante. Existem duas diferenças (consulte UTF-8 para uma discussão completa). A primeira é que o ponto de código U + 0000 é codificado como a sequência de dois bytes C0 80(em hexadecimal) em vez da codificação de byte único padrão 00. A segunda diferença é que os caracteres suplementares (aqueles fora do BMP em U + 10000 e acima) são codificados usando uma construção de par substituto semelhante ao UTF-16 em vez de serem codificados diretamente usando UTF-8. Nesse caso, cada um dos dois substitutos é codificado separadamente em UTF-8. Por exemplo, U + 1D11E é codificado como a sequência de 6 bytes ED A0 B4 ED B4 9E, em vez da codificação UTF-8 correta de 4 bytes F0 9D 84 9E.

Veja também

Referências

Leitura adicional

  • Tim Lindholm , Frank Yellin (1999). The Java Virtual Machine Specification (segunda edição). Prentice Hall. ISBN 0-201-43294-3. Página visitada em 2008-10-13 .O documento oficial de definição da Java Virtual Machine , que inclui o formato do arquivo de classe. Tanto a primeira como a segunda edições do livro estão disponíveis gratuitamente online para visualização e / ou download .