Jvm内存模型与垃圾回收

作者: Tim在路上 | 来源:发表于2018-10-08 22:42 被阅读1次

    内存模型

    JVM内存空间包含:方法区、java堆、java栈、本地方法栈。


    352511-20170810232433792-373676900.png

    方法区是各个线程共享的区域,存放类信息、常量、静态变量。

    java堆也是线程共享的区域,我们的类的实例就放在这个区域,可以想象你的一个系统会产生很多实例,因此java堆的空间也是最大的。如果java堆空间不足了,程序会抛出OutOfMemoryError异常。

    java栈是每个线程私有的区域,它的生命周期与线程相同,一个线程对应一个java栈,每执行一个方法就会往栈中压入一个元素,这个元素叫“栈帧”,而栈帧中包括了方法中的局部变量、用于存放中间状态值的操作栈,这里面有很多细节,我们以后再讲。如果java栈空间不足了,程序会抛出StackOverflowError异常,想一想什么情况下会容易产生这个错误,对,递归,递归如果深度很深,就会执行大量的方法,方法越多java栈的占用空间越大。

    本地方法栈角色和java栈类似,只不过它是用来表示执行本地方法的,本地方法栈存放的方法调用本地方法接口,最终调用本地方法库,实现与操作系统、硬件交互的目的。

    PC寄存器,说到这里我们的类已经加载了,实例对象、方法、静态变量都去了自己改去的地方,那么问题来了,程序该怎么执行,哪个方法先执行,哪个方法后执行,这些指令执行的顺序就是PC寄存器在管,它的作用就是控制程序指令的执行顺序。

    执行引擎当然就是根据PC寄存器调配的指令顺序,依次执行程序指令。

    堆与栈分开设计是为什么呢?

    • 栈存储了处理逻辑、堆存储了具体的数据,这样隔离设计更为清晰
    • 堆与栈分离,使得堆可以被多个栈共享。
    • 栈保存了上下文的信息,因此只能向上增长;而堆是动态分配
      栈的大小可以通过-XSs设置,如果不足的话,会引起java.lang.StackOverflowError的异常
    名称 特征 作用 配值 异常
    栈区 线程私有,使用一段连续的内存空间 存放局部变量表、操作栈、动态链接、方法出口 -XSs StackOverflowError OutOfMemoryError
    堆区 线程共享,生命周期与虚拟机相同 保存对象实例 -Xms -Xmx -Xmn OutOfMemoryError
    程序计数器 线程私有、占用内存小 字节码行号
    方法区 线程共享 存储类加载信息、常量、静态变量等 -XX:PermSize -XX:MaxPermSize OutOfMemoryError

    垃圾回收

    Generational Collection 分代收集
    目前JVM主要采取的一种方法,思想就是把JVM分成不同的区域。每种区域使用不同的垃圾回收方法。

    • 新生代(Young Generation):用于存放新创建的对象,采用复制回收方法,如果在s0和s1之间复制一定次数后,转移到年老代中。这里的垃圾回收叫做minor GC;
    • 年老代(Old Generation):这些对象垃圾回收的频率较低,采用的标记整理方法,这里的垃圾回收叫做 major GC。
    • 永久代(Permanent Generation):存放Java本身的一些数据,当类不再使用时,也会被回收。

    在新生代中,分为三个区:Eden, from survivor, to survior。

    • 当触发minor GC时,会先把Eden中存活的对象复制到to Survivor中;
    • 然后再看from survivor,如果次数达到年老代的标准,就复制到年老代中;如果没有达到则复制到to survivor中,如果to survivor满了,则复制到年老代中。
    • 然后调换from survivor 和 to survivor的名字,保证每次to survivor都是空的等待对象复制到那里的。

    相关文章

      网友评论

        本文标题:Jvm内存模型与垃圾回收

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