Java面试之JVM(1)内存模型

以下内容来自网络整理,侵删

JVM内存模型

程序计数器(program counter register)

(1)线程执行的字节码的行号指示器。通过改变这个值,选取下一条执行的字节码指令。实现 分支、循环、跳转、异常处理、线程恢复。
(2)线程私有,生命周期与线程相同。线程间,互不影响
(3) 较小的内存空间,几乎可以忽略不计。也是运行速度最快的存储区域。
(4)执行Java方法,指向正在执行的字节码指令;执行native方法,值为空。Undefined。
(5) 唯一一个没有OutOfMemoryError的区域。

Java虚拟机栈(Java virtual machine stacks)

(1)是什么:每个线程在创建时都会创建一个虚拟机栈,其内部保存一个个的栈帧,对应着一次次方法调用。
(2)生命周期:是线程私有的,它的生命周期与线程相同
(3)作用:主管Java程序的运行,它保存方法的局部变量、部分结果,并参与方法的调用和返回
(4)栈帧:每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法返回地址等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
(5)局部变量表:局部变量表是编译期可知的。大小确定,运行期间不会改变。提前存放了基本类型,引用类型,返回地址等
(6)操作数栈:主要用于保存计算过程的中间结果,同时作为计算过程中变量
(7)异常:如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果虚拟机栈可以动态扩展,当扩展时无法申请到足够的内存时会抛出OutOfMemoryError异常

本地方法栈(native method stack)

与虚拟机栈类似,但是是为native方法服务的。可以抛出StackOverflowError和OutOfMemoryError

Java堆(Heap)

在这里插入图片描述

(1)是什么:线程共享的内存,用来存放对象实例。几乎所有的对象实例都会放在堆中。是垃圾回收的主要区域。
(2)Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可,就像我们的磁盘空间一样。
(3)内存细分:如果从内存回收的角度看,由于现在垃圾收集器基本都是采用的分代收集算法,所以Java堆中还可以细分为:新生代、老年代和元空间;新生代分为伊甸园空间和两个存活区等。
(4)对象分配过程
a. new的对象先放伊甸园区。此区有大小限制。
b. 当伊甸园的空间填满时,程序又需要创建对象,JVM的垃圾回收器将对伊甸园区进行垃圾回收(MinorGC),将伊甸园区中的不再被其他对象所引用的对象进行销毁。再加载新的对象放到伊甸园区
c. 然后将伊甸园中的剩余对象移动到幸存者0区
d. 如果再次触发垃圾回收,此时,上次幸存下来的放到幸存者0区的,如果没有回收,就会放到幸存者1区
e. 如果再次经历垃圾回收,此时会重新放回幸存者0区,接着再去幸存者1区。
f. 何时去老年代? 可以设置次数
g. 如果老年代内存不足,就会触发full gc,对整个块进行回收
(5)异常:如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常。
a. 对象优先分配在Eden区,如果Eden区没有足够的空间时,虚拟机执行一次Minor GC
b. 大对象直接进入老年代.这样做的日的是避免在Eden区和两个Sirvivor区之间发生大量的内存拷贝
c. 长期存活的对象进入老年代。虚拟机为每个对象定义了一.个年龄计数器,如果对象经过了1次Minor GC那么对象会进入Survivor区,之后每经过一次Minor GC那么对象的年龄加1,直到达到阀值,对象进入老年区
d. 动态判断对象的年龄。如果Survivor区中相同年龄的所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象可以直接进入老年代。
e. 空间分配担保。每次进行Minor GC时,JVM 会计算Survivr区移至老年区的对象的平均大小,如果这个值大于老年区的剩余值大小则进行一次Full GC. 如果小于,则检查HandlePromoctionFailure设置,如果true则只进行Minor GC,如果 false则选行Full GC

方法区(Method Area)

在这里插入图片描述

(1)是什么:方法区(Method Area)与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息等数据。虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫做Non-Heap(非堆),目的应该是与Java堆区分开来。
(2)历史演进:方法区是一个 JVM 规范,永久代或者元空间都是其一种实现方式。在 JDK 1.8 之后,原来永久代的数据被分到了堆和元空间中。元空间存储类信息,字符串常量和运行时常量池等放入堆中。
(3)元空间与直接内存:元空间使用的是直接内存。
直接内存并不是虚拟机运行时数据区的一部分,也不是虚拟机规范中定义的内存区域,但是这部分内存也被频繁地使用。而且也可能导致 OutOfMemoryError 错误出现。
(3)异常:根据Java虚拟机规范的规定,当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。
(4)运行时常量池:属于方法区的一部分。
Class文件中包含了: 版本、字段、方法、接口、常量池(constant pool table)。Class中常量池存放了编译生成的 字面量、符号引用。 这些东西在类被加载后会进入到方法区的运行时常量池里面存放。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值