Jvm内存结构
Java内存模型
Java内存区域及对象
Java内存模型2
1. 硬件存储体系结构
当代计算机通常是多cpu多core, CPU都会有一系列的寄存器(Registers),CPU从寄存器读取数据计算要比从主存(Memory)中读取数据快非常多
有CPU缓存(Cache),缓存存取的速度要比寄存器慢,比主存快, Cache 是由 n 个 cache line 构成, 一个 cache line 占用 64 bit, 这里是一个优化点.
存储与CPU的计算交互如下:
write: cpu --> register --> cache --> memory
read: app --> memory--> cache --> register
cpu读取register信息进行计算,计算结果保存在register. 当要将结果更新至memory时,会先把register的值更新至cache, cache放满后flush到memory
处理器使用乱序执行来优化执行, 因此在多线程情况下, 如果对顺序有要求, 建议使用 barrier.
计算机内存空间分为:
- 内核空间:操作系统运行时所使用的用于程序调度、虚拟内存的使用或者链接硬件资源的程序逻辑
- 用户空间:程序只能使用用户空间的内存
2. JMM Java内存模型
堆是用来存放对象(数据),栈是用来执行程序(执行过程)
如果不存在数据逃逸, 那么对象就不需要分配到 heap 上(可以减少gc时间), 数据伴随着stack结束就被释放.
Java内存模型(JMM)解决了可见性和有序性
3. 缓存一致性模型
缓存一致性有很多中模型来实现, 保证了数据的可见性.
- 顺序一致性模型 对处理机所写的值立即进行传播,确保所有处理机都接受后才可以继续执行
- 释放一致性模型 允许所有处理机写值延迟到释放锁的时候才进行传播
4. JVM体系结构
4.1 类加载系统
ClassLoader
4.2 执行引擎
4.3 运行时数据区
4.3.1 线程私有级(工作内存->寄存器/高速缓存)
- 线程栈 ThreadStack
-
局部变量表、操作棧、方法出口, 引用常量等...
- 局部变量表存放的是方法参数和方法内部定义的局部变量,局部变量按slot存储。slot是复用的, 手动增加gc 概率将不需要的对象设置为null
- 基本数据类型(int,long,boolean...),对象引用(reference),returnAddress(finally使用,无法被运行中程序修改)
- 每个方法从调用到完成,都是一个栈帧(stack frame)从线程栈入栈到出栈的过程
- 栈里面存着的是一种叫“栈帧”的东西,每个方法会创建一个栈帧,栈帧中存放了局部变量表(基本数据类型和对象引用)、操作数栈、方法出口等信息。
-
局部变量表、操作棧、方法出口, 引用常量等...
- PC register(Program Counter)寄存器:
- 保存的是当前的指令地址,字节码解释器通过改变这个计数器的值来选取下一条需要执行的字节码指令
- 不受GC管理
- 只有Java的方法计数器才有值,Native方法计数器是null
- 本地方法栈 Native Method Stack (JNI)
4.3.2 公用级(主内存->主存/内存)
TLAB存在的意义
我们知道多线程在分配堆内存时,由于堆是一整块内存,出于线程安全考虑,分配内存需要对堆加锁, 极度消耗资源。
TLAB
就是在Eden上开辟一小块空间,每个线程拥有一个自己独有的空间,在分配内存时先分配TLAB空间。当TLAB空间被分配完了之后,再进行加锁堆内存的分配。
- 堆 Heap
- 虚拟机启动时创建
- 存放对象实例
- 物理上不连续,逻辑上连续
- Young Genration
- EdenSpace 8
- FromSpace(S1) 1
- ToSpace(S2) 1
- Old Generation
- 方法区 MethodArea(1.7PermGen/1.8Metaspace)
- 物理上不连续,逻辑上连续
- Runtime Constant Pool
- Field/Method Data
- Static Variable/Static Method
- Code(.class)/Hot JIT Code(.class)
- JDK1.7后使用Native Memory来实现规划
- permGen被删除的原因在于 持久代JDK1.7前受限制于JVM总的内存大小,会出现持久代OOM的问题,因此在JDK1.8使用操作系统的本地内存Metaspace来取代,仅仅受限于操作系统内存大小(可以减少风险)
- Runtime Constant Pool, 具备动态性, String.intern()
- 直接内存 Direct Memory
- NIO减少Java Heap->Native Heap的数据来回拷贝
- 受限制于OS的RAM和SWAP
5. 堆/栈
栈:向低地址扩展,连续 堆:向高地址扩展,不连续。(堆大小受限于计算机中有效虚拟内存)