由浅入深了解JVM-程序计数器

从硬件的角度来说,它是一个寄存器,当然在jvm中它是被虚拟化出来的一个寄存器,它的寄存功能是用来寄存当前线程所执行的字节码的行号。特性:占用内存较小,线程私有,不会抛OutOfMemoryError异常,存的是一个地址,不是整数值,但是可以理解成只需要暂存一个整数。其实程序计数器的功能与特性也就差不多这些,但有两个疑问,程序正常执行的时候为何要记住当前行?当前行的地址在哪里?

为何要记住当前行

程序计数器是一个线程私有的,一个线程在一个时间片内可能执行不完,例如A线程执行到第5行时,时间片用完了,或者被高优先级的线程插队,总而言之线程A不能往下执行了,也就是所谓的挂起,那么当线程A重新回到运行状态时,于情于理都应该从第5行开始往下执行,这里的第5行就存放在线程A私有的程序计数器中。总之,使用程序计数器是为了在线程挂起时,当再次回到运行状态时,能够保证线程恢复到原来的位置。

当前行的地址在哪里

在分析虚拟机栈时,当时有如下一段代码以及其对应的字节码:

源程序:

public class JVMTest {
    
    
    public int add(){
    
    
        int a = 3;
        int b = 10;
        int c = a+b;
        return c;
    }
    public static void main(String[] args) {
    
    
        JVMTest jvmTest = new JVMTest();
        int result = jvmTest.add();
        System.out.println("The result is : "+result);
    }
}

字节码:

Compiled from "JVMTest.java"
public class com.research.JVMTest {
    
    
  public com.research.JVMTest();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public int add();
    Code:
       0: iconst_3
       1: istore_1
       2: bipush        10
       4: istore_2
       5: iload_1
       6: iload_2
       7: iadd
       8: istore_3
       9: iload_3
      10: ireturn

  public static void main(java.lang.String[]);
    Code:
       0: new           #2                  // class com/research/JVMTest
       3: dup
       4: invokespecial #3                  // Method "<init>":()V
       7: astore_1
       8: aload_1
       9: invokevirtual #4                  // Method add:()I
      12: istore_2
      13: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
      16: iload_2
      17: invokedynamic #6,  0              // InvokeDynamic #0:makeConcatWithConstants:(I)Ljava/lang/String;
      22: invokevirtual #7                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      25: return
}

通过字节码可以发现每一个指令前都有一个数字,这个数字就是当前指令的地址,例如main方法中iload_2指令,它的地址就是16,当程序执行到iload_2时,可以理解成程序计数器中存放的是16,当然真正存放的是一段地址。
个人觉得jvm中程序计数器理解到这应该差不多了,如果想进一步的了解寄存器推荐看一下汇编语言。
至于jvm其他部分的工作原理请参考如下博文:
由浅入深了解JVM-内存结构
由浅入深了解JVM-堆
由浅入深了解JVM-虚拟机栈

猜你喜欢

转载自blog.csdn.net/hongyinanhai00/article/details/113871313