1内存模型
引用一张内存模型的图
1.1:线程私有区域
1.1.1 程序计数器:
为什么会有程序计数器:
JVM的多线程是通过CPU时间片轮转(即线程轮流切换并分配处理器执行时间)算法来实现的。所以
某个线程在执行过程中可能会因为时间片耗尽而被挂起,而另一个线程获取到时间片开始执行。当被挂起的
线程重新获取到时间片的时候,它要想从被挂起的地方继续执行,就必须知道它上次执行到哪个位置,在JVM中,
程序计数器就是来记录某个线程的字节码执行位置的
特点:
1. 用于存储当前运行的线程所执行的字节码的行号指示器
2. 线程隔离性,每个线程工作时都有属于自己的独立计数器。
3. 占用内存很小,在进行JVM内存计算时,可以忽略不计
4. 唯一一个在java虚拟机规范中没有规定任何OutOfMemoryError的区域。
1.1.2: 虚拟机栈
它是来干啥的:
描述Java方法的执行过程的内存模型,就是我们常说的栈内存,在方法被执行时虚拟机会为其创建一个与之对应的栈帧,
在栈帧(Stack Frame)中存储了局部变量表、操作数栈、动态链接、方法出口,部分运行时数据及其数据结构,处理动
态链接,方法的返回值和异常分派等信息,在每个运行中的线程当前只有一个栈帧处于活动状态
特点:
1. 虚拟机栈是线程隔离的,即每个线程都有自己独立的虚拟机栈
2. 虚拟机栈是一个后入先出的栈
3. 每个方法的执行和返回都对应一个栈帧的入栈和出栈,每个运行中的线程当前只有一个栈帧处于活动状态
1.1.3:本地方法区
作用:
本地方法栈的功能和特点类似于虚拟机栈,区别是虚拟机栈为执行Java方法服务,本地方法栈为Native方法服务
如何去服务native方法?native方法使用什么语言实现?怎么组织像栈帧这种为了服务方法的数据结构?虚拟机规
范并未给出强制规定,因此不同的虚拟机实可以进行自由实现,我们常用的HotSpot虚拟机选择合并了虚拟机栈和本地方法栈。
特点:
1. 线程私有,隔离
1.2:线程共有区域
1.2.1:方法区
他是干啥的:
方法区也被称为永久代,方法区保存在着被加载过的每一个类的信息,包括存储常量、静态变量、类信息、即时编译器编译后的机器码、
运行时常量池等数据
特点:
1. 方法区是线程共享的;
2. 方法区的大小不是固定的,jvm根据应用的需要动态调整。jvm也允许用户和程序指定方法区的初始大小,最小和最大限制;
1.2.2:堆(运行时内存)
堆的组成:
从GC的角度可以将JVM堆分为新生代、老年代和永久代
(在Java 8中永久代已经被元数据区(也叫作元空间)取代。元数据区的作用和永久代类似,二者最大的区别在于
:元数据区并没有使用虚拟机的内存,而是直接使用操作系统的本地内存)。
其中新生代默认占1/3堆空间,
老年代默认占2/3堆空间,永久代占非常少的堆空间。
新生代又分为Eden区、ServivorFrom区和ServivorTo区,
Eden区默认占8/10新生代空间,ServivorFrom区和ServivorTo区默认分别占1/10新生代空间
特点:
1. 线程共享
2. 垃圾收集器的主要区域
3. 堆大小是可控制的,通过-Xmx(初始大小)和-Xms(最大大小)控制
4. 在内存不够时会抛出outOfMemoryError异常