欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

JVM的简介及内部结构

程序员文章站 2022-04-27 11:12:38
JVM介绍1.jvm(java virtual machine)java程序的跨平台我们编写一个helloWorld.java,通过javac命令生成helloWorld.class字节码文件,再通过java命令由jvm生成机器码。跨平台特性: 我们只需编写一份代码,可以在不同操作系统中执行。但是不同的操作系统它底层硬件与指令存在区别,那java如何做到一份代码在不同操作系统中运行的呢?原因: 在oracle官网提供不同操作系统的JDK,不同JDK里面也就包含不同的JVM。在通过java命令根据...

JVM介绍

1.jvm(java virtual machine)

  1. java程序的跨平台
    我们编写一个helloWorld.java,通过javac命令生成helloWorld.class字节码文件,再通过java命令由jvm生成机器码。
    跨平台特性: 我们只需编写一份代码,可以在不同操作系统中执行。但是不同的操作系统它底层硬件与指令存在区别,那java如何做到一份代码在不同操作系统中运行的呢?
    原因: 在oracle官网提供不同操作系统的JDK,不同JDK里面也就包含不同的JVM。在通过java命令根据不同操作系统的JVM生成不同的机器码,这样就完成了跨平台的效果。
  2. JVM内部大概运行流程
    JVM的简介及内部结构
    上图中JVM虚拟机分为大致的三部分:类装载子系统内存模型(虚拟机内存区域)字节码执行引擎
    A.Math.java通过javac命令生成Math.class字节码文件
    B.Math.class通过java命令,JVM中的类装载子系统会将字节码文件加载到JVM内存区域,最终由字节码执行引擎运行虚拟机内存区域中的方法区里的代码,生成机器码。

2.实例分析

public class hello_test {
   public int math(){
       int a =11;
       int b = 20;
       int c = a + b;
       return c;
   }
   public static void main(String[] args) {
       hello_test helloTest = new hello_test();
       int a = helloTest.math();
       System.out.println(a);
   }
}	

一:当程序运行时,会根据线程为其分配 栈(线程) 内存空间,用来存放线程中用到的局部变量。
二:栈中又包含一个个栈帧,栈帧用来存放线程中方法用到的方法局部变量。上面代码有两个方法,一个main方法和一个math方法。栈帧采用栈的数据结构进行存储(先进后出),上面程序先运行main方法,就先将main()-栈帧存入栈中,当运行到int a = helloTest.math();,又将math()-栈帧存入栈中,而当math()方法运行完,整个math()-栈帧移出栈。
三:栈帧中包含:局部变量表操作数栈动态链接方法出口
JVM的简介及内部结构
四:局部变量表、操作数栈后面通过代码进行说明。类中的方法放在方法区(元空间),而栈帧中的动态链接则是记录是方法存放的地址,程序会根据地址去方法区找到位置进行执行。
五:方法出口:字节码执行引擎执行完helloTest.math();后,需要回到主方法继续执行下面代码。那程序怎么知道该回到那里执行,所以方法出口也就是记载此方法执行完后,该去哪里执行。当然有返回值的时候,返回值是保存在方法出口里。
六:通过字节码文件查看局部变量表操作数栈的作用
想通过代码分析JVM内部机制,则需对java文件转成字节码文件(.class),但是字节码文件是让JVM运行,可读性不强,这里需要将.class文件反汇编,方便我们查阅。具体操作如下:
A.在java文件位置处打开Windows终端,执行javac命令生成.class文件
B.执行javap -c xxx.class > xxx.txt ,对代码进行反汇编的内容保存在txt文本中
方法一:如果使用eclipse工具编程,选中类名,点击右键,选择show in —>terminal。在下方弹出来的控制台执行A、B两步。生成txt文件。
方法二:如果使用idea工具编程,选中类名,点击右键,选择open in terminal。在下方弹出来的控制台执行A、B两步。生成txt文件。
方法三:在电脑本地找到你写的java文件,cmd打开Windows终端,执行A、B两步。生成txt文件。
生成的txt文件如下:
JVM的简介及内部结构

通过对math()方法的分析,加深局部变量表操作数栈的认识。根据上面的内容去oracle官网网站查询JVM指令手册,理解具体执行含义。
0: bipush 11
查询JVM指令手册:0x10 bipush 将单字节的常量值(-128~127)推送至操作数栈
就是先将11这个值放进操作数栈
2: istore_1
查询JVM指令手册:0x3c istore_1 将操作数栈int型数值存入第二个本地变量
这里需要解释一下,第一个本地变量默认为this。看上面代码不难看出,第二个变量就是a,这条代码也就是将操作数栈中保存的11赋值给变量a
3: bipush 20
查询JVM指令手册:0x10 bipush 将单字节的常量值(-128~127)推送至操作数栈
就是将20这个值放进操作数栈
5: istore_2
查询JVM指令手册:0x3d istore_2 将操作数栈int型数值存入第三个本地变量
就是将操作数栈中保存的20赋值给变量a
6: iload_1
查询JVM指令手册:0x1b iload_1 将第二个int型本地变量推送至操作数栈
就是将变量a的值放在操作数栈
7: iload_2
就是将变量b的值放在操作数栈
8: iadd
查询JVM指令手册:0x60 iadd 将操作数栈两int型数值相加并将结果压入操作数栈

通过上面可以看出局部变量表存放变量的、操作数栈临时存放数据以及做运算时使用。
七:我们都知道java是多线程运行,当优先级更高的线程抢走CPU的时间片后,当前线程就会被挂起。当挂起线程被唤起运行时,又是如何知道挂起前运行到哪里?这时候就需要程序计数器。当字节码执行引擎运行完一段程序,就会在程序计数器记录一下位置,这样即使被挂起,也知道程序是在哪里停止的。

本文地址:https://blog.csdn.net/study_study_know/article/details/110205839

相关标签: java jvm