乐趣区

关于java:JVM虚拟机整体结构简单介绍

前言

本文将具体解说 JVM 整体的构造,以及各个构造的里的具体形成与作用


一、JVM 是什么?

JVM 百度百科介绍 简略来说 JAVA 是运行在 JVM 下面的,没有 JVM 那么 JAVA 文件是无奈运行的

二、JVM 组成构造

  1. 办法区
  2. 本地办法栈
  3. 程序计数器

**JVM 结构图:**

三、JVM 构造详解


栈是 JVM 重要的组成部分,每有一个新的线程都 JVM 都会为其在栈上调配一份内存,线程里有栈帧,程序计数器。另外线程栈内存大小决定的线程数量的多少,当线程栈内存大小设置的越大,则同时存在的线程数量越少,反则越大。另外在栈中最容易产生的谬误是StackOverflowError 栈溢出,看以下代码:

 public class StackOverflowTest { 
   static int count = 0;
    static void redo() { 
    count++; 
     redo();}
     public static void main(String[] args) { 
      try {redo(); 
     } catch (Throwable t) {t.printStackTrace(); 
     System.out.println(count); 
             } 
         } 
     }  
      运行后果:java.lang.StackOverflowError 
复制代码

栈帧构造组成

  1. 局部变量表: 次要用来保留申明的局部变量以及办法的参数信息, 局部变量表作用于为以后办法,当办法执行实现后,局部变量表也会随之删除,开释内存。另外局部变量表里用来保存信息的叫做变量槽(slot)

  1. 操作数栈:顾名思义,操作数栈其本质就是个栈,压栈,出栈两个操作,例如执行 a +b,先将局部变量表中的 a 与 b 别离压入栈中,接着执行加法操作,最终出栈。
  2. 动静链接: 是在程序运行期间实现的将符号援用替换为间接援用叫动静链接,既然有动静链接那么天然也有动态链接,局部符号援用在类加载阶段 (解析) 的时候就转化为间接援用, 这种转化为动态链接。
  3. 办法返回地址: 在办法退出 (失常执行 / 异样返回) 后,返回办法被调用的地位。

** 栈帧结构图 **

2. 程序计数器

程序计数器是 JVM 十分重要的一个构造,是线程公有的,每个线程独有一份,它用来保留指向下一条将被执行指令的地址,例如当线程被阻塞再进行唤醒时,从程序计数器读取指令的地址,从而继续执行。

3. 本地办法栈

本地办法栈次要是为了执行 native 办法,保留 native 办法进入区域的地址,所以本地办法栈也是线程公有的内存区域。

4. 办法区

被所有的线程共享。办法区蕴含所有的 class 和 static 变量,类的办法代码,变量名,办法名,拜访权限,返回值等等都是在办法区的。


堆是十分重要的一个区域,治理着简直所有的对象,咱们常说的垃圾回收的次要区域就是产生在这个区域。堆分为新生代 (young) 与老年代(Old),新生代又分为 Eden 与 survivor 区,survivor 分为 From 区与 To 区。这几个区寄存着 java 的对象,当区内存不够的时候会产生 GC,GC 次要分为两种,一种是 minorGC(Young GC),另一种是 Full GC,JVM 调优次要就是缩小 Full GC 的次数。

逃逸剖析

首先大家听得最多的就是 new 进去对象是寄存在堆中的,然而在上文中,所写的是简直对象是存在堆中,那么为什么是简直呢,因为有的对象是寄存在栈中的,是不是很不堪设想,接下来来看下一段代码。

// 办法一
public Person test1() {Person person = new Person();
        person.setId(1);
        return person;
        } 
// 办法二 
public void test2() {User person = new person(); 
         person.setId(1); 
       }
复制代码

上述代码中很显然 test1 办法中的 personr 对象被返回了,那么这个对象就可能被其余办法进行援用,test2 办法中的 personr 对象,当办法完结的时候,该对象就是一个有效对象了,不会在其余中央被进行援用,对于这样的对象,JVM 将其调配的栈内存里,让其在办法完结时追随栈内存一起被回收掉,缩小堆内存的回收。JVM 对于这种状况能够通过开启逃逸剖析参数 (-XX:+DoEscapeAnalysis) 来优化对象内存调配地位,JDK7 之后默认开启逃逸剖析,如果要 敞开应用参数(-XX:-DoEscapeAnalysis)

总结

  1. 运行时数据区次要由 程序计数器 办法区 本地办法栈
  2. 线程栈、程序计数器、本地办法栈都是线程公有的区域,堆、办法区是线程共享的区域。
  3. 堆分为细分为 Eden、From、To、老年代
  4. 对象不全都是在堆中,没有产生逃逸的对象在栈中。

参考:《2020 最新 Java 根底精讲视频教程和学习路线!》

链接:https://juejin.cn/post/692200…

退出移动版