1.运行时数据区存放的内容:
区域 | 权限 | 作用 |
程序计数器 | 线程私有 | 记录的是当前线程字节码的行号;java代码,执行jvm字节码指令的地址 |
栈stack | 私有 | 存放局部变量、操作数栈、线程创建时有的; 本地方法栈, |
本地方法栈 | ||
方法区 | 线程共享 | 类的版本、字段、方法、接口;静态变量常量池(字面量+符号引用) jdk6,有永久代,常量池放在方法区 jdk7有永久代,常量池在堆 jdk8无永久代,常量池元空间中 |
堆heap | new出来的所有实例对象;堆是垃圾回收的主要对象 |
2.对象的结构
对象由对象头、实例数据、对齐填充组成
- 对象头:MarkWord(hash\GC年龄,锁标志、线程持有锁、偏向线程ID、时间戳)+类型指针(如果是数组的话,还有个数组长度)
- 实例数据:相同宽度的数据块放一块
- 对齐标识:8字节的整数倍
备注:
创建对象的几种方式:
1.new
2.反射
3.克隆
4.序列化、反序列化
jvm有哪些:
1.oracle:hotspot
2.Alibaba:taobaojvm
3.IBM:J2
3.堆空间分配
新创建的对象在堆中需要分配内存空间,方式有两种:指针碰撞和空闲列表
1.指针碰撞
堆分为未分配和已分配两个区域,使用指针来区分(指针的两边分别为已分配和未分配?)。
2.空闲列表(字典)
4.多线程分配时,线程安全性的问题
解决线程安全问题有两种方式:线程同步和TLAB
TLAB:thread local allocation buffer
记录三个指针:start end top
TLAB默认占用eden的1%空间
5.heap区的垃圾回收机制
垃圾回收的重点是,如何回收、何时回收。
JVM内存中的堆是垃圾回收的主要区域,分为新生代和老年代。
垃圾回收机制的算法包括,识别垃圾算法、清除垃圾算法。
下图是堆空间的结构:
5.1识别垃圾算法:
引用计数法
可达性分析
引用计数法在某些场景下会出现循环引用的问题,所以很少使用了
循环引用的问题:
class MyObj{
public MyObj childNode;
}
public class referenceCounter{
public static void main(String[] args){
MyObj obj1 = new MyObj();
MyObj obj2 = new MyObj();
obj1.childNode = obj2;
obj2.childNode = obj1;
}
}
可达性分析更加常用一些:
GCroots(根搜索法)能直接索引到的就不是内存垃圾,其他的则可以被清理掉了
5.2清除垃圾算法:
标记清除算法(Mark-Sweep):实现简单,但有内存碎片
复制算法(copying):无内存碎片,但是内存利用率低
标记整理算法(Mark-Compact):没有内存碎片,内存利用率也高,但是算法相对比较复杂
分代回收:分为新生代和老年代
标记清除算法:
复制算法:
标记整理算法:
分代回收:
当对象不断创建时,首先存放在eden区,当eden区存满时,触发minorGC,将eden区的数据移到from中,from和to不断对调
当from或to对空间满了,触发MaxGC,将“年龄最大”的移到老年代堆空间
当老年代对空间满时,触发fullGC:stop the world(如果一直fullGC,就会有程序假死的问题)
执行回收操作的是垃圾回收器
CMS:
- 初始标记:stop-the-world,标记GCRoots直接关联的对象
- 并发标记:并发追溯标记,程序不会停顿
- 重新标记:暂停虚拟机,扫描CMS堆中的剩余对象
- 并发清理:清理垃圾对象,程序不会停顿
- 并发重置:重置CMS收集器的数据结构
G1回收器:
- G1垃圾收集器将整个 JVM 内存分为多个大小相等的;region,年轻代和老年代逻辑分区 。
- G1 是 Java9 以后的默认垃圾回收器了
- G1 在整体上使用标记整理算法,局部使用复制算法
- G1 的每个 Region 大小在 1-32M 之间,可以通过 -XX:G1HeapRegionSize=n 指定区大小。
- 总的 Region 个数最大可以存在 2048 个,即heap最 大能够达到32M*2048=64G
- 0.5<obj<1,那么放到old区,old标记为H; 1<obj<n,连续的n个region,作为H
Jvm优化相关命令、工具
- jps
主要是看虚拟机的相关参数配置
- jstat
类加载,内存,垃圾收集,jit编译信息
https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jstat.html
- jinfo
实时调整和查看虚拟机参数
- jmap
侧重查看内存信息
- jhat
分析java堆信息,以html的形式显示出来,支持对象查询语言
- jstack
线程堆栈信息
- jconsole和jvisualvm工具
https://visualvm.github.io/pluginscenters.html