常见面试题
百度 三面:说一下JVM内存模型吧,有哪些区?分别干什么的?
- Java虚拟机栈: 每个线程独有,主要用于控制程序运行,保存局部变量 动态链接
- 堆空间: 主要存储类的实例对象数据
- 方法区: 主要存放类的类型信息 域信息 运行时常量池 方法信息
- 本地方法区: 主要用于非java实现方法的调用
- 程序计数器: 保存当前程序指令地址
蚂蚁金服: Java8的内存分代改进 JVM内存分哪几个区,每个区的作用是什么? 一面:JVM内存分布/内存结构?栈和堆的区别?堆的结构?为什么两个survivor区? 二面:Eden和survior的比例分配
- 栈
- 线程私有不存在线程安全问题
- 主要 局部变量表 等方法的信息
- 每调用一个方法会压入一个栈帧到栈中
- 堆
- 主要用于存储真实的对象实例数据
Eden:Survior0:Survior1 = 8:1:1 (默认)
小米: jvm内存分区,为什么要有新生代和老年代
核心目的为了减少GC的触发频率,因为实际过程中大量的对象是朝生夕死的,新生成的对象优先会被放在新生代的Eden中,在Eden满了之后触发MajorGC对Eden进行回收,此时Eden放不下或者Survior中年龄达标进入老年代.此时GC主要集中在新生代,而新生代的GC执行效率相对较高,STW的时间较少,使得用户体验更好
字节跳动: 二面:Java的内存分区 二面:讲讲jvm运行时数据区 什么时候对象会进入老年代?
jvm运行时数据区: 在Class字节码被加载的时候,每一个类将字节码文件中的常量池加载到方法区,形成运行时数据区
- Eden 满了触发MajorGC 此时 Survior0/1中 年龄大于15(默认)的对象进入老年代
- Eden满了触发MajorGC 此时Eden还是放不下的数据 进入老年代
- 大数据对象Eden无法存下直接进入老年代
京东: JVM的内存结构,Eden和Survivor比例。 JVM内存为什么要分成新生代,老年代,持久代。新生代中为什么要分为Eden和survivor。
天猫: 一面:Jvm内存模型以及分区,需要详细到每个区放什么。 一面:JVM的内存模型,Java8做了什么改动
拼多多: JVM内存分哪几个区,每个区的作用是什么?
美团: java内存分配 jvm的永久代中会发生垃圾回收吗? 一面:jvm内存分区,为什么要有新生代和老年代?
JVM永久代会发生垃圾回收
总结!
JVM内存分哪几个区每个区的作用?
-
程序计数器: 保存程序当前执行的指令地址,执行引擎调度执行完成之后,指针向下移动得到下一条在指令,直到执行完所有指令,不存在GC也不存在OOM
-
Java栈: 每个线程独有,存放一个一个栈帧,每个栈帧中存放了局部变量表,操作数栈,动态链接,方法返回地址和额外附加信息.线程调度执行一个方法就会创建一个栈帧压入java栈,执行完毕弹出.不存在GC,但是会OOM
-
局部变量表: 存储方法的局部变量 以Slot为单位,基本数据类型直接存储,引用类似存储指向堆空间的地址.编译时期确定大小
-
操作数栈:主要用于保存计算过程中的中间结果,同时保存计算过程中的临时数据,根据字节码指令往栈压入数据计算提取数据,具有深度,一旦确定不能改变
-
动态链接(指向运行时常量池的引用): 方法执行过程中可能需要用到类的常量,这个引用指向了运行时常量池
-
方法返回地址: 当一个方法执行完毕之后,保存了PC寄存器的指令地址,从而让程序继续往下执行
-
-
本地方法栈: 线程私有,用于调用非java实现的本地方法,不存在GC存在OOM
-
堆: 除去特殊TLAB区域以外线程共享,用于存储对象实例数组等的空间,存在GC也存在OOM
- 新生代: 对象创建之后默认会优先放在新生代
- Eden: 对象创建默认优先放在Eden中,当Eden满的之后,触发MinorGC,对Eden进行清空,将还有用的对象提升到Survivor TO区 对于溢出部分放入老年代
- Survior0/Survior1: 幸存者区对象存在年龄的概念,每次进行一个MinorGC之后存活的对象年龄+1,当年龄达到15(默认),或者相同年龄的对象占Survior空间1/2的时候,大于等于这个年龄的对象晋升到老年代.放不下的直接进入老年代
- 老年代: 存放生命周期较长的对象,空间占用较长的对象,满了之后触发FullGC进行全堆垃圾回收,回收之后还放不下报出OOM
- 调优参数 -Xms -Xmx
- 新生代: 对象创建之后默认会优先放在新生代
-
方法区
-
被线程所共享主要保存类型信息,域信息,方法信息,存在GC也存在OOM
-
JDK6以前 有永久代 静态变量和字符串常量池存储在永久代 JDK7 有永久代 静态变量和字符串常量池存储在堆 JDK8 废弃永久代 采用使用本地内存的元空间 静态变量和字符串常量池存在堆 -
运行时常量池: 因为class字节码文件本身存在许多与之关联的其他类,如果全部都放在字节码文件中就会非常大,所有每一个类的字节码文件中有一个常量池,保存了各种可能需要用到字面量,类,域或者方法的符号引用.在class文件编译之后会有一个常量池,在运行的时候将这个常量池加载到方法区上,在创建类或者接口的时候可能会使用到运行时常量池
-
Eden和survior的比例分配
默认Eden:Survior0:Survior1 = 8:1:1
java内存分配 jvm的永久代中会发生垃圾回收吗?
会FullGC
jvm内存分区,为什么要有新生代和老年代?
为了减少GC的触发次数