JVM学习总结(一)自动内存管理机制
JAVA内存区域与内存溢出异常
一、运行时数据区域
java 虚拟机的内存模型分为两部分:一部分是线程共享的,包括 Java 堆和方法区;另一部分是线程私有的,包括虚拟机栈和本地方法栈,以及程序计数器这一小部分内存
1、程序计数器:
- 当前线程所执行的字节码行号指示器,保证了程序的正常执行
- 特点:1、线程私有 2、 是java虚拟机规范里面, 唯一 一个 没有规定任何 OutOfMemoryError 情况的区域 【原因是只保存指令偏移地址,不需要申请空间保存新的指令,因此不会有OutOfMemoryError异常】3、生命周期随着线程,线程启动而产生,线程结束而消亡。3如果执行的是native方法,计数器记录为空。
2、 java虚拟机栈
- java虚拟机规范,对该区域规定了两种异常状况:
- (1).线程请求的深度大于虚拟机所允许的深度跑出stackoverflowerror
- (2).扩展到无法申请足够的内存跑出outofmemeryeeorr
- java虚拟机栈是为虚拟机执行java方法服务
3、本地方法栈是native方法服务
4、JAVA堆
- java堆是虚拟机管理的内存中最大的一块,被所有线程共享的区域 存放对象实例
- 对象实例和数组都放在堆上 jit 即时编译
- java堆是垃圾收集管理的主要区域(GC堆)
- 分代收集算法分为新生代和老年代
- 线程共享的java堆可能还可以分出不同的区,目的是更好地回收内存,更快的分配内存。大小通过-Xmx和-Xms控制
- 如果堆中没有内存完成实例分配,并且堆也无法再扩展,抛出OutOfMemoryError
5、 方法区
- 永久代 内存上限(-XX:MaxPermSize)
- 目前jdk1.7已经把原本放在永久代的字符串常量池移出。
- 也会回收,针对常量池的回收和对类型的卸载
- 如果方法区无法满足内存分配需求,抛出OutOfMemoryError 6
6、运行时的常量池
方法区的一部分,用于存放编译期产生的各种字面量和符号引用。具备动态性。
String类中的intern()方法 作用:就是重用String对象,以节省内存消耗。
- 直接使用双引号声明出来的String对象会直接存储在常量池中。
- 如果不是用双引号声明的String对象,可以使用String提供的intern方法。intern 方法会从字符串常量池中查询当前字符串是否存在,若不存在就会将当前字符串放入常量池中
String s = new String("abc")创建了两个对象,第一个对象是”abc”字符串存储在常量池中,第二个对象在JAVA Heap中的 String 对象。
7、直接内存
jdk1.4后加入NIO,引入了基于通道和缓冲区的I/O方式,分配堆外内存 避免了java堆和native堆复制数据。受到本机总内存大小限制。如果配置各个内存大于物理内存限,也会报OutOfMemoryError
二、hotspot虚拟机对象
1、对象的创建
类加载通过后,为对象分配空间分为两种情况
垃圾收集器是否带有压缩整理功能:
有: java堆中内存规整,用过的放一边,空闲的内存的放一边,中间放指针做分界点的指示器。
分配方式:“指针碰撞” 指针向空闲内存空间挪一段与对象大小相等的位置 。
无:内存不规整,
分配方式:空闲列表 虚拟机需维护一个列表在表上做记录划分对象,更新记录。、、
并发线程安全考虑,1分配内存时虚拟机采用CAS配上失败重试的方式保证更新操作的原子性
2 本地线程分配缓冲 TLAB,分配动作按照线程划分,每个线程先分配一个内存块,用完的时候就锁定。通过参数-XX:+/-UseTLAB
2 、对象的内存布局
对象头,实例数据、对齐填充
对象头存储两部分数据
一部分自身的运行数据
第二部分存类型指针
实例数据,字段的内容,存储顺序受虚拟机分配策略参数和源码定义的顺序影响,默认相同宽度的字段分配到一起
填充:占位符,对象起始地址必须是8字节的整数倍
3 、对象的访问定位
访问方式两种:
句柄: java堆中会划分出一块内存作为句柄池,方法栈reference存储句柄地址
什么是逃逸分析(Escape Analysis)?
在编程语言的编译优化原理中,分析指针动态范围的方法称之为逃逸分析。它跟静态代码分析技术中的指针分析和外形分析类似。
通俗一点讲,当一个对象的指针被多个方法或线程引用时,我们称这个指针发生了逃逸。
而用来分析这种逃逸现象的方法,就称之为逃逸分析。
3种常见的指针逃逸场景。分别是 全局变量赋值,方法返回值,实例引用传递。
逃逸分析另一个重要的优化 - 同步消除
JVM中启用逃逸分析 DoEscapeAnalysis
安装jdk1.6.0_14,运行java时传递jvm参数 -XX:+DoEscapeAnalysis
JVM中启用逃逸分析 DoEscapeAnalysis
安装jdk1.6.0_14,运行java时传递jvm参数 -XX:+DoEscapeAnalysis