JVM
2023-03-15 12:42:09 0 举报
AI智能生成
jvm
作者其他创作
大纲/内容
JVM下篇:性能监控与调优
整体结构
详细结构
JVM与Java结构体系
目的
引导类加载器(Bootstrap ClassLoader)
扩展类加载器(Extension ClassLoader)
系统类加载器(系统类加载器,AppClassLoader)
用户自定义类加载器
自定义类加载器(User-Defined ClassLoader)
类加载器
优势
沙箱安全机制
其他:判断两个class对象是否相同?
加载
验证
准备
解析
链接
初始化
类加载子系统
系统线程主要类别
线程
扩展:JVM优化方向
运行时数据区及概述
作用
介绍
举例说明
问题
程序计数器(PC计数器也称为程序钩子)
可能出现的异常
设置栈内存大小
虚拟机栈概述
栈帧
运行原理
内部结构
栈的储存单位
结构
slot的理解
slot重复利用
静态变量与局部变量的对比
补充
局部表量表(Local Variables)
关键点
代码试例
栈顶缓存技术(Top Of Stack Cashing)技术
操作数栈(Operand Stack)
概念
为什么需要运行时常量池呢?
动态链接(Dynamic Linking)
静态链接
动态链接
早期绑定
晚期绑定
方法的绑定机制
对应关系
指令
关于invokednamic指令
动态类型语言和静态类型语言
虚方法和非虚方法
方法重写的本质
方法的调用:虚方法表
方法的调用:解析与分配
内容
方法的结束方式
个人理解
方法返回地址(return address)
一些附加信息
举例栈溢出的情况?(StackOverflowError)
调整栈大小,就能保证不出现溢出么?
分配的栈内存越大越好么?
各区域情况
垃圾回收是否涉及到虚拟机栈?
方法中定义的局部变量是否线程安全?
栈的相关面试题
虚拟机栈
定义
为什么使用Native Method?
本地方法接口
本地方法栈
堆内存细分
JDK1.7
JDK8之前和8
堆(Heap)的核心概述
堆空间大小的设置
OutOfMemory举例
设置堆内存大小与OOM
分类
-XX:NewRatio
-xx:SurvivorRatio
-XX:-UseAdaptivesizePolicy
-Xmn
设置参数
年轻代与老年代
过程
过程图解
流程图
总结
常用调优工具
图解对象分配过程
Minor GC
Major GC
Full GC
Minor GC,Major GC、Full GC
堆空间分代思想
原则
内存分配策略
为什么有TLAB(Thread Local Allocation Buffer)?
图解
什么是TLAB?
对象分配内存分配图解
TLAB的再说明
为对象分配内存:TLAB
java8虚拟机参数说明
官网
常用参数
小结:堆空间的参数设置
逃逸分析
举例
栈上分配
同步省略
分离对象或标量替换
逃逸分析:代码优化
逃逸分析小结
堆是分配对象的唯一选择么?
本章小结
堆
栈、堆、方法区的交互关系
在哪里?
方法区的基本理解
HotSpot中方法区的演进
方法区的理解
JDK7及以前
JDK8及以后
设置方法区内存的大小
如何解决这些OOM
设置方法区大小与OOM
经典结构图
方法区(Method Area)存储什么?
类型信息
域(Field)信息
方法(Method)信息
non-final的类变量
补充说明:全局常量(static final)
方法区的内部结构
为什么需要常量池?
常量池中有什么?
小结
运行时常量池 VS 常量池
运行时常量池
方法区使用举例
变化
JDK1.6
JDK1.8
变化图示
为什么永久代要被元空间替代?
StringTable为什么要调整位置?
代码
结论
静态变量存放在那里?
方法区的演进细节
字面量
符号引用
回收内容
回收机制
方法区的垃圾回收
面试题
方法区
最常见的方式
变形1:x的静态方法(单例)
变形2:xBuilder/xFactory的静态方法(建造者、工厂模式)
new
Class的newInstance():放射的方式,只能调用空参的构造器,权限是public,已过时
Constructor的newInstance(x):反射的方式,可以调用空参和有参的构造器,无权限要求
使用clone():不调用任何构造器,当前类需要实现cloneable接口,实现clone()方法,实际是从写Object类的clone()
使用序列化:从文件、网络中获取对象发二进制流
使用第三方库Objensis
创建对象的方式
1. 判断对象对应的类是否加载、链接、初始化
指针碰撞
如果内存规整
维护空闲列表
如果内存不规整
说明
2. 为对象分配内存
采用CAS失败重试、区域加锁保证更新的原子性
每个线程预先分配一块TLAB:通过设置 -XX:+UseTLAB参数来设定
3. 处理并发问题
所有属性设置默认值,保证对象实例字段在不赋值时可以直接使用
4. 初始化分配到的内存
5. 设置对象的对象头
6. 执行init方法进行初始化
1. 加载类元信息
2. 为对象分配内存
4. 属性的默认初始化(零值初始化)
5. 设置对象头信息
6. 属性的显示初始化、代码块中初始化、构造器中初始化
简述
属性的默认初始化
显式初始化
代码块中初始化
构造器中初始化
说明:给对象属性赋值的操作(4类)
创建对象的步骤
对象的实例化
哈希值(HashCode)
GC分代年龄
锁状态标志
线程持有的锁
偏向线程ID
偏向时间戳
运行时元数据
指向类元数据InstanceKlass,确定该对象所属的类型。
类型指针
包含两部分
说明:如果是数组,还需记录数组的长度
对象头(Header)
相同宽度的字段总是被分配在一起
父类中定义的变量会出现在子类之前
如果CompactFields参数为true(默认为true):子类的窄变量可能插入到父类变量的空隙
规则
说明:它是对象真正存储的有效信息,包括程序代码中定义的各种类型的字段(包括从父类继承下来的和本身拥有的字段)
实例数据(Instance Data)
说明:不是必须的,也没有特别的含义,仅仅起到占位符的作用
对齐填充(Padding)
图示
对象的内存布局
创建对象的目的是为了使用它
定位,通过栈上reference访问
JVM是如何通过栈帧中的对象引用访问到其内部的对象实例的呢?
实现
好处
句柄访问
直接指针(Hotspot采用)
对象访问方式主要有两种
对象的访问定位
直接内存概述
非直接缓存区
直接缓存区
直接内存
对象实例化以及直接内存
String Pool
String的基本特性
StringTable为什么要调整?
String的内存分配
String的基本操作
常量与常量的拼接结果在常量池,原理是编译期优化
常量池中不会存在相同内容的变量
只要其中有一个是变量,结果就在堆中。变量拼接的原理是StringBuilder
如果拼接的结果调用intern()方法,则主动将常量池中还没有的字符串对象放入池中,并返回此对象地址
字符串拼接操作性能对比
字符串拼接操作
intern()的使用
StringTable的垃圾回收
G1中的String去重操作
StringTable
运行时数据区
概述
执行引擎的工作流程
执行引擎概述
总体流程
编译成字节码(前端编译器)
执行字节码(后端编译器)
解释器
JIT编译器
为什么Java是半编译半解释型语言?
Java代码编译和执行过程
机器码
指令集
汇编语言
高级语言
C、C++源程序执行过程
字节码
机器码、指令、汇编语言
工作机制
Java代码的执行分类
HotSpot JVM执行方式
概念解释
运行图示
设置方式
方法调用计数器
热点衰减
回边计数器
热点代码及探测技术
HotSpotVM 可以设置程序执行方法
使用规则
C1和C2优化方向
HotSpotVM中 JIT 分类
Graal编译器
AOT编译器
执行引擎
虚拟机是屏蔽了机器的差异,字节码屏蔽了语言的差异
垃圾回收概述
垃圾回收相关算法
垃圾回收相关概念
垃圾回收器
垃圾回收
JVM上篇:内存与垃圾回收
JVM中篇:字节码与类加载
JVM
0 条评论
下一页