Edição: Correção no título, quem disse a frase, foi o Jack, não o Jason. Obrigado ao colega Eduardo, que corrigiu a gafe lá no LinkedIn. 🤓
Deêm uma boa olhada na imagem abaixo e processem a informação de que sim, a JVM é complexa, nem de longe é algo simples, até para que seja possível a portabilidade do código, foi pensado em como fazê-la de maneira que fosse capaz de executar comandos ao mesmo tempo que faz gestão de memória, melhoramento de processamento, entre outras funções e claro, tudo isso e mais um pouco, de forma independente do sistema operacional que ela esteja. Eu mesmo não conhecia algumas nuances de dentro desse universo, mas bora lá aprender juntos? #partiu
Na parte dois chegamos a dizer a forma que a classe Programa era compilada e enviada para execução. Agora vamos ver os caminhos que uma classe pode percorrer dentro da JVM. Então vou tentar explicar cada camada como venho fazendo nos artigos, pois acho que tá sendo uma boa maneira de me expressar e fica bastante didática (ao meu ver, claro)
Alô galera, deêm feedbacks!! assim eu sei se tá sendo legal (ou não) a experiência de vocês por aqui <3
Spoiler: Uma classe enviada à JVM pode ter até 256 opcodes possíveis em sua estrutura e seus operadores podem ser de 8 ou 16 bit. (Olha que artigo legal temos aqui! kkk)
Dado o Spoiler, bora lá então! A galera quer ser dominadora do café, né? Então vamos explorar cada pedaço pra melhorar nossas habilidades e pra começar, na Java Virtual Machine têm-se três principais subsistemas:
- Subsistema de carregamento de classes (ClassLoader Subsystem)
- Subsistema da área de pilha (Runtime Data Area)
- Subsistema do motor de execução (Execution Engine)
Tentei traduzir pro pt-BR pra que a galera vá entendendo em português, mas já consiga também fazer um paralelo com o inglês onde esse material é mais farto e detalhado.
Subsistema de carregamento de classes
Fazem parte desse subsistema: Carregamento | Vinculação | Inicialização
Carregamento (Loading)
O carregamento performa afim de preparar a JVM para a execução e avalia os seguintes pontos:
- O caminho completo da classe invocada na execução e o caminho de seu parente imediato; O que quero dizer com isso é: imagine que nossa classe Programa esteja no caminho, por exemplo:
C:\Desktop\projeto\Programa.java
- O caminho completo é este mesmo exibido acima (em inglês fully qualified name, também chamado de FQN ), já o seu parente imediato é:
C:\Desktop\projeto
- Qual referência o Bytecode (.class) é relacionado: Se a uma classe, se a uma Inteface ou a um Enum: No nosso exemplo, o arquivo Programa faz referência a uma Classe!
- Onde tu olhas pra ter tanta certeza disso, Rodrigo?
...Olhem a assinatura da nossa classe:
public Class Programa{
Basta por hora entender que por ter escrito ali ao lado de Programa a palavra Class, isso indica qual a referência será vinculada ao nosso Bytecode, que neste caso, a referencia é à Classe.
- Informações dos modificadores, variáveis e métodos:
- Modificadores: public, protected, default;
- Variaveis: qualquer variável encontrada na classe ou nos blocos de execução dela;
- Métodos: qualquer outro método que pode ser invocado dentro da classe, incluindo o método main;
E nesse contexto, o fluxo abaixo é realizado:
- Inicializar o carregador de classes (BootStrap ClassLoader) - Que tem a responsabilidade de carregar as classes nativas para o classpath, ou seja, carrega os arquivos em memória a partir de onde está instalada a JVM no sistema operacional; E a biblioteca que se encarrega disso e terá a maior prioridade de todas nesta execução é a rt.jar (Runtime do Java); Ex.: Todas as bibliotecas dentro de $JAVA_HOME/jre/lib serão inicializadas a começar pela rt;
- Extensor do carregador de classes (Extension ClassLoader) - Filha da Bootstrap e é responsável por carregar as demais bibliotecas da instalação a partir do caminho lib/ext; Ex.: Todas as bibliotecas dentro de $JAVA_HOME/lib/ext também serão carregadas para a memória após a inicialização anterior;
- Carregador de classe de aplicação (Application Class Loader ou System Class Loader) - Responsável por carregar os Bytecodes encontrados no diretório invocado na execução. Ex.: No nosso exemplo, será a classe Programa.
_Usando a classe Programa como exemplo, vamos para a próximo fluxo...
Vinculação (Linking)
Performa afim de avaliar o que será necessário da JVM para a execução.
- Verifica (Verifying) - Analisa a classe que entrou na JVM (Programa.class) e quais vinculações ela possui (se possui herança, se possui extensão, se há dependências de outras classes através de seus imports), caso haja falha, nessa verificação podemos encontrar a exceção java.lang.VerifyError por exemplo;
- Prepara (Prepare) - Carrega a classe, fazendo a alocação de memória necessária e inicializando todas as referencias estáticas e seus valores padrões;
- Resolve (Resolve) - É o processo que reaplica as referências simbólicas aos tipos e suas referências diretas. Essa resolução é dada através da busca e localização da entidade na área de método. Ex.: Nossa classe possui um System.out.println que imprime saídas no prompt (ou terminal), mas essa referencia é de uma biblioteca a System da biblioteca java.lang e a out (PrintStream) da java.io;
Inicialização (Initialization)
Nessa fase, já temos todas as variáveis estáticas definidas e seus valores padrões (caso tenham sido declarados), referencias de imports, se código referencia a uma Classe, uma Interface ou a um Enum. Então a inicialização se dá de cima para baixo, seguindo as nomenclaturas de pacotes, imports, definição de classe, definição de métodos, variáveis e modificadores;
A JVM segue o princípio de Delegação-Hierarquia para carregar as classes. Isso significa que é uma sequencia definida pela classe que entra e suas relações com as classes nativas da JVM...
Caso a JVM não consiga identificar essa relação com suas classes nativas, classes de extensão ou de aplicação, que foi o fluxo que explicamos acima, haverá uma exceção do tipo java.lang.ClassNotFoundException, indicando que o código não possui referência de classe capaz de tratar aquela execução que entrou na JVM.
Ufa! Hoje foi bastante detalhado, não foi? Mas por hora, como tá no título, vamos concordar com o Jason, porque o assunto é extenso e por isso, vamos por partes. hehehehehe
Espero que esteja gostando do conteúdo e se quiser me seguir, minhas redes estão aqui no meu perfil, fiquem a vontade!!
Um grande abraço e até a próxima!
Referências:
- Como a JVM opera (em inglês) - https://www.geeksforgeeks.org/jvm-works-jvm-architecture/?ref=lbp
- A arquitetura da JVM (em inglês) - https://dzone.com/articles/jvm-architecture-explained
Top comments (0)