Java Virtual Machine=JVM 虚拟机的内存空间:
分别是:
1. 堆
2. 方法区
3. 线程私有区
先介绍线程私有区: 这里说的线程私有区,顾名思义,就是多线程中各个线程独立使用的内存空间,包括:
程序计数器:
-
在多线程编程中,存在上下文切换的现象(每条线程用完自己的时间片后,即使任务还没完成,操作系统也会剥夺它的执行权,让另一条线程执行),为了记录当前线程执行的代码行号、指令地址,诞生了程序计数器。
-
指向当前线程正在执行的字节码指令的地址、行号。
-
这块内存不会进行GC,即不存在OutOfMemoryError。
-
与线程同生命周期。
Java 虚拟机栈:
- 描述的是Java 方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧,用于存储局部变量表、操作栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
- 与线程同生命周期。
- Java 虚拟机栈中有一个局部变量表,在方法被执行的时候被创建,存放了编译期所能知的各类基本数据类型,对象引用例如:
Person p=new Person();
存的是p(引用变量)。 double 和long会占用2个局部变量空间,其余的占用1个。 - 局部变量表的大小在编译时期就确定下来了,在创建的时候只需分配事先规定好的大小即可。此外,在方法运行的过程中局部变量表的大小是不会发生改变的。
堆:
- 最大的一块内存,在JVM启动的时候创建这块内存
- 包含两个大部分,新生代和老年代(1:2),新生代中包含Eden区,From Survivor和To Survivor,比率为8:1:1,这样分配的目的是为了更好地进行GC。
- 几乎所有的对象的实例都存放在这里
方法区:
- 在Java8.0被替换为MetaSepace
- 存放 已经被虚拟机加载的类信息、常亮、静态变量
- 在HotSpot虚拟机上被称为“永久代”
本地方法栈:
- 与Java栈的区别在于,执行的是Native方法(非Java方法)
- Sun hotspot虚拟机直接把本地方法栈和Java栈合二为一
直接内存:
- 不属于虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域,但是也被频繁使用,而且也可能导致OutOfMemoryError
- JDK引入NIO类,引入一种基于通道Channel与缓冲区Buffer的IO方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作,这样能显著提高某些场景的性能,避免Java堆和Native堆的来回复制
- 直接内存的分配不会受Java堆大小的限制,但是肯定还是受本机总内存大小、处理器寻址空间的限制,所以在配置虚拟机参数的时候,除了根据实际内存配置-Xmx等参数,还得注意直接内存