JAVA虚拟机内存

JAVA虚拟机内存

一、运行时数据区/JVM虚拟机数据区

  1. 线程隔离的数据区
    虚拟机栈(java执行方法的内存模型):每执行一个方法都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息;
    本地方法栈:类似于虚拟机栈但是执行的是Native关键字修饰的本地方法;
    -Xss128k 虚拟机栈大小
    -Xoss128k 本地方法栈大小,但HotSpot不区分虚拟机栈和本地方法栈,因此对其无效
    程序计数器:当前线程所执行的字节码行号指示器;

  2. 线程共享的数据区
    方法区:存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据;
    堆:所有对象的实例以及数组的分配区域;
    堆参数 -Xms20M -Xmx20M

方法区和永久代关系:

  1. 方法区是JVM规范的一部份(同理虚拟机栈、本地方法栈、程序计数器、堆、方法区都是虚拟机规范),在JDK1.7之前方法区的具体实现用的是永久代(见深入理解JAVA虚拟机第二版42页第二行原话:原因是HotSpot设计团队选择把GC分代收集扩展至方法区,或者说使用使用永久代来实现方法区而已,这样HotSpot的垃圾收集器可以像管理JAVA堆一样管理这部份内存,能够省去专门为方法区编写内存管理代码的工作)。
  2. JDK1.8之后移除了永久代(永久代是堆内存的一部份),使用元空间(Metaspace)代替了永久代,也就是说JDK1.8里方法区的实现是元空间,好处是永久代申请扩展空间时不再受到堆内存的限制。

二、本地内存

  1. 元数据区/元空间:java8中替代永久代的数据区;
    配置JVM参数 -XX:MetaspaceSize=8m -XX:MaxMetaspaceSize=50m
  2. 直接内存:jdk1.4引入了NIO,它可以使用Native函数库直接分配堆外内存;

总结:java虚拟机启动时会有两部分内存,分别是本地内存和运行时数据区。
涉及到一个例子:MQ中常用到的零拷贝,按照BIO模型数据需要先从操作系统输入buffer加载到虚拟机堆中(JVM已经申请使用的内存中),再从堆中加载到操作系统输出buffer中。原因是操作系统输入/输出buffer使用的内存不能和虚拟机堆内存是同一段,为了减少数据拷贝次数所以可以直接使用操作系统底层提供的方法,从输入buffer直接拷贝到输出buffer。

posted @ 2020-02-14 11:12  oneBo  阅读(139)  评论(0)    收藏  举报