Java虚拟机内存划分---Java代码如何运行的?

Java虚拟机的作用?

了解这个问题前,先搞清两个问题:
1.Java为何称为“高级”语言?
2.Java为何能一次编译多次(多系统)运行?
Ok!慢慢道来,众多周知硬件只能识别由二进制组存的机器语言,而机器语言则难以让人阅读;即便C语言
等编译后可直接转化为二进制的语言也是让人费解,于是更接近人类思维逻辑的“高级”语言便孕育而生;如java和现时火热的Python,但由于其高度抽象,也并不适合直接在硬件上运行。因此作为高级语言和机器语言间的枢纽虚拟机便诞生了,与此同时由于虚拟机的出现,只要装有支持Java的虚拟机的操作系统便可运行编译后的Java文件.class。虚拟机同时还承担着内存对象生命周期的管理、数组越界、动态类型、安全权限等,省去了非业务逻辑的开发。

JVM虚拟机运行时数据?

由.java文件经编译后的.class文件,此处省略1万字解释啥是编译器。
作者lyt图1-1Java虚拟机运行时数据区

Java堆(Heap)

是Java虚拟机管理所占内存中最大的一块(其次大的是java方法栈),存在于线程共享的内存区,在虚拟机启动时创建。此区域唯一目的就是存放对象实例,几乎所有对象实例都在这分配内存,为何不是100%?JIT编译器,栈上分配、变量替换了解一下。
同时Java堆也是垃圾收集器管理的主要区域,同时也被称为“GC堆”(Garbage Collected Heap)。由于内存回收的进步,Java堆中还分为:新生代、老年代,TLAB等,但存储的仍是对象实例。在此不做过多描述,后续会专题讲解GC回收及内存分配空间不连续等问题。

方法区(Method Area)

也存在于线程共享的内存区,存储已被加载的类信息、常量、静态变量、即时编译器编译后的代码等;然而方法区的规范非常的宽松,不需要连续的内存和可选择固定大小或者扩展,甚至可以不选择垃圾回收,因此方法区的回收效果难以尽如人意;所以要求开发者在有关方法区编码时有所顾虑,其中著名的异常“OutOfMemoryError”就常出于此处。

程序计数器(Program Counter Register)

是寄存器的一种,然而它的作用仅仅是为了让CPU可以按顺序执行代码的临时寄存器;它记录着当前线程执行字节码的行号,而字节码解释器(CPU仍然无法识别字节码,需要字节码解释器)就是通过改变计数器的值来选取下一条执行字节码,分支、循环、跳转、异常处理、线程恢复等执行都需要计数器来完成。每个线程占有独立空间,拥有独立的计数器,各自互不影响;
值得一提的是,如果线程执行一个java方法则记录着正在执行的虚拟机字节码指令地址;如果线程执行的是Native方法则计数器为空(Undefined)。

Java虚拟机栈

它描述着的是Java方法执行的内存模型:每个方法都会创建一个帧栈,用于存放局部变量、操作数栈、动态链接、方法出口等信息;每一个方法的调用到执行完成,就对应着一个帧栈在虚拟机栈中入栈到出栈的过程,下图展示出入栈的信息:

 public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: new           #1                  // class Exception/Foo
         3: dup
         4: invokespecial #37                 // Method "<init>":()V
         7: invokevirtual #38                 // Method test:()V
        10: return
      LineNumberTable:
        line 21: 0
        line 22: 10
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      11     0  args   [Ljava/lang/String;
}
SourceFile: "Foo.java"

stack :最大操作数栈,JVM运行时会根据这个值来分配栈帧(Frame)中的操作栈深度,此处为2;
locals:局部变量所需的存储空间,单位为Slot, Slot是虚拟机为局部变量分配内存时所使用的最小单位,为4个字节大小;
args_size:方法参数的个数,这里是1,因为每个实例方法都会有一个隐藏参数this;(此处简单介绍,有兴趣自学JAVA字节码)

本地方法栈(Native Method Stack)

与Java虚拟机栈一样,只不过为Native方法服务,虚拟机规范中并无强制规定,具体的过程视对应的虚拟机而定。

了解上述模块,可知.class中的字节码进入方法区,虚拟机会执行其中的代码,在堆中分配实例对象空间,并在栈中执行;在运行过程中,每当调用进入一个 Java 方法,分配帧栈并经过入栈出栈等过程。
当然,Java 字节码无法直接执行。因此,Java 虚拟机需要将字节码翻译;如下图描述:
截图来源为极客时间郑雨迪老师讲义
图1-2 截图来源为极客时间郑雨迪老师讲义(自认为无法更好表达该知识点,故截图摘抄,仅自我学习用)

总结

至此Java代码的运行过程大致描述清楚,更详细的请自行学习,也会不定期更新补全相关知识点。
1.虚拟机的作用?—向硬件解释字节码,同时管理内存对象生命周期、数组越界、动态类型、安全权限等。
2.虚拟机运行时相关数据的存放?—方法区存放类信息、常量、静态变量等;存放对象实例…
3.Java字节码的运行过程?—初始化各种内存空间后,便执行字节码,同时向硬件解释其意义。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值