Java虚拟机的内存模型
java虚拟机的内存模型
内存区域名称 | 英文名称 | 作用 | 批注 | 可能的异常 | 线程共享与否 |
---|---|---|---|---|---|
程序计数器 | Program Counter Register | 当前线程锁执行的字节码的行号指示器 | 对于Java方法,记录的是正在执行的虚拟机字节码指令的地址,对于Natice方法,计数器值为空 | 无 | 线程私有,对于每一个线程都具有自己的一个计数器用于在线程切换情况下的恢复 |
Java虚拟机栈 | Java Virtual Machine Stacks | Java方法的执行内存模型 | 每个java方法会对应一个栈帧,存放局部变量表,操作数栈,动态链接,方法出口 | StackOverflowError:如果申请的栈深度大于虚拟机所允许的深度,OutOfMemoryError:如果动态拓展时无法申请到足够的内存 | 线程私有,与线程生命周期相同 |
本地方法栈 | Native Method Stacks | Native方法执行的内存模型 | 同上 | 同上 | 同上 |
Java堆 | Java Heap | 用于存放对象实例 | 1.数组也是在堆上进行分配的2.Java8中字符串常量池被放入堆中3.分为新生代和老生代 | OutOfMemoryError:堆中没有内存进行实例分配并且不能在进行动态拓展时 | 所有线程共享 |
方法区 | Method Area | 存储虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码 | 1所谓的永久代2可以不进行垃圾收集的区域,垃圾回收效果一般不好 | OutOfMemoryError:堆中没有内存进行实例分配并且不能在进行动态拓展时 | 所有线程共享 |
运行时常量池 | Runtime Constant Pool | 方法区的一部分,用于存放编译期生成的各种字面量和符号引用 | 无 | OutOfMemoryError:堆中没有内存进行实例分配并且不能在进行动态拓展时 | 所有线程共享 |
直接内存 | Direct Memory | 不是java虚拟机运行时数据区的一部分,称为堆外内存 | 无 | OutOfMemoryError:各个内存区域总和大于物理内存限制 | 无 |
解决对象分配时并发问题的两种方法
- 对分配内存空间的动作进行同步处理,可采用CAS配上失败重试的方式保证更新的原子性
- 使用TLAB(Thread Local Allocation Buffer)本地线程分配缓冲来进行分配
HotSpot虚拟机对象中包含的内容
名称 | 英文名称 | 作用 | 包含内容 |
---|---|---|---|
对象头 | Header | 包含有关该对象的属性信息 | 1.MarkWord:自身运行时数据:哈希码、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳。2.类型指针:该对象指向其类元数据的指针,用于表示该对象是哪个类的实例。3.如果是数组,则还包含数组的长度 |
实例数据 | Instance Data | 即对象中实际存放的数据 | 对象中的实例数据 |
对齐填充 | Padding | 用于进行2K或者4K对齐的填充部分 | 无实际意义的空白填充 |