美文网首页
JVM 内存结构

JVM 内存结构

作者: 慕子昂 | 来源:发表于2017-04-13 11:49 被阅读0次

    描述

            JVM定义了若干个程序执行期间使用的数据区域。这个区域里的一些数据在JVM启动的时候创建,在JVM退出的时候销毁。而其他的数据依赖于每一个线程,在线程创建时创建,在线程退出时销毁

    Java中的内存分配:

            Java程序在运行时,需要在内存中的分配空间。为了提高运算效率,就对数据进行了不同空间的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。

    一. 程序计数器

     描述:程序计数器是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器。分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。

    1)在线程创建时创建

    2)当前线程所执行的字节码的行号指示器

    3)执行本地方法时,PC的值为undefined

    4)每条线程都需要有一个独立的程序计数器,各条线程之间的计数器互不影响,独立存储,我们称这类内存区域为“线程私有”的内存

    5)此内存区域是唯一一个在Java 虚拟机规范中没有规定任何OutOfMemoryError情况的区域

    二. 虚拟机栈

    描述:线程私有,它的生命周期与线程相同。虚拟机栈描述的是Java 方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)用于存储局部变量表、操作栈、动态链接、方法出口等信息

    设置大小:-Xss2M

    1)线程私有,生命周期和线程相同

    2)栈由一系列帧组成(因此Java栈也叫做帧栈)

    3)帧保存方法参数,方法的局部变量、操作数栈、常量池,指针

    4)每一次方法调用创建一个帧,并压栈

    三. 方法区

    描述:方法区在一个jvm实例的内部,类型信息被存储在一个称为方法区的内存逻辑区中。类型信息是由类加载器在类加载时从类文件中提取出来的。类(静态)变量也存储在方法区中。

    简单说方法区用来存储类型的元数据信息

    设置大小:-XX:PermSize=10M -XX:MaxPermSize=10M

    1)保存装载的类信息

    2) 存储常量池

    3) 存储static变量,方法信息(方法名,返回类型,参数列表,方法的修饰符)

    4) 通常和永久区(Perm)关联在一起可以通过-XX:PermSize-XX:MaxPermSize参数限制方法区的大小

    5)方法区是线程安全的。由于所有的线程都共享方法区,所以,方法区里的数据访问必须被设计成线程安全的

    6)  方法区也可被垃圾收集,当某个类不在被使用(不可触及)时,JVM将卸载这个类,进行垃圾收集

    四.常量池

    描述:运行时常量池是方法区的一部分.Class文件中除了有类的版本,字段,方法,接口等描述信息外还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区运行时常量池中存放

    五.堆(heap)内存

    描述:堆是Java 虚拟机所管理的内存中最大的一块。Java 堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存

    设置大小:-Xms2g -Xmx2g -Xmn1g-Xss128k

    -Xms2G 虚拟机内存最小2G

    -Xms2G 虚拟机内存最大2G

    -Xmn1G 年轻代内存1G

    -Xss128 每个线程堆栈大小

    1)  Java 堆是被所有线程共享的

    2)  存放对象实例,几乎所有对象的实例都在这里分配内存

    3)堆是垃圾收集器管理的主要区域,因此很多时候也被称做“GC 堆”。

    4)堆的大小可以通过-Xms(最小值)和-Xmx(最大值)参数设置,-Xms为JVM启动时申请的最小内存,默认为操作系统物理内存的1/64但小于1G,-Xmx为JVM可申请的最大内存,默认为物理内存的1/4但小于1G

    5)  默认当空余堆内存小于40%时,JVM会增大Heap到-Xmx指定的大小,可通过-XX:MinHeapFreeRation=来指定这个比列;当空余堆内存大于70%时,JVM会减小heap的大小到-Xms指定的大小,可通过XX:MaxHeapFreeRation=来指定这个比列

    6)  从内存回收的角度看,由于现在收集器基本都是采用的分代收集算法,所以Java 堆中还可以细分为:新生代和老年代

    新生代:程序新创建的对象都是从新生代分配内存,新生代由Eden Space和两块相同大小的Survivor Space(通常又称S0和S1或From和To)构成,可通过-Xmn参数来指定新生代的大小,也可以通过-XX:SurvivorRation来调整Eden Space及SurvivorSpace的大小

    老年代:用于存放经过多次新生代GC仍然存活的对象,例如缓存对象,新建的对象也有可能直接进入老年代,主要有两种情况:1、大对象,可通过启动参数设置-XX:PretenureSizeThreshold=1024(单位为字节,默认为0)来代表超过多大时就不在新生代分配,而是直接在老年代分配。2、大的数组对象,且数组中无引用外部对象。

    老年代所占的内存大小为-Xmx对应的值减去-Xmn对应的值。

    六. 本地方法栈

    描述本地方法栈(Native MethodStacks)与虚拟机栈所发挥的作用是非常相似的,其区别不过是虚拟机栈为虚拟机执行Java 方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native 方法服务。虚拟机规范中对本地方法栈中的方法使用的语言、使用方式与数据结构并没有强制规定,因此具体的虚拟机可以自由实现本地方法栈。

    七. 直接内存

    描述:直接内存并不是虚拟机运行时数据区的一部分,也不是java虚拟机规范中定义的内存区域。但是这部分内存也被频繁使用,而且也有可能导致OutOfMemoryError一场的出现

    NIO(New Input/Output)类引入一种基于通道(Channel)与缓冲区(Buffer)的I/O 方式,它可以使用Native函数库直接分贝堆外内存,然后通过一个存储在java堆中的DirectByteBuffer对象作为这块内存的引用进行操作,

    相关文章

      网友评论

          本文标题:JVM 内存结构

          本文链接:https://www.haomeiwen.com/subject/ablbattx.html