在 JVM 中 , 每当一个新的线程被创建 , 都会创建一个与之关联的私有 JVM 栈 。这个栈会随着线程的运行而进行入栈(push)和出栈(pop)操作 。它主要用于存储局部变量、操作数堆栈以及方法调用的情况 。
JVM 栈是由一系列栈帧(Stack Frame)组成的 。每当一个方法被调用 , 一个新的栈帧就会被压入栈中 , 每当一个方法调用结束 , 一个栈帧就会被弹出栈 。每个栈帧中都包含了局部变量表、操作数栈、动态链接和方法返回地址等信息 。
局部变量表主要存放了编译期可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference 类型 , 它不等同于指针 , 可能是一个指向对象起始地址的引用指针 , 也可能是指向一个代表对象的句柄或者其他与此对象相关的位置)和 returnAddress 类型(指向了一条字节码指令的地址) 。
操作数栈则是在执行字节码指令时用到的临时存储区 , 比如在进行算数运算时 , 操作数栈就会用来存放操作数和接收结果 。
Java虚拟机栈可能会抛出以下异常:
- 如果线程请求的栈深度大于 JVM 所允许的深度 , 将抛出 StackOverflowError 。
- 如果 JVM 栈可以动态扩展 , 当扩展时无法申请到足够的内存 , 会抛出 OutOfMemoryError 。
文章插图
3. 本地方法栈本地方法栈(Native Method Stack)也是线程私有 , 生命周期与线程相同 。作用是与虚拟机栈类似 , 虚拟机栈是为Java 方法服务的 , 而本地方法栈是为 Native 方法服务的 。
和虚拟机栈一样 , 本地方法栈的大小可以是固定的也可以是动态的 。如果是固定的 , 当线程请求的栈深度超过最大深度时 , 会抛出 StackOverflowError 。如果是动态的 , 并且在尝试扩展时无法申请到足够的内存 , 会抛出 OutOfMemoryError 。
4. 堆堆(Heap)是 JVM 所管理的最大一块内存空间 , 也是所有线程共享的一块内存区域 , 在虚拟机启动时创建 。堆主要用于存储对象实例和数组 , 这也是 Java 垃圾回收器主要活动的区域 。
在物理上 , 堆区可以处于分散的内存空间中 , 但在逻辑上它被视为连续的 。堆区在 JVM 启动时创建 , 如果堆区的空间不足 , 将会抛出 OutOfMemoryError 。
堆分为新生代(Young Generation)和老年代(Old Generation) 。新生代又分为 Eden 区、From Survivor 区(简称 S0)、 To Survivor 区(简称 S1) 。划分这么多区域的目的是为了更好地回收内存 , 或者更快地分配内存 。
新生代中各个区域的内存占比分别是 , Eden : S0 : S1 = 8 : 1 : 1
新创建的对象优先在 Eden 区进行分配 。当 Eden 区满时 , 会触发一次 Minor GC(新生代垃圾回收 , 也叫 Young GC) , 将仍然存活的对象从 Eden 区和 S0 区移动到 S1 区 , 下次 Minor GC 处理情况类似 , 把存活的对象从 Eden 区和 S1 区移动到 S0 区 。当 Survivor 区也满了 , 还存活的对象会被移动到老年代 。如果老年代也满了 , 将会触发 Major GC(老年代垃圾回收 , 也叫 Old GC) 。当老年代满了 , 也可能触发 Full GC , Full GC 会对整个堆内存进行垃圾回收 , 包含新生代、老年代和方法区 。Full GC 会导致较长的停顿时间 , 并且会消耗大量的系统资源 。
【面试必问,JVM内存模型扫盲】
文章插图
推荐阅读
- 女孩|我,面试一个女生,准备30万录用她,不料发现她简历造假,放弃了
- 公务员面试紧张怎么办
- 跳槽|面试过程中,特别难回答的十大问题,相信你也对此为难过!
- hr|为什么HR面试从不当面拒绝,而是让你回去等通知?
- hr|我,50岁失业,多次面试都因年龄被拒绝,中老年人再就业真的太难
- hr|为什么HR不告知面试未通过原因?
- 求职|你面试不通过的主要原因?
- 国企|中国烟草广招人才,月薪超9000且无需笔试,面试通过就能被录用
- 求职|有哪些面试技巧
- 乌克兰|量体裁衣吗?国企招聘要求一本,两个北大被拒,面试官质问其动机