深入浅出 Java 中 JVM 内存管理你了解吗?


小编最近回顾Java基础,跟着小编一起学习吧!最近都会发表一些基础,一起学习进步吧!

java岗位面试,JVM是对程序员基本功考察,通常会问你对JVM了解吗?

可以分几部分回答这个问题,首先JVM内存划分 | JVM垃圾回收的含义 | 有哪些GC算法 以及年轻代和老年代各自特点等等。

1) JVM内存划分:

① 方法区 (线程共享) 常量 静态变量 JIT(即时编译器)编译后代码也在方法区存放

② 堆内存(线程共享) 垃圾回收的主要场地

③ 程序计数器 当前线程执行的字节码的位置指示器

④ Java虚拟机栈(栈内存) :保存局部变量,基本数据类型以及堆内存中对象的引用变量

⑤ 本地方法栈 (C栈):为JVM提供使用native方法的服务

通过这幅图了解一下

深入浅出 Java 中 JVM 内存管理你了解吗?


JDK 1.8同JDK 1.7 最大的区别是:元数据取代了永久代.元空间的本质和永久代类似,都是对JVM规范中的方法区的实现.其元空间和永久代之间的最大区别在于:元数据空间不在虚拟机中,而是在本地内存中

详细了解一下各个部分

01)程序计数器(PC寄存器)

程序计数器的定义: 程序计数器是一块较小的内存空间,是当前线程正在执行的哪一条字节码指令的地址,若当前线程正在执行的是一个本地方法,那么此时程序计数器为Undefined

程序计数器的作用:

  • 字节码解释器通过改变程序计数器来依次获取指令,从而实现代码的流程的控制
  • 在在多线程情况下,程序计数器记录的是当前线程执行的执行的位置,从而当线程切换回来时,就知道上次线程执行到哪了

程序计数器的特点

  • 是一块较小的内存空间
  • 线程私有,每个线程都有自己的程序计数器
  • 生命周期:随着线程的创建而创建,随着线程的销毁而销毁
  • 是一个唯一不会出现的OutOfMemoryError的内存区域


02)Java虚拟机栈

定义: 描述Java方法运行过程的内存模型

Java虚拟机栈会为每一个即将运行的Java方法创建一块叫做"栈帧"的区域,用于存放该方法运行过程中的一些信息,如 局部变量表 /操作数栈 /动态链接 /方法出口信息 .............

深入浅出 Java 中 JVM 内存管理你了解吗?


压栈出栈过程:

当方法运行过程中需要创建局部变量时,就将局部变量的值存入栈帧的局部变量表中

Java虚拟机栈的栈顶是当前正在执行的活动栈,也就是当前正在执行的方法,PC寄存器也会指向这个地址,只有这个活动的栈帧的本地变量可以被操作数栈操作,当前这个栈帧中调用另一个方法,与之对应的额栈帧又会被创建,新创建的栈帧压入栈顶,变成当前的活动栈帧,方法结束后,当前栈帧的返回值变成新的活动栈帧的中的操作数栈的一个操作数,如果没有返回值,那么新的活动栈帧中操作数栈的操作数没有变化

由于Java虚拟机栈是线程对应的,数据不是共享的,因此不用关心数据一致性问题,也不会存在同步锁的问题

特点

  • 局部变量表随着栈帧的创建而创建,他的大小在编译时确定,创建时只需分配事先规定的大小即可,在方法运行的过程中,局部变化表的大小不会发生变化
  • Java虚拟机栈会出现两种异常:StackOverFlowError和OutOfMemoryError
  • StackOverFlowError若Java虚拟机栈的大小不允许动态扩展,那么当前线程请求的栈的深度超过当前的Java虚拟机栈的最大深度是,就会抛出此异常
  • OutOFMemoryError,若允许动态扩展,那么当前线程的请求的栈内存用完了,无法再动态扩展时,抛出此异常
  • Java虚拟机栈也是线程私有,随着线程创建而创建,随着线程的结束而销毁


03)本地方法栈(C栈)

定义: 是为了JVM运行native方法准备的空间,由于很多native方法都是用C语言实现的,所以通常又叫C栈,它与Java虚拟机栈实现的功能类似,只不过本地方法栈描述本地方法运行过程的内存模型

栈帧变化过程:

本地方法被执行时,在本地方法栈也会创建一块栈帧,用于存放该方法的局部变量表 /操作数栈 /动态链接 /方法出口等信息; 方法结束后,相应的栈帧也会出栈,并释放内存空间.也会抛出StackOverFlowError和OutOfMemoryError异常

04) 堆

定义: 堆是用来对象的内存空间,几乎所有的对象都存储在堆中

特点:

  • 线程共享,整个Java虚拟机只有一个堆,所有线程都访问同一个堆.
  • 在虚拟机启动时创建
  • 是垃圾回收的主要场地
  • 进一步可分为:新生代(Eden区 From Survior To Surviror) 老年代
  • 不同的区域存放的不同生命周期的对象,这样可以根据不同区域使用不同的垃圾回收算法,更具有针对性. 堆的大小也可以固定也可以扩展,对于主流的虚拟机,堆大小可扩展的,因此当线程请求分配的内存,但堆已满,且内存已无法再扩展,就抛出OutOfMemoryError异常


05)方法区

定义: Java虚拟机规范中定义方法区是堆的一个逻辑部分,方法区存放以下信息 已被虚拟机加载的类信息 /常量 /静态变量 /即时编译后代码

特点:

  • 线程共享.方法区是堆的一个逻辑部分,因此和堆一样,都是线程共享,整个虚拟机中只有一个方法区
  • 永久代 方法区中的信息一般需要长期存在,而且它又是堆的逻辑分区,因此用堆的划分方法,把方法区称为"永久代"
  • 内存回收的效率低.方法区中的信息一般需要长期存在,回收一遍只有少量信息无效.主要回收的目标是: 对常量池的回收;对类型的卸载
  • Java虚拟机规范l对方法区的要求比较宽松,和堆一样,允许固定大小.也允许动态扩展,还允许不实现垃圾回收


运行时常量池:

方法区中存放:类信息 常量 静态变量 即时编译器变编译后代码.常量就存放在运行时常量池中.当类被Java虚拟机加载后,.class文件中的常量就存在方法区的运行常量池,而且在运行期间,可以向常量池中添加新的常量,如String类的intern()方法就能在运行期间向常量池中添加字符串常量

你必须很努力,然后看起来才毫不费力!

关注我每天都有干货,看下期哦。


分享到:


相關文章: