Slide 1

Slide 1 text

Desvendando a JVM Kamila Santos Arquitetura e funcionamento JVM

Slide 2

Slide 2 text

Kamila Santos BACKEND DEVELOPER AME DIGITAL MICROSOFT MVP DEVELOPER TECHNOLOGIES CONTENT CREATOR @KAMILA_CODE

Slide 3

Slide 3 text

O que é a JVM? JVM (Java Virtual Machine) foi criada nos anos 90, ela é a base da plataforma Java e é responsável por tratar todos os SOs e plataformas para a linguagem, ela não conhece a linguagem Java, somente o seu bytecode.

Slide 4

Slide 4 text

O que é a JVM? O bytecode vem no formato .class e são instruções que indicam para a JVM o que deve ser realizado naquela parte da aplicação.

Slide 5

Slide 5 text

Tipos de linguagem -> Linguagem compiladas -> Linguagens interpretadas -> E o Java????????

Slide 6

Slide 6 text

Linguagens compiladas Compilam e transformam o código em binário (linguagem de máquina) seguindo a arquitetura do sistema. Tem como vantagem velocidade de execução pela compilação ser focada na arquitetura. Ex: C e C++

Slide 7

Slide 7 text

Linguagens interpretadas Traduzem cada linha de código em binário conforme a linha é executada. A vantagem dessa abordagem é a portabilidade, que permite executar o código em diversos tipos de arquiteturas sem precisar fazer nenhum tipo de pré-compilação para a arquitetura. Por ex: Ruby e Python

Slide 8

Slide 8 text

E O JAVAAAA? Ela é um misto de linguagem compilada e interpretada. Primeiramente o código é compilado para um formato portátil e intermediário (chamado de bytecode), para somente depois ser interpretado. Dentre as vantagens dessa abordagem podemos citar: type checking (verificação da tipagem), otimização da compilação do código, o bytecode só necessita ser compilado uma vez para chegar o mais próximo do código de máquina e mantém a portabilidade.

Slide 9

Slide 9 text

Apresentando a arquitetura IMAGEM DE: HTTPS://WWW.GURU99.COM/JAVA-VIRTUAL-MACHINE-JVM.HTML

Slide 10

Slide 10 text

Class Loader IMAGEM DE: HTTPS://WWW.GURU99.COM/JAVA-VIRTUAL-MACHINE-JVM.HTML

Slide 11

Slide 11 text

Class Loader Loading Linking Initialization Class Loader é responsável por 3 atividades:

Slide 12

Slide 12 text

Class Loader Quando você compila um arquivo java, ele é convertido em bytecode (arquivo .class). Quando você tenta usar esta classe em seu aplicativo, o class loader o carrega na memória principal.

Slide 13

Slide 13 text

Class Loader - Loading Normalmente, a primeira classe a ser carregada na memória é a classe principal (que contém o método principal). Jvm armazena as seguintes informações no method area:

Slide 14

Slide 14 text

Class Loader - Loading O nome da classe carregada e sua classe pai. Todos os arquivos .class relacionados a esta classe Modificadores, Métodos e Variáveis. 1. 2. 3. Temos 3 carregadores de classes integrados disponíveis em Java:

Slide 15

Slide 15 text

Class Loader - Loading Bootstrap class loader: O carregador de classes raiz. É a superclasse do Extension Class Loader e carrega os pacotes Java padrão (lang, util, net, io ..). Esses pacotes padrão estão presentes no arquivo rt.jar e em outras bibliotecas centrais no diretório $ JAVA_HOME / jre / lib.

Slide 16

Slide 16 text

Class Loader - Loading Extension Class Loader: é a subclasse do Bootstrap Class Loader e a superclasse do Application Class Loader. Carrega as extensões das bibliotecas Java padrão presentes no diretório $ JAVA_HOME / jre / lib / ext

Slide 17

Slide 17 text

Class Loader - Loading Application Class Loader: O último class loader e a subclasse do Extension Class Loader. Carrega os arquivos presentes no caminho de classe. O caminho de classe é definido como o diretório atual do aplicativo.

Slide 18

Slide 18 text

Class Loader - Loading A JVM usa o método ClassLoader.loadClass () para carregar a classe na memória. Tenta carregar a classe com base em um nome totalmente qualificado.

Slide 19

Slide 19 text

Class Loader - Loading Se um class loader pai não puder localizar uma classe, delega o trabalho a um class loader filho. Se o filho não for capaz de carregar a classe, ele lança noClassDefFoundError ou ClassNotFoundException.

Slide 20

Slide 20 text

Class Loader - Linking Depois que uma classe é carregada na memória, ela vai para o processo de linking . O processo de linking envolve combinar os diferentes elementos e dependências do programa.

Slide 21

Slide 21 text

Class Loader - Linking Verificação Preparação Resolução Linking inclui as seguintes etapas: 1. 2. 3.

Slide 22

Slide 22 text

Class Loader - Linking Verificação: Verifica se um arquivo está corretamente formatado e se foi gerado por compilador válido ou não. Se essa verificação falhar, nós recebemos uma runtime exception java.lang.VerifyError. Essa verificação é feita pelo componente ByteCodeVerifier. Quando essa atividade é concluída a classe está pronta para compilação.

Slide 23

Slide 23 text

Class Loader - Linking Preparação: JVM aloca memória para variáveis ​ ​ de classe e inicializa a memória para valores padrão.

Slide 24

Slide 24 text

Class Loader - Linking Resolução: O processo de substituição de referências simbólicas, o processo é feito pesquisando no method area para alocar a entidade de referência.

Slide 25

Slide 25 text

Class Loader - Initialization Nesta etapa, todas as variáveis ​ ​ estáticas são atribuídas com seus valores definidos no código e no bloco estático. Esta etapa é executada de cima para baixo em uma classe de pai para filho na hierarquia de classes.

Slide 26

Slide 26 text

JVM Memory IMAGEM DE: HTTPS://WWW.GURU99.COM/JAVA-VIRTUAL-MACHINE-JVM.HTML

Slide 27

Slide 27 text

JVM Memory Method area Heap JVM language stacks PC registers Native Method stacks Nós temos 5 componentes nessa area:

Slide 28

Slide 28 text

JVM Memory - Method Area Contém todas as informações das classes, como nome, métodos e etc.

Slide 29

Slide 29 text

JVM Memory - Method Area Se a memória disponível nesta área não for suficiente para a inicialização do aplicativo, a JVM lança um OutOfMemoryError.

Slide 30

Slide 30 text

JVM Memory - Method Area Existe apenas uma method area por JVM e é um recurso compartilhado.

Slide 31

Slide 31 text

JVM Memory - Heap Area Aqui estão todos os objetos, suas variáveis ​ ​ de instância e matrizes relacionadas. Esta memória é compartilhada por vários threads.

Slide 32

Slide 32 text

JVM Memory - JVM language Stacks (stack area) Quando uma nova thread é criada na JVM, uma pilha de tempo de execução separada também é criada neste momento. (armazena informações específicas da thread criada, que será destruída assim que a thread for finalizada.

Slide 33

Slide 33 text

JVM Memory - JVM language Stacks Variáveis ​ ​ locais, chamadas de método e resultados parciais são armazenados aqui.

Slide 34

Slide 34 text

JVM Memory - JVM language Stacks Um stackOverFlowError ocorre quando um processo que está sendo executado em uma thread requer um tamanho de pilha muito grande que não está disponível.

Slide 35

Slide 35 text

JVM Memory - JVM language Stacks Para cada chamada de método, uma entrada é feita na pilha de memória (stack frame) quando essa chamada de método é concluída, a stack frame é destruído.

Slide 36

Slide 36 text

JVM Memory - JVM language Stacks Local Variables Operand stack Frame Data A stack frame é dividida em 3 partes:

Slide 37

Slide 37 text

JVM Memory - Local Variables cada frame contém um array de variáveis chamado local variables. Todas local variables e seus valores são armazenados aqui. No tempo de compilação o tamanho desse array é determinado.

Slide 38

Slide 38 text

Diferença entre heap e stack

Slide 39

Slide 39 text

Heap -> armazena objetos complexos -> em um aplicativo, ele é compartilhado por todas as threads -> os dados armazenados na heap podem ser acessados ​ ​ por threads multiplas -> ponteiro para aquele objeto, que é a referência da variável e que está armazenado na pilha

Slide 40

Slide 40 text

Stack -> cada thread tem sua própria stack -> pode ser definida como uma estrutura de dados gerenciada pela JVM -> todas as variáveis ​ ​ locais são criadas na pilha e são automaticamente retiradas da pilha quando você chega ao fechamento do bloco que criou aquela variável -> o dado na stack é restrito para a thread , não pode ser acessada por outras threads da aplicação.

Slide 41

Slide 41 text

JVM Memory - Operand stack Cada frame contém uma pilha LIFO chamada operand stack. Atua como um workspace em tempo de execução para performar operações intermediárias.

Slide 42

Slide 42 text

JVM Memory - Frame Data Armazena todos os símbolos correspondentes ao method area e armazena as informações do bloco catch em caso de exceptions.

Slide 43

Slide 43 text

PC (Program Counter) Registers Cada thread tem o seu próprio PC registers para armazenar o endereço do que está sendo executado no momento na JVM.

Slide 44

Slide 44 text

PC (Program Counter) Registers Quando a instrução é executada, o PC register é atualizado com a próxima instrução.

Slide 45

Slide 45 text

JVM Memory - Native Method Stacks Para cada nova thread, uma nova native method stack é alocada.

Slide 46

Slide 46 text

Execution Engine IMAGEM DE: HTTPS://WWW.GURU99.COM/JAVA-VIRTUAL-MACHINE-JVM.HTML

Slide 47

Slide 47 text

Execution Engine Interpreter Just-In-Time Compiler(JIT) Garbage Collector Na execution engine nós temos 3 partes:

Slide 48

Slide 48 text

Execution Engine A execution engine executa os bytecodes (arquivo .class) Lê o bytecode linha a linha Então usa os dados e informação presentes na área de memória para executar instruções.

Slide 49

Slide 49 text

Execution Engine - Interpreter O interpreter é responsável por ler e executar o bytecode linha a linha. Devido a esse processo linha a linha o interpreter é uma das etapas mais demoradas.

Slide 50

Slide 50 text

Execution Engine - Interpreter Quando um método é chamado múltiplas vezes,a cada vez é necessário uma nova interpretação.

Slide 51

Slide 51 text

Execution Engine - JIT Compiler O JIT compiler ve quais partes do código são executadas com maior frequência. (Principalmente quais métodos são chamados com maior frequência). A execução desse código pode ser acelerada se o método já for compilado para código nativo de máquina. A parte do código que já estiver em código de máquina vai rodar mais rápido que o bytecode interpretado.

Slide 52

Slide 52 text

O que é o código de máquina nativo mesmo? O código executável que é compreendido pelo SO, na compilação o bytecode é convertido para o código de máquina nativo (isso em um thread separada), enquanto isso a JVM continua usando a versão interpretada.

Slide 53

Slide 53 text

JIT Compiler seu prinicipal objetivo é recompilar o bytecode anteriormente gerado em tempo de runtime,buscando por possíveis melhorias para sua execução em código nativo. Nesse processo estão envolvidos dois tipos de compiladores: Client Compiler (C1) e o Server Compiler (C2).

Slide 54

Slide 54 text

C1 Compiler voltado para aplicações no lado cliente com inicialização mais rápida, o compilador busca por hot methods (mais utilizados) para fazer otimizações simples. Short lived applications também se benficiam da rapidez do C1, levando em conta que nao houve tempo de "aprender" como otimizar aquele código inicialmente.

Slide 55

Slide 55 text

C2 Compiler voltado para aplicações do lado sever, tem como objetivo analisar e monitorar por mais tempo o comportamento do código dentro da nossa aplicação, buscando por pontos críticos e para fazer a otimização posteriormente. As otimizações são mais agressivas já que a análise é mais rigorosa também. Métodos compilados pelo C2 são mais rápidos que os compilados pelo C1.

Slide 56

Slide 56 text

Tiered Compilation Surgiu no Java 7 e no Java 8 se tornou default, tem como estratégia começar somente com o interpretador de forma rápida e depois começar a fazer pequenas otimizações usando o C1 para saber quais são os hot methods.

Slide 57

Slide 57 text

Tiered Compilation Depois desse tempo inicial de execução, o funcionamento da app e dos hot methods ganha maior relevância e o C2 é chamado para fazer as otimizações mais avançadas. o Tiered Compilation é dividido em 5 níveis:

Slide 58

Slide 58 text

Níveis da Tiered Compilation Nível 0 - usa somente o modo de interpretação Nível 1 - usa o C1 de modo simples sem nenhuma análise de comportamento (profiling) Nível 2 - usa o C1 com um profiling limitado e moderado

Slide 59

Slide 59 text

Níveis da Tiered Compilation Nível 3 - usa o C1 com um processo de profiling completo Nível 4 - usa o C2 com o mesmo profiling do nível anterior.

Slide 60

Slide 60 text

Segmented Code Cache Surgiu no Java 9 com maneiras de organizar e separar os tipos de código compilados em cache, é uma área onde JVM armazena seu bytecode compilado em código nativo. Chamamos cada bloco de código nativo de nmethod , ele pode ser um método Java completo ou parte dele.

Slide 61

Slide 61 text

Segmented Code Cache Ele tem um tamanho fixo, quando encher o JIT será desligado (a app não vai parar). Caso isso aconteça iremos receber o erro: "CodeCache is full… The compiler has been disabled" e teremos uma grande queda de desempenho. Para melhorar isso temporariamente, podemos mudar seu tamanho tendo as seguintes opções:

Slide 62

Slide 62 text

Segmented Code Cache InitialCodeCacheSize – tamanho inicial do code cache, 160K default ReservedCodeCacheSize – valor padrão é 48MB CodeCacheExpansionSize – quantidade que pode ser adicionada ao code cache, 32KB or 64KB

Slide 63

Slide 63 text

Segmented Code Cache Para saber como está o uso do code cache temos a opção – XX:+PrintCodeCache e teremos uma saída semelhante a essa: CodeCache: size=xyzKb used=xyz max_used=xyz free=xyzKb

Slide 64

Slide 64 text

Segmented Code Cache É dividido em 3 partes: non-method segment: aramzenda o código interno relacionado à JVM, como o interpretador de bytecode. Por default, este segmento tem cerca de 5 MB. Além disso, é possível configurar o tamanho do segmento por meio do argumento -XX: NonNMethodCodeHeapSize

Slide 65

Slide 65 text

Segmented Code Cache É dividido em 3 partes: profiled-code segment: armazenda o código ligeiramente otimizado com tempos de vida potencialmente curtos. Tem como tamanho padrão 122 MB , podemos alterá-lo por meio do argumento -XX: ProfiledCodeHeapSize

Slide 66

Slide 66 text

Segmented Code Cache É dividido em 3 partes: non-profiled segment : armazena o código totalmente otimizado com tempos de vida potencialmente longos. Tem cerca de 122 MB por padrão. Este valor é, obviamente, configurável por meio do argumento -XX: NonProfiledCodeHeapSize

Slide 67

Slide 67 text

Execution Engine - Garbage Collector O Garbage Collector (GC) é responsável gerenciar de modo automático a alocação de memória da aplicação coordenando junto ao SO a quantidade de memória utilizada, a eliminação de objetos que já não estão mais sendo utilizados e assim determinar quando será necessário realizar uma limpeza para disponibilizar mais recursos.

Slide 68

Slide 68 text

Execution Engine - Garbage Collector Existem vários algoritmos de limpeza que se combinam na implementação do GC. Os mais comuns são:

Slide 69

Slide 69 text

Mark and Sweep Que percorre os objetos em memória sinalizando os que possuem referência e depois os percorre novamente limpando aqueles que não estão marcados

Slide 70

Slide 70 text

Copying Semelhante ao anteriror, porém no final copia de um buffer para outro ,organizando e memóeira durante a cópia e removendo a fragmentação existente.

Slide 71

Slide 71 text

Generational Separa a memória em gerações na qual cada passagem do GC pelo objeto incrementa sua "idade", tendo como resultado uma separação da seguinte maneira:

Slide 72

Slide 72 text

Garbage Collector - Generational Eden S0 S1 Old Generation (tenured) Permanent Generation Young Generation Survival Space Imagem baseada de :https://www.oracle.com/webfolder/technetwork/tutorials/ obe/java/gc01/index.html e do Livro Jornada Java , cap Garbage Collection, imagem 44.1

Slide 73

Slide 73 text

Eden -> onde todo novo objeto é alocado. Survivor Space -> onde ficam os objetos que já "sobreviveram" às primeiras limpezas e possuem referências válidas. Old Generation -> objetos com idade mais avançada. Permanent generation -> armazena os metadados de classes e métodos (a partir do JDK 8 essa sessão foi removida e as informações que antes ficavam nela ficam alocadas diretamente em memória).

Slide 74

Slide 74 text

Execution Engine - Garbage Collector GC é executado automaticamente pela JVM em intervalos regulares mas também pode ser disparado chamando System.gc ()

Slide 75

Slide 75 text

Execution Engine - Garbage Collector Serial GC Parallel GC Garbage First (G1) GC Nós temos 3 tipos de GC:

Slide 76

Slide 76 text

Execution Engine - Garbage Collector Serial GC: é destinado para aplicações pequenas que executam em ambiente single-thread,é a implementação mais simples do GC. O argumento da JVM para usar o Serial Garbage Collector é -XX:+UseSerialGC

Slide 77

Slide 77 text

Execution Engine - Garbage Collector Parallel GC: é o tipo default de GC da JVM. Usa múltiplas threads para garbage collection, mas permanece pausado quando a aplicação está em execução. O argumento da JVM para usar o Parallel Garbage Collector é - XX:+UseParallelGC.

Slide 78

Slide 78 text

Execution Engine - Garbage Collector Garbage First (G1): recomendado para aplicações multi-thread que tem grande espaço de heap disponível.A heap é dividida em espaços de tamanho iguais, G1 identifica as regiões com maior “lixo” e faz a coleta nessa região O argumento da JVM para usar o G1 Garbage Collector é -XX:+UseG1GC

Slide 79

Slide 79 text

Native Method Interface IMAGEM DE: HTTPS://WWW.GURU99.COM/JAVA-VIRTUAL-MACHINE-JVM.HTML

Slide 80

Slide 80 text

Native Method Interface É uma interface (como uma ponte) Que interage com as Native Method Libraries e provem as native libraries (C, C++).

Slide 81

Slide 81 text

Native Method Interface Isso permite que a JVM chame bibliotecas C/C++ e seja chamada por bibliotecas C/C++

Slide 82

Slide 82 text

Native Method Libraries IMAGEM DE: HTTPS://WWW.GURU99.COM/JAVA-VIRTUAL-MACHINE-JVM.HTML

Slide 83

Slide 83 text

Native Method Libraries São bibliotecas que são escritas em outras linguagens de programação (como assembly, C e C++). Essas bibliotecas geralmente estão presentes na forma de arquivos .dll ou .so.

Slide 84

Slide 84 text

Referências https://www.freecodecamp.org/news/jvm-tutorial-java-virtual-machine- architecture-explained-for-beginners/ https://www.geeksforgeeks.org/jvm-works-jvm-architecture/ https://www.guru99.com/java-virtual-machine-jvm.html Imergindo na JVM - otávio Santana Jornada Java - Capitulos - capitulos 43 e 44 https://www.baeldung.com/jvm-code-cache https://deviniciative.wordpress.com/2020/02/06/desmistificando-otimizacao- de-jvm/ https://www.udemy.com/course/java-application-performance-and-memory- management/

Slide 85

Slide 85 text

Obrigada :) https://www.linkedin.com/in/kamila-santos-oliveira/ https://www.instagram.com/kamila_code/ https://www.youtube.com/channel/Kamilacode