JVM浅入2

JVM运行时数据区(堆,方法区(非堆),虚拟机栈,本地方法栈,程序计数器)相当于一种规范,约定。而JMM就是JVM的落地/实现;
JMM :Java内存模型
(JMM与JVM其实是没关系的,两个维度的东西)

堆内部结构
JVM浅入2
垃圾回收
age默认值15(及经过15次垃圾回收后,对象将从young区到达old区)
大小:old区:young区 = 2:1

垃圾回收的整个过程:
1.新创建的对象放入Eden区,当Eden区满了之后则继续minorGC/youngGC;为了防止空间的不连续性发生(如GC掉部分对象,则内存区域变得残缺且分散,如果此时要放入一个大的对象,则需要将分散的内存空间整合)此时将young区分为Eden区和survivor区,GC后将存活对象放入Survivor区,这样Eden区的剩余空间就整合了。
为什么Eden区会远大于S区(默认为8:1:1)Eden区越小,则GC次数越频繁,则会消耗性能。
2.同时为了避免Survivor区发生空间不连续性,将S区分成大小相同的两个区域S0+S1;GC时S0和S1区会相互进行交换
3.如果直接来大对象,Eden区之间放不下,则直接将对象放入old区。
担保机制

图解
JVM浅入2
full GC = minor GC + major GC(old GC) + Matespace GC(系统可用内存)
通常认为major GC与Matespace GC相绑定

Java自带工具 :在命令行中输入jvisualvm
可监控jvm内存信息

面试题:性能优化,栈内存一般设置多大?
答:4000(大概能起1000个线程)

GC时如何判断对象是否可以回收?如果出现循环引用怎么办?
可达性分析算法/跟搜索算法:
GC Root (一组活跃引用,并不是实际对象)可达性

虚拟机方法栈的栈帧的局部变量表所引用的对象;
本地方法栈的JNI所引用的对象;
方法区的静态变量以及常量所引用的对象;

什么时候进行垃圾回收?
(1).当Eden区或者S区不够用了
(2).老年代(old)空间不够用了
(3).方法区空间不够用了
(4).System.gc()
System.gc() 仅通知,并没有做判断

怎么收垃圾?
标记/清除算法:给GC Root进行标记,GC时遍历所有对象,无标记的则清除
但由于回收时是通过,业务线程和GC线程相互配合进行的(并行)。此时若发生了将不要GC的对象回收了,将要GC的对象留下怎么办(在回收时业务线程对没打标记的对象进行引用,同理后面的情况)
STW stop the world将业务线程和GC线程串行执行

缺点:1.效率低,因为要遍历所有对象
2.会出现内存碎片化

复制算法:开辟新的空间,将GC后留下的对象整理到新空间中。
缺点:将原有内存缩小到了一半,代价高。(空间换时间)

标记/整理算法:同标记算法,GC后进行整理,解决内存碎片化,同时更新地址引用
缺点:效率低(地址发生改变)

分代收集算法:基于对象的生命周期进行不同的算法
young区进行复制算法,因为young区持续不断新增对象,GC频繁,使用空间换时间的方式来提升效率
old区进行标记/清楚算法或标记/整理算法,因为old区对象存活率高,切一般较大,则采用时间换空间的方式进行优化。