JVM HotSpot 虚拟机, JRockit,IBM J9, [ Android Dalvik, ART(Android Runtime) ]
内存
JVM数据区:
程序计数器: 当前线程执行的字节码指令的地址,执行Native方法时为空
虚拟机栈: 局部变量表 方法出口等
异常: StackOverflowError OutOfMemoryError
-Xss1m
本地方法栈: 执行Native方法的栈
异常: StackOverflowError OutOfMemoryError
-Xoss1m (HotSpot不生效)
堆: 对象和数组在堆上分配(有例外,JIT优化),垃圾回收, 物理上可以不连续
异常: OutOfMemoryError Java Heap Space
-Xms256m -Xmx1024m
方法区: 类信息、常量、静态变量、JIT编译后代码, 也叫Non-Heap(非堆)
Java7、8 废弃了永久代
异常:OutOfMemoryError
直接内存:DirectMemory, 非JVM数据区
异常:OutOfMemoryError
注:java.nio.DirectByteBuffer受 -XX:MaxDirectMemorySize=256m 限制,默认为-Xmx
对象
对象创建:
1、检查类加载
2、分配内存:指针碰撞 空闲列表, 取决于内存是否规整
并发:CAS失败重试 本地线程分配缓冲TLAB -XX:+/-UseTLAB
3、初始化为0值,设置对象头,引用入栈,执行<init>方法
对象内存布局: 对象头、实例数据、对齐填充
对象头:1、运行时数据:hashCode GC分代年龄 锁信息
(2、类型指针)
(3、数组长度)
对象访问定位:句柄、直接指针
垃圾收集 GC
哪些内存需要回收?
什么时候回收?
如何回收?
衡量指标:
内存占用 吞吐量 延迟
分配内存效率
1、引用计数: 循环引用问题 (如 Python COM)
2、可达性分析 (如 Java Go C#)
GCRoot:栈引用、静态变量引用、常量引用、虚拟机内部引用等
引用类型:
强引用 Strongly:不回收
软引用 Soft: 内存溢出时回收
弱引用 Weak:GC时一定会回收
虚引用 Phantom:不能通过虚引用获取对象实例,用于回收时接收通知
方法区的回收:
废弃的常量和不再使用的类型
分代收集
将Java堆划分出不同的区域, 对象依据年龄分配的不同的区域中
弱分代假说:绝大多数对象都是朝生夕灭的
强分代假说:熬过越多次垃圾收集过程的对象就越难以消亡
跨代引用假说:跨代引用相对于同代引用来说仅占极少数。
部分收集(Partial GC): 收集部分Java堆,分为:
1、新生代收集(Minor GC/Young GC):指目标只是新生代的垃圾收集。
2、老年代收集(Major GC/Old GC):指目标只是老年代的垃圾收集。目前只有CMS收集器会有单独收集老年代的行为。另外请注意“Major GC”这个说法现在有点混淆,在不同资料上常有不同所指,读者需按上下文区分到底是指老年代的收集还是整堆收集。
3、混合收集(Mixed GC):指目标是收集整个新生代以及部分老年代的垃圾收集。目前只有G1收集器会有这种行为。
整堆收集(Full GC):收集整个Java堆和方法区的垃圾收集。
标记清除 Mark-Sweep
标记复制
半区复制 Semispace Copying
appel式回收
Eden : Survivor : Survivor = 8 : 1 : 1
在Eden和一个Survivor分配对象,收集时复制到另一个Survivor,空间不足则进入老年代
标记整理 Mark-Compact
根节点枚举
安全点 Stop The World
安全区域
记忆集与卡表 跨代引用问题
写屏障
并发的可达性分析
三色标记 对象消失问题 增量更新 原始快照
经典收集器
并行(Parallel):多个垃圾收集器线程并行
并发(Concurrent):垃圾收集器线程与用户线程
用于客户端模式
吞吐量优先
CMS(Concurrent Mark Sweep): 并发 低停顿
初始标记(CMS initial mark) Root
并发标记(CMS concurrent mark) 并发
重新标记(CMS remark) 增量更新
并发清除(CMS concurrent sweep) 并发
G1(Garbage First)
初始标记(Initial Marking) Root
并发标记(Concurrent Marking) 并发
最终标记(Final Marking)
筛选回收(Live Data Counting and Evacuation)
Shenandoah:
不分代 记忆集改为连接矩阵
初始标记(Initial Marking) root
并发标记(Concurrent Marking) 并发
最终标记(Final Marking)
并发清理(Concurrent Cleanup) 并发 清理没有存活对象的区域
并发回收(Concurrent Evacuation) 并发 读屏障 转发指针
初始引用更新(Initial Update Reference)
并发引用更新(Concurrent Update Reference) 并发
最终引用更新(Final Update Reference) 更新 root 引用
并发清理(Concurrent Cleanup)
ZGC:
基于Region内存布局的,(暂时)不设分代的,使用了读屏障、染色指针和内存多重映射等技术来实现可并发的标记-整理算法的,以低延迟为首要目标的一款垃圾收集器
小型Region(Small Region):容量固定为2MB,用于放置小于256KB的小对象。
中型Region(Medium Region):容量固定为32MB,用于放置大于等于256KB但小于4MB的对象。
大型Region(Large Region):容量不固定,可以动态变化,但必须为2MB的整数倍,用于放置4MB或以上的大对象。最小容量为4MB。
染色指针: 指针前4位记录三色标记、被移动信息
虚拟内存映射
并发标记(Concurrent Mark):更新染色指针中的Marked 0、Marked 1标志位
并发预备重分配(Concurrent Prepare for Relocate):统计得出本次收集过程要清理哪些Region
并发重分配(Concurrent Relocate):存活对象复制到新的Region上,维护转发表,指针的“自愈”(Self-Healing)
并发重映射(Concurrent Remap):修正所有引用,释放转发表,合并到下一次并发标记
“NUMA-Aware”的内存分配
Epsilon
只分配不回收,用于微服务
CG参数
日志级别 Trace,Debug,Info,Warning,Error,Off
GC日志 java9- java9+
GC基本信息 -XX:+PrintGC -Xlog:gc
GC详细信息 -XX:+PrintGCDetails -Xlog:gc*
参数自动设置 -XX:+PrintAdaptiveSizePolicy -Xlog:gc+ergo*=trace
并发/停顿时间 -XX:+PrintGCApplicationConcurrentTime
-XX:+PrintGCApplicationStoppedTime -Xlog:safepoint
-XX:+UseG1GC
-XX:+UnlockExperimentalVMOptions
-XX:+UseZGC
-XX:+UseShenandoahGC AdoptOpenJDK HotSpot
-showversion 查看java版本
-XX:+PrintCommandLineFlags 查看参数设置
-XX:+PrintFlagsInitial --查看出厂默认值
-XX:+PrintFlagsFinal --查看修改更新 (= 没有修改过 := 人为修改过)