JVM - Java é Verboso Mesmo? Parte III (já dizia Jack "vamos por partes")
Published: 2023-01-27 15:29:50

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

![Imagem que descreve com agrupamentos três de retangulos principais as partes da JVM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xtpysqgyj3irwt9ww7j2.png)

Na [parte dois](https://dev.to/eguadorodrigo/jvm-java-e-verboso-mesmo-parte-ii-a-saga-continua-nok) 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](https://javaalmanac.io/bytecode/opcodes/) possíveis em sua estrutura e seus [operadores](https://www.infoworld.com/article/2077233/bytecode-basics.html) 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

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pvdjgsr2nuh13d2t88n7.png)

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