zoukankan      html  css  js  c++  java
  • jvm内存模型

    JVM的五大内存区域

    1、程序计数器
    2、方法区(也称为永久代,后续被Metaspace取代)
    3、虚拟机栈
    4、本地方法栈
    5、堆

    1、程序计数器

    记录线程的执行位置,线程私有内存
    在多线程的情况下,线程被切换回来的时候能够知道该线程上次运行到哪儿了

    2、方法区

    方法区是所有线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量
    放在永久代中经常会出现内存溢出,即PermGen Space异常,所以用元空间取而代之
    元空间直接使用本地内存,理论上电脑有多少内存它就可以使用多少内存,所以不会再出现PermGen Space异常
    java虚拟机对方法区比较宽松,可以选择不实现垃圾收集

    3、虚拟机栈(stack)
    每个线程都有各自的Java虚拟机栈,而且随着线程的创建而创建,随着线程的死亡而死亡.
    Java虚拟机栈会为每一个即将运行的Java方法创建“栈帧”,用于存储局部变量表、操作栈、动态连接、方法返回地址等
    每个方法从开始调用到执行完成的过程,就是栈帧从入栈到出栈的过程
    如果方法A调用了方法B,那么A就会先入栈创建一个栈桢,接着B再入栈成为栈顶,B执行完先出栈,接着A执行完出栈。

    Java虚拟机栈可能出现两种类型的异常:
    1、线程请求的栈深度大于虚拟机允许的栈深度,将抛出StackOverflowError。
    2、虚拟机栈空间可以动态扩展,当动态扩展是无法申请到足够的空间时,抛出OutOfMemory异常。

    4、本地方法栈

    本地方法栈和Java虚拟机栈实现的功能与抛出异常几乎相同
    只不过虚拟机栈是为虚拟机执行Java方法服务,本地方法栈则为虚拟机使用到的本地方法服务.
    线程开始调用本地方法时,会进入一个不再受JVM约束的世界
    本地方法可以通过JNI(Java Native Interface)来访问虚拟机运行时的数据区

    5、堆(heap)

    堆区是所有线程共享的内存区域
    堆是OOM故障最主要的发源地,它存储着几乎所有的实例对象
    通常情况下,它占用的空间是所有内存区域中最大的,但如果无节制地创建大量对象,也容易消耗完所有的空间

    堆的内存空间既可以固定大小,也可运行时动态地调整,通过如下参数设定初始值和最大值
    -Xms256M. -Xmx1024M
    其中,-X表示它是JVM运行参数,ms是memorystart的简称 最小堆容量,mx是memory max的简称 最大堆容量
    但是在通常情况下,服务器在运行过程中,堆空间不断地扩容与回缩,势必形成不必要的系统压力,
    所以在线上生产环境中,JVM的Xms和Xmx设置成一样大小,避免在GC后调整堆大小时带来的额外压力

    堆分成两大块:新生代和老年代(默认空间比例为1:2)
    新生代分为三块:Eden区、From Survivor区和To Survivor区(默认空间比例为8:1:1)
    对象产生之初在新生代,步入暮年时进入老年代,但是老年代也接纳在新生代无法容纳的超大对象
    Survivor区每个对象都有一个计数器,每次YGC都会加1,默认加到15次,就要移送到老年代

    Eden区 -> Survivor 0区 -> Survivor 1区 -> 老年区的过程

    1、所有对象都在伊甸园出生,当伊甸园占满时,开始进行一次Young GC,此次GC会将已存活的对象复制到S0区中
    2、伊甸园区又被占满时,此时又进行一次Young GC,伊甸园存活的对象又复制到S0区。
    3、在若干次Young GC后,幸存区S0也满了,此时Young GC会对伊甸园和幸存区S0的做一次垃圾回收,将两个区存活的对象复制到幸存区S1中,再把伊甸园和S0清空,最后把S1的内存与S0交换,此时S1又腾空了,S0剩下一些老对象。
    4、又经历若干次GC,幸存区S0已经放满了经历过N次GC都回收不了的老对象,此时会将老对象复制到老年代中,腾空伊甸园和幸存区。
    (并非当幸存区被老对象占满才复制到老年代中,当老对象年龄达到15岁,即经历过15次GC都还活着的,也会复制到老年代中)
    (另外伊甸园中如果诞生了一个比幸存区还大的对象,那么该对象回收不了时,也会直接送入到老年代中)

    5、又经历过若干次GC后,老年代也满了,那么此时它会进行一次Full GC。
    6、当执行Full GC后,老年代还是放不下新来的对象时,就会抛出OOM

    堆特点

    Java虚拟机所需要管理的内存中最大的一块,被所有线程共享,在虚拟机启动时创建
    堆是垃圾回收的主要区域,所以也被称为GC堆.
    当线程请求分配内存,但堆已满,且内存已满无法再扩展时,就抛出OutOfMemoryError

  • 相关阅读:
    web前端技术社区分享
    programming-challenges Shoemaker's Problem (110405) 题解
    caffe 训练測试自己的数据集
    BootStrap有用代码片段(持续总结)
    H5学习_番外篇_PHP数据库操作
    WPF-MVVM-Demo
    android Toast大全(五种情形)建立属于你自己的Toast
    Java
    记一次死锁问题的排查和解决
    一步一步跟我学习lucene(19)---lucene增量更新和NRT(near-real-time)Query近实时查询
  • 原文地址:https://www.cnblogs.com/jis121/p/11045186.html
Copyright © 2011-2022 走看看