宋红康讲jvm

p39

  1. 老年代是jdk8之前的叫法,jdk8之后叫元空间。
  2. 堆和方法区是jvm全局共有,程序计数器、本地方法栈、虚拟机栈都是每个线程一份


    示意图

    阿里版本的架构划分

p43

pc寄存器

p44

栈是运行时单位,而堆是存储的单位


栈的特点

p45

栈- stackoverflowError
堆-oom- outOfMemoryError
-Xss jvm 栈大小设置的参数

p47

动态连接、方法返回地址和一些附加信息统称为帧数据区

栈针的内部结构

48

局部变量表:定义为一个数字数组,主要用于存储方法参数和定义在方法体内的局部变量;局部变量是建立在线程的栈上,是线程的私有数据,不存在线程安全问题

局部变量的单位是(slot),double和long占据两个槽位,局部变量出了作用域,他所在的局部变量表的槽位会被其他变量所占据

操作数栈:主要用于保存计算过程的中间结果,同事作为计算过程中的变量的临时储存空间

p54

栈顶缓存技术:将栈顶元素全部缓存在物理cpu的寄存器中,降低对内存的读/写次数,提升执行引擎的执行效率

p55 动态链接(也叫指向运行时常量池的方法引用)

动态链接
为什么需要常量池

p56-57 方法的调用

静态连接-早期绑定-非虚方法
动态连接-晚期绑定
例子:
多态,方法传参是父类,编译期间无法确定是哪个子类所以是晚期绑定
重载?构造方法?是早期绑定

静态方法,私有方法,final方法,构造方法,服了方法都是非虚方法

方法调用指令
方法重写的本质
虚方法表

p60 方法返回地址

方法返回地址

p62 栈的面试题

堆溢出:不断的new 一个对象,一直创建新的对象
栈溢出:死循环或者是递归太深,递归的原因,可能太大,也可能没有终止。(调用方法过多)
分配的栈内存越大越好吗
jvm整个空间是有限的,如果栈的内存过大,jvm所能创建的线程数量就过少了

P66堆

堆的简介

P67堆、栈和GC的关系

如果代码中new了一个对象,首先虚机栈的栈针会指向当前方法,堆会给该对象分配空间,虚机栈的操作数栈会引用堆中的该对象的引用地址。当当前方法执行完毕后,栈针出栈,栈和堆的引用会消失。没有被引用的堆空间,等到某个时刻进行GC释放。
如果频繁GC,Gc线程活跃,用户线程受阻,程序效率变慢

p68 堆的结构

堆的结构-1

堆的结构-2

P69 设置堆空间大小

堆空间大小参数

-X是jvm的运行参数
ms是memory start
mx是memory max

如何查看进程的堆大小
方式一:jps /jstat -gc 进程id
方式二:-XX:+PrintGCDetails

p71

image.png

-XX:NewRatio 参数一般不调整,默认是1:2


新生代的内部比例

对象分配过程

YGC/Minor GC:当伊甸园区满了时候会发生YGC
幸存者0区满了之后,忽略阈值15,直接放到老年代

对象分配过程-流程图

79 内存分配策略

内存分配策略

TLAB(Thread Local Allocation Buffer)

TLAB
TLAB说明

P81

堆空间常用参数

逃逸分析(用个人的话定义)
如果一个参数存在于两个方法,叫做逃逸。jvm在分配内存时候会进行逃逸分析,假如参数没有发生逃逸会直接分配到该方法的栈帧上,会随着栈帧出栈。这样做的好处减少gc频率,在堆内存不足时候降低oom的概率。

代码优化

标量替换(用个人的话定义)
基本数据类型为标量;含有多个属性的对象称之为聚合量
未发生逃逸的聚合量会被替换成标量,叫做标量替换。因为没有逃逸所以也会栈上分配

87栈、堆和方法区关系

栈、堆和方法区关系

方法区在逻辑上是堆的一部分,但是实现方法不一样,方法还有个别名:非堆(Non-heap);

方法区的一些断言

元空间不在jvm里在本地物理机的内存中
方法区的大小可以自动扩容和收缩,也可以设置固定大小

设置方法区大小-jdk7
设置方法区大小-jdk8

92方法区的结构

方法区结构

image.png

类信息

域信息

方法信息

p97

方法区演进细节

jdk版本 变化
jdk1.6之前 有永久代,静态变量存在永久代
jdk1.7 有永久代,但逐步在去除永久代,字符串常量池、静态变量移除放在堆里
jdk1.8 无永久代,类型信息、字段、方法常量保存在本地内存的元空间,但字符串常量池、静态变量仍在堆里

永久代被元空间取代的原因

  • 为永久代设置空间大小是很难确定的
  • 对永久代进行调优是很困难的
Stringtable为什么放在堆里

p100方法区的垃圾回收

方法区gc条件
创建对象的过程

p105对象内存布局

内存布局

p106对象访问定位

句柄访问:虚机栈-栈帧-本地变量表 引用堆中句柄池中对应地址,该对应地址存储这堆中实际对象地址以及方法区中类的信息地址
直接访问::虚机栈-栈帧-本地变量表 引用堆中对象地址,对象地址指向方法区中类的信息地址
句柄访问缺点:需要专门开辟句柄池,更消耗空间,到堆中对象需要两次引用,性能较差。
优点:当堆中对象地址移动的时候,本地变量表中地址不需要改变,稳定解耦

p106直接内存

直接内存就是物理机系统内存,调用直接内存会比调用堆中数据会更快一点,缺点:分配回收成本高;不受jvm内存回收管理

可以由MaxDirectMemorySize设置直接内存大小,如果没设置,默认和堆最大内存一致
java代码申请内存小例子


直接内存申请

P110执行引擎

执行引擎负责把高级语言(字节码)翻译成机器语言


解释器和编译器

p115jit和热点代码

热点代码及探测方式

新名词:方法调用计数器、回边计数器

计数器设定
编译顺序

其中代码缓存存在方法区

热度衰减
JIT的分类

64位默认是server模式

C1和C2的优化策略
graal编译器
aot介绍
aot的优缺点

P119

JDK8中String底层是char[]
JDK9中String底层是byte[]+编码标记
原因


String的特性

P120

p123-字符串变量拼接操作的底层原理

String a1="1"; //存储在常量池
String a2= a1+"2"; //因为有变量运算,所以存储在堆里
String a0= a1.intern()+"2"  //intern返回的对象也在常量池
final String a3 = "1";
final String a4 = "2";
String a5 = a3 + a4; //final修饰的的变量时确定的 所以a5也在常量池,且存在编译优化,直接等于String a5="12"
/**
*String的”+“操作相当于
*StringBuilder s =new StringBuilder(); 
*s.append();
*s.append();
*return s.toString();
**/
String a5 = a1 + a2;

Q:既然String的+操作能自动优化成StringBuilder为什么还建议字符串累加使用StringBuffer效率更高


StringBuilder累加

String累加

A:1.频繁创建对象2.创建的对象也需要回收
Q:StringBuilder的进一步优化空间
A:StringBuilder sb=new StringBuilder(xxx);设置底层数组的初始大小,避免数组频繁扩容

Sting面试题

重点:intern在jdk6版本时new一个新对象放在常量池,在jdk7以后的版本是用旧字符地址放在常量池当中

StingBuilder sb=new StringBuilder("ab").toString(),实际底层toString()也创建一个都对象(等价于new Sring(char[]),注意构造方法的入参为char[]时候,不会加入常量池

p131

对于大型网站,使用intern函数,把字符串存储在常量池中,有三点好处
1.空间效率上更节省
2.代码效率也更快
3.gc不会那么频繁

p139引用计数算法

引用计数算法
解决循环引用

p141可达性分析算法(根搜索算法、追踪性垃圾回收)

可达性分析算法的思路
GC ROOTS

对象在销毁时候会调用finalize()方法


对象的三种状态

可达性分析的两次标记


两次标记

p147标记清除算法

标记清除算法

标记清除算法的缺点

p148复制算法

复制算法

复制算法是为了解决标记清除算法容易产生内存碎片的问题,特别的,如果垃圾对象特别多,存活对象较少,复制算法效率会更快

p148标记压缩算法

标记压缩

P150

算法对比

P151分代收集算法

年轻代--复制算法
老年代--标记清除 和标记整理混用

P152增量收集算法

增量收集算法

增量收集的缺点

P153分区算法的说明

分区算法

p158内存泄漏

静态变量,单例模式,未释放的jdbc链接都是内存泄漏的例子

p162安全点 安全域

安全点
如何保证所有线程同步到达安全点

安全区域:线程处于sleep或者阻塞状态

P163强引用、弱引用,软引用、虚引用

强引用:永远不会回收,也是内存泄露的主要原因。
软引用:在垃圾回收后内存空间依然不足就会回收软引用对象。用途:可大可小的缓存。
弱引用:发现即回收,垃圾回收时候弱引用正常被回收。场景:可有可无的缓存(知识点:weakHashMap)
虚引用:不能通过虚引用获取到实例,场景:跟踪垃圾回收时间

P170垃圾回收器的分类

分类方式 A B
线程数 串行垃圾回收 并行垃圾回收
工作模式 并发式垃圾回收 独占式垃圾回收
碎片的处理方式 压缩式垃圾回收 非压缩式垃圾回收
工作的内存空间 年轻代垃圾回收 老年代垃圾回收

P171 GC性能指标

GC性能指标

吞吐量低:垃圾回收次数少,单次回收时间长
低延迟:垃圾回收次数长,单次回收时间长短,总会收时间长。回收线程和用户线程来回切换,cpu开销时间长


注重吞吐量和低时延的图示

P174

image.png
经典垃圾回收器按代划分
image.png

并行:多个垃圾回收线程
并发:用户线程和垃圾回收线程并发

查看使用的垃圾回收器参数
指定serial

java的web应用程序一般不会用serial,一般用于桌面程序

178ParNew

除了是并行的和serial没有什么区别


面试题

参数

P180 ParallelScavenge(并行 吞吐量优先)

image.png

参数:-XX:MaxGCPauseMillis 设置垃圾回收最大停顿时间,为了实现该参数,jvm会自动修改java堆参数或其他参数,该参数较小的话,回收频率会增高,慎用该参数

参数1

参数2

参数3

P182CMS(consurrent-Mark-Sweep 并发 低延迟 )

image.png
CMS的优缺点

参数


参数1
参数2

P186

image.png

并行和并发、分代收集、空间整合、可预测的停顿时间模型
image.png

空间整合

可预测的停顿时间模型

参数

P195垃圾回收器的总结

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

相关阅读更多精彩内容

友情链接更多精彩内容