JAVA虚拟机内存
JAVA虚拟机内存
一、运行时数据区/JVM虚拟机数据区
-
线程隔离的数据区
虚拟机栈(java执行方法的内存模型):每执行一个方法都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息;
本地方法栈:类似于虚拟机栈但是执行的是Native关键字修饰的本地方法;
-Xss128k 虚拟机栈大小
-Xoss128k 本地方法栈大小,但HotSpot不区分虚拟机栈和本地方法栈,因此对其无效
程序计数器:当前线程所执行的字节码行号指示器; -
线程共享的数据区
方法区:存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据;
堆:所有对象的实例以及数组的分配区域;
堆参数 -Xms20M -Xmx20M
方法区和永久代关系:
- 方法区是JVM规范的一部份(同理虚拟机栈、本地方法栈、程序计数器、堆、方法区都是虚拟机规范),在JDK1.7之前方法区的具体实现用的是永久代(见深入理解JAVA虚拟机第二版42页第二行原话:原因是HotSpot设计团队选择把GC分代收集扩展至方法区,或者说使用使用永久代来实现方法区而已,这样HotSpot的垃圾收集器可以像管理JAVA堆一样管理这部份内存,能够省去专门为方法区编写内存管理代码的工作)。
- JDK1.8之后移除了永久代(永久代是堆内存的一部份),使用元空间(Metaspace)代替了永久代,也就是说JDK1.8里方法区的实现是元空间,好处是永久代申请扩展空间时不再受到堆内存的限制。
二、本地内存
- 元数据区/元空间:java8中替代永久代的数据区;
配置JVM参数 -XX:MetaspaceSize=8m -XX:MaxMetaspaceSize=50m - 直接内存:jdk1.4引入了NIO,它可以使用Native函数库直接分配堆外内存;
总结:java虚拟机启动时会有两部分内存,分别是本地内存和运行时数据区。
涉及到一个例子:MQ中常用到的零拷贝,按照BIO模型数据需要先从操作系统输入buffer加载到虚拟机堆中(JVM已经申请使用的内存中),再从堆中加载到操作系统输出buffer中。原因是操作系统输入/输出buffer使用的内存不能和虚拟机堆内存是同一段,为了减少数据拷贝次数所以可以直接使用操作系统底层提供的方法,从输入buffer直接拷贝到输出buffer。

浙公网安备 33010602011771号