jvm诸葛老师笔记

jvm

jvm简单介绍

jvm诸葛老师笔记_第1张图片
从这张图我们可以清楚的看出来 我们写好的java代码是先经过编译生成class文件
然后才是我们jvm 要做的部分 意思就是java是面向编译之后的class文件产生的 用来屏蔽不同的操作系统在底层和硬件指令上的区别 把class文件翻译成为无论是什么机器都可以 "看懂"的机器码

一个简单的Math运行过程

jvm诸葛老师笔记_第2张图片

public class Math {
     
    public static final int initDate = 666;
    public User user = new User();

    public Math() {
     
    }

    public int compute() {
     
        int a = 1;
        int b = 2;
        int c = (a + b) * 3;
        return c;
    }

    public static void main(String[] args) {
     
        Math math = new Math();
        math.compute();
    }
}
  1. 就是将class文件加载进类加载子系统
  2. 开辟一个包含 堆,方法区,栈,本地方法栈,程序计数器的空间
  3. 字节码引擎开始执行

课中主要讲解的就是jvm运行空间

栈功能

	栈也叫虚拟机栈,每开辟一个线程就会有一个栈空间被开辟出来 

栈的组成

栈实际上就是栈帧组成的, 而每一个栈帧又存储着与之对应的方法的局部变量表,操作数栈,动态链接,方法出口
也就是一个方法对应一个栈帧 栈帧就是java中每个方法的存放空间
局部变量表 : 存放着方法中的局部变量
操作数栈: 用来操作方法中的数的一个临时栈
动态链接:把符号引用存在直接应用存在内存空间中
方法出口: 记录该方法调用完毕应该回到的地方 (放到我们这个例子中就是回到Main函数的下一行)

下面是Math.java反编译的结果
具体分析compute()函数的指向流程 来深刻的理解帧栈这个空间

Compiled from "Math.java"
public class com.shen.Main.jvm.Math {
  public static final int initDate;

  public com.shen.Main.jvm.User user;

  public com.shen.Main.jvm.Math();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."":()V
       4: aload_0
       5: new           #2                  // class com/shen/Main/jvm/User
       8: dup
       9: invokespecial #3                  // Method com/shen/Main/jvm/User."":()V
      12: putfield      #4                  // Field user:Lcom/shen/Main/jvm/User;
      15: return

  public int compute();
    Code:
       0: iconst_1
       1: istore_1
       2: iconst_2
       3: istore_2
       4: iload_1
       5: iload_2
       6: iadd
       7: iconst_3
       8: imul
       9: istore_3
      10: iload_3
      11: ireturn

  public static void main(java.lang.String[]);
    Code:
       0: new           #5                  // class com/shen/Main/jvm/Math
       3: dup
       4: invokespecial #6                  // Method "":()V
       7: astore_1
       8: aload_1
       9: invokevirtual #7                  // Method compute:()I
      12: pop
      13: return
}

栈帧的局部变量其实是用一个数组进行存储的
其中特殊的局部变量0就是this
public int compute();
Code:
0: iconst_1 将局部变量1 放入到操作数栈
1: istore_1 将int类型的值存入局部变量1(将int值赋给在局部变量表的局部变量)
2: iconst_2
3: istore_2
(这就明白了 这两个实际上指行的就是 现在局部变量表中开辟一个b的空间 然后在从操作数栈中弹栈赋给局部变量b)
4: iload_1 //局部变量1压入栈
5: iload_2 //局部变量2 压入栈
6: iadd //弹栈两次 执行int 类型的add
7: iconst_3 //将计算结果 压入栈
8:bipush //将 10压入栈
9: imul //计算乘法结果 在压入栈中
10: istore_3 //将结果存给局部变量3
11: iload_3 //取出局部变量3的值
12: ireturn //return int

局部变量表

存放的就是地址 (如果指向的是对象的话) 也就是math

程序计数器

属于线程私有 用来存放线程执行代码的位置(就是.class文件中的行号) 由字节码执行引擎来操作

方法区

常量 (静态常量)

静态变量(指向堆空间)

方法信息

存放各种new出来的对象
局部变量表会指向
方法区 中的静态变量也会指向

堆结构和垃圾搜集过程jvm诸葛老师笔记_第3张图片

//垃圾搜集都是字节码执行器在做

  1. new 出来的对象都会往 Eden(伊甸)区放 然后满了 会进行minor gc
  2. 存活的放到s0中
  3. 再次满了 再次搜集s0和Eden存活对象 放到s1中
  4. …s1,eden–>s0 不断调换
  5. 年龄到达15的 进入老年区
  6. 老年区满了 会启动full gc 启动full gc时候必须暂停所有执行的代码也就是STW(stop the world) 因为我们的对象必须要有一个确定的状态 不暂停的话就无法确定

一个jvm调优案例

jvm诸葛老师笔记_第4张图片

你可能感兴趣的:(jvm,jvm)