深入理解Java虚拟机第三版 第二部分 自动内存管理

第二章 Java内存区域与内存溢出异常

2.2 运行时数据区域

2.2.1 程序计数器

如果线程正在执行一个Java方法,计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是本地(Native)方法,这个计数器值是null。

2.2.2 Java虚拟机栈

每个方法被执行的时候,Java虚拟机都会同步创建一个栈帧,存储局部变量表、操作数栈、动态链接、方法出口

2.2.3 本地方法栈

2.2.4 Java堆

存对象实例

2.2.5 方法区

存储被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据

2.2.6 运行时常量池

方法区的一部分,存放编译期生成的各种字面量与符号引用

2.2.7 直接内存

在jdk1.4引入了NIO类,引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O方式,他通过Native函数库直接分配堆外内存,使用存储再Java堆里的DirectByteBuffer对象最为这块内存的引用

 

2.3 HotSpot对象揭秘

2.3.1 对象的创建

内存分配方式:指针碰撞、空闲列表(维护一个列表,记录空闲内存和使用过的内存)

选择哪种分配方式由内存是否规整决定,内存是否规整,由垃圾收集器是否带有空间压缩整理的能力决定

虚拟机如何保证操作的原子性?

采用CAS配上失败重试的方式保证更新操作的原子性;

2.3.2 对象的内存布局

在HotSpot里,对象在堆里的存储布局分为三部分:对象头、实例数据、对齐填充

2.3.3 对象的访问定位

句柄、直接指针

 

 

第三章 垃圾收集器与内存分配策略

3.2 对象已死?

3.2.1 引用计数法

给对象加一个引用计数器,为0时表示对象死亡,但解决不了互相引用的问题

3.2.2 可达性分析

3.2.3 再谈引用

强引用:只要存在强引用,对象就不会被回收,Object obj = new Object();

软引用:有用但非必须,如果内存不足,会被二次回收;

弱引用:只能生存到下一次GC,无论内存是否足够,都会被回收;

虚引用:没什么用,只是在被GC的时候收到一个系统通知。

3.2.4 生存还是死亡?

在可达性分析认为对象不可达之后,还需要经历两次标记:

      在对象被认为没有与GC Roots相连之后,被第一次标记,随后进行一次筛选,条件是对象是否有必要执行finalize()方法,如果对象没有覆盖finalize()方法或finalize()方法已经被调用过,就被认为是没必要执行;

      对象被判定为有必要执行finalize()方法之后,被放到F-Queue队列,之后由线程执行,执行finalize()方法时会进行二次标记,如果此时重新连接,那么二次标记时会把对象从队列移出,否则被回收。

3.2.5 回收方法区

废弃的常量和不再使用的类型

 

3.3 垃圾收集算法

3.3.1 分代收集理论

新生代收集(Minor GC/Young GC)

老年代收集(Major GC/Old GC)

3.3.2 标记-清除算法

标记需要回收的对象并回收。

两个缺点:1.数据量大时标记和清除的效率很低;2.会产生内存碎片

3.3.3 标记-复制算法(一般用于新生代垃圾收集)

把内存均分为两半,每次只使用其中一块,回收一次后,把对象复制到另一块内存,然后清理这一块内存。

缺点:空间浪费

优化:把内存分为一个Eden区和两个Survivor区,比例是Eden区占8,两个Survivor分别占1,每次只使用Eden和其中一个Survivor,每次回收时把Eden和Survivor里存活的对象复制到空闲的Survivor里,然后清理Eden和使用过的Survivor。

3.3.4 标记-整理算法(一般用于老年代垃圾收集)

清除掉不可用的对象后,把存活对象向内存空间的一侧移动。

缺点:移动时,必须暂停用户应用程序才能进行,被称为“Stop The World”。

 

3.5 经典垃圾收集器

1. Serial收集器

曾经是虚拟机新生代收集器的唯一选择(目前仍然是hotspot运行在客户端模式下的默认的新生代收集器);

单线程工作的收集器;

Stop The World,进行垃圾收集时,必须停止其他所有工作线程;

2.ParNew收集器

Serial收集器的多线程版本;

JDK7之前系统首选的新生代收集器;

在JDK5发布时,hotspot发布了老年代收集器CMS,CMS只能搭配Serial或ParNew使用,这提高了ParNew的地位;

推出G1之后,ParNew+CMS退出历史舞台;

3.Parallel Scavenge收集器

新生代收集器标记-复制,并行收集的多线程收集器;

关注点和其他收集器不同,其他收集器关注减少垃圾收集时用户线程的停顿时间,本收集器关注吞吐量

吞吐量=运行用户代码时间/(运行用户代码时间+运行垃圾收集时间)

4.Serial Old收集器

Serial的老年代版本,单线程,标记-整理

作用:配合Parallel Scavenge使用;CMS失败的备用预案

5.Parallel Old收集器

Parallel Scanenge的老年代版本,并发,标记-整理

6.CMS收集器

标记-清除

四个步骤:初始标记、并发标记、重新标记、并发清除

其中初始标记和重新标记仍然需要Stop The World,但时间比较短。这四个步骤就是可达性分析后的两次标记过程

优点:并发收集(两次STW时间都很短,近似并发),低停顿

缺点:对处理器资源敏感(处理器少于4个的话,占用资源很大);

无法处理浮动垃圾(标记之后,程序正常运行产生的垃圾),可能会触发Full GC;

标记-清除会产生内存碎片,从而触发Full GC;

7.Garbage First收集器(G1)

JDK9发布时,G1宣布取代Parallel Scavenge+Parallel Old的收集器组合,成为服务器模式下的默认垃圾收集器;

G1跳出了分代收集的牢笼,虽然仍然遵循分代收集的方式,但不再坚持固定大小和固定数量的区域,而是把Java堆分为多个相同大小的Region,每个region都可以根据需要来扮演Eden、Survivor、老年代的角色

处理器让G1去跟踪每个Region里的垃圾堆的价值大小,价值就是垃圾收集获得的空间大小以及停顿时间,然后在后台维护一个优先级列表,每次根据用户设定的停顿时间,优先处理价值最大的Region,这就是Garbage First名字的由来。

步骤:初始标记、并发标记、最终标记、筛选回收

除了并发标记,其他都需要Stop The World。

G1仍然存在的问题:

Q:跨Region引用对象如何解决?

A:目前使用记忆集,但要耗费比较多的资源

Q:并发问题:

A:原始快照

Q:如何建立可靠的停顿预测模型?

A:记录各种值,然后分析

 

第四章 虚拟机性能监控、故障处理工具

4.2 基础故障处理工具

4.2.1 jps:虚拟机进程状况工具

jps [options] [hostid]

4.2.2 jstat:虚拟机统计信息监视工具

显示本地或远程虚拟机进程中的类加载、内存、垃圾收集、即时编译等运行数据

主要使用:jstat -gc [hostid] 监视Java堆状况

4.2.3 jinfo:Java配置信息工具

jinfo作用是实时查看和调整虚拟机参数

jinfo [option] pid

jinfo -v pid 显式指定的参数列表

jinfo -flag pid 默认的参数值

4.2.4 jmap:Java内存映像工具

生成堆转储快照

4.2.5 jhat:虚拟机堆转储快照分析工具

搭配jmap使用

4.2.6 jstack:Java堆栈跟踪工具

生成虚拟机当前时刻的线程快照,目的是定位线程出现长时间停顿的而原因,如线程间死锁、死循环

 

4.3 可视化故障处理工具

JConsole、JHSDB、VisualVM、JMC

 

第五章 调优案例分析与实战

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值