Java自动内存管理

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  --查看修改更新  (= 没有修改过  := 人为修改过)

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容