1.JVM内存模型了解过吗?
-
User user = new User();
-
User 放在方法区中/1.8之后放在元空间(MetaSpace)
-
user 放在栈中的局部变量表中
-
new User(); 放在堆当中
-
-
元空间(方法区):存放类模版对象,是线程共享的区域,本地内存空间,一般不会GC(垃圾回收) ,之前方法区是有一个non-heap(非堆)
-
堆空间:线程共享的区域,对象创建与GC(垃圾回收)的主要阵地
-
虚拟机栈:线程私有的,基本组成单位是栈帧,每个栈帧对应一个方法,栈帧组成如下
-
局部变量表:存放方法变量信息
-
操作数栈:方法运行的区域
-
动态链接:指向方法模板对象
-
返回地址:方法的返回地址
-
-
本地方法栈:线程私有,本地方法的执行区域
-
程序计数器:线程私有,负责在线程上下文切换的过程中记录线程执行到了哪个位置
-
1.8后改为元空间存储,是存在哪里的?
-
Metaspace所占用的内存空间不是在虚拟机内部,而是在本地内存空间中,这也是与1.7的永久代最大的区别所在
-
由于永久代内存经常不够用或发生内存泄露,爆出异常oom,基于此,将永久区废弃,而改用元空间,改为了使用本地内存空间
-
.class文件,java代码编译后的产出。项目过大,文件比较多,所以你编译出来的.class文件就会很多
-
-
2.GC有了解过吗?
-
年轻代GC
-
对象优先在Eden中分配,当Eden中没有足够空间时,虚拟机将发生一次Minor GC,因为Java大多数对象都是朝生夕灭,所以Minor GC非常频繁,而且速度也很快,并发执行。
-
YGC/YoungGC
-
-
老年代GC
-
Full GC是指发生在老年代的GC,当老年代没有足够的空间时即发生Full GC,发生Full GC一般都会有一次Minor GC。
-
发生FGC的时候,其他的所有线程全部停止,把资源让给FGC。
-
你负责的应用,一旦频繁发生FGC,你就要去排查FGC的原因。
-
大对象过多,分析GC日志(dump日志)
-
-
3.为啥会有个Survivor?而且为什么有两个S?还有就是为啥不设置3个4个5个?
-
就是减少被送到老年代的对象,进而减少Full GC的发生,Survivor的预筛选保证,只有经历16次Minor GC还能在新生代中存活的对象,才会被送到老年代
-
刚刚新建的对象在Eden中,经历一次Minor GC,Eden中的存活对象就会被移动到第一块survivor space S0,Eden被清空;等Eden区再满了,就再触发一次Minor GC,Eden和S0中的存活对象又会被复制送入第二块survivor space S1(这个过程非常重要,因为这种复制算法保证了S1中来自S0和Eden两部分的存活对象占用连续的内存空间,避免了碎片化的发生)。S0和Eden被清空,然后下一轮S0与S1交换角色,如此循环往复。如果对象的复制次数达到16次,该对象就会被送到老年代中。 整个过程中,永远有一个survivor space是空的,另一个非空的survivor space无碎片。
-
Survivor区再细分下去,每一块的空间就会比较小,很容易导致Survivor区满
4.JVM怎么判断一个对象是否被回收?
-
判断一个对象是否应该被回收,主要是看其是否还有引用。判断对象是否存在引用关系的方法包括
-
引用计数法
-
循环引用,解决不了,有可能产生内存泄漏,最终导致内存溢出
-
-
可达性分析法
-
-
引用计数法
-
此对象有一个引用,即增加一个计数,删除一个引用则减少一个计数。垃圾回收时,只需要收集计数为0的对象。
-
-
可达性分析法 GCRoot 引用链
-
通过一系列可以做为root的对象作为起始点,从这些节点开始向下搜索。当一个对象到root节点没有任何引用链接时,则证明此对象是可以被回收的。
-
栈内存中引用的对象
-
方法区中静态引用和常量引用指向的对象
-
被启动类(bootstrap加载器)加载的类和创建的对象
-
Native方法中JNI引用的对象。
-
-
5.垃圾回收算法了解过吗,简单说一下
-
标记-清除
-
执行效率不稳定,会因为对象数量增长,效率变低
-
标记清除后会有大量的不连续的内存碎片,空间碎片太多就会导致无法分配较大对象,无法找到足够大的连续内存,而发生gc
-
-
复制
-
可用内存缩成了一半,浪费空间
-
-
标记整理
-
内存利用率是最高的,效率相较上面两种是低的
-
-
垃圾回收器有了解吗?大致的流程是怎样的?
-
流程
-
初始标记
-
标记GC root
-
-
并发标记
-
执行标记(标记垃圾对象)
-
-
最终标记
-
并发标记过程中产生变动导致标记更新,需重新标记
-
-
回收
-
-
CMS
-
CMS收集器是一种以获取最短回收停顿时间为目标的收集器。CMS收集器是基于标记-清除算法实现的,是一种老年代收集器
-
-
G1 jdk9
-
分代回收
-
通过将JVM堆分为一个个的区域(region),G1收集器可以避免在Java堆中进行全区域的垃圾收集。G1跟踪各个region里面的垃圾堆积的价值大小(回收所获得的空间大小以及回收所需时间的经验值),在后台维护一个优先列表,每次根据回收时间来优先回收价值最大的region。
-
新生代采用复制算法,老年代采用标记-整理算法。
-
-
-
Parallel Scavenge && Parallel Old jdk1.8默认的回收器
-
Parallel Scavenge 年轻代垃圾回收 复制算法
-
Parallel Old 老年代回收 标记-整理算法
-
-