JVM内存模型及特征:
堆:
1.JVM管理内存中最大的一块,被所有线程共享
2.唯一目的是存放对象实例和数组
3.垃圾搜集器管理的主要区域
4.可扩展,通过-Xmx和-Xms来控制
5.如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常
虚拟机栈:
1.线程私有
2.局部变量表所需的内存空间在编译期间完成分配
3.该区域规定了两种异常状况:
a.线程请求的栈深度大于虚拟机所允许的栈深度,将抛出StackOverflowError(栈溢出)异常
b.如果虚拟机栈可以动态扩展(大部分允许,也允许固定长度的虚拟机栈),如果扩展时申请不到足够的内存,就会抛出OutOfMemoryError(内存不足)异常
4.虚拟机栈为虚拟机执行java方法服务
方法区:
1.各个线程间共享,用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译的代码等
2.这区域的内存回收目标主要是针对常量池的回收和对类型的卸载
3.会抛出OutOfMemoryError异常
4.Class文件中,除了有类的版本,字段,方法,接口等描述信息外,还有一项信息是常量池.运行时常量池是方法区的一部分,用于存放编译器生成的各种字面量和符号引用
本地方法栈:
1.本地方法栈为虚拟机执行Native方法服务
2.本地方法栈会抛出StackOverflowError和OutOfMemoryError异常
程序计数器:
1.java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式实现的,为了线程切换后能恢复到正确的执行位置,每个线程都需要有一个独立的程序计数器,各线程间计数器互不影响,独立存储,我们称这类内存区域为"线程私有"的内存
2.线程私有
堆中内存分配方式:
指针碰撞:
假设堆中内存是绝对规整的,所有用过的内存放在一边,空闲的内存放在另一边.在使用Serial,ParNew等带Compact过程的搜集器时,系统采用的分配算法是指针碰撞
空闲列表:
虚拟机维护一个列表,记录哪些内存是可用的.使用CMS这种基于Mark-Sweep算法的搜集器时,通常采用空闲列表
常见问题:
1.为什么要给每个线程开辟一个独立的内存空间
java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式实现的,为了线程切换后能恢复到正确的执行位置,每个线程都需要有一个独立的程序计数器,各线程间计数器互不影响,独立存储,我们称这类内存区域为"线程私有"的内存