zoukankan      html  css  js  c++  java
  • JVM学习

    1、JVM内存模型

      


    a、栈:

      包括虚拟机栈和本地方法栈。

      虚拟机栈为线程私有,生命周期与线程相同。java方法执行时会创建一个栈帧,里面保存着对象引用、基本类型数据等

      本地方法栈和虚拟机栈类似,虚拟机为java方法服务,为本地方法栈为Native方法服务。

    b、方法区:

      方法区其中一种实现为永久代(PermGen),他是所有线程共享的区域,里面保存着类信息、静态变量、常量等。

    c、堆(heap):

      所有线程共享区域,里面保存着对象和数组(java8开始静态变量和常量也保存在堆中)

    d、PC寄存器(程序计数器):

      线程私有,记录着每个线程运行的位置

    e、元空间(Metaspace):

      从java1.7开始,永久代里的数据有一部分数据开始移到堆中保存了,到了java1.8,永久代已经完全移除,取而代之的是元空间。他的作用类似永久代

    2、个别内存区域的单独介绍

    a、堆:

      堆内存分为新生代(伊甸园eden、幸存区from Survivor -to Survivor ,默认大小8:1:1(对象的生命周期不一样,98%的对象在minor gc时被回收掉,这样可以利用90%空间,这个大小是经验值))和老年代。堆数据优先保存在eden区,大对象直接进去老年区。当jvm经历了Minor Gc时,对象从eden区移至Survivor区。当对象在Survivor经历了MaxTenuringThrehold(默认15)-1(从Eden到Survivor已经经历了1次)次后仍然存活,对象移至老年代。

    b、元空间:

      java8开始,jvm不在支持PermSize和MaxPermSize参数配置永久代。但是可以通过 -XX:MetaspaceSize和 -XX:MaxMetaspaceSize(可防止元空间占用太多本地内存)来配置元空间大小。

      元空间与永久代最大的区别是:元空间不在虚拟机中,而在本地内存中。同时原来的常量移到了堆中的运行时常量池,静态变量也移到堆中了,因此java8中的堆内存会比以前大很多

      由于永久代每次FullGc都会使永久代数据移动,同时类信息的大小比较难以确定等原因,使得永久代大小也难以确定。因此永久难以调优。元空间有元空间虚拟机管理,同时可以动态管理元空间大小。节约了GC扫描和压缩时间。

    3、对象已死:

      a、引用计数法:给对象引用加一个计数器,当一个地方引用它一次,加1,引用失效时,减1,为0时则对象已死。

        缺点:当实例相互引用时,无法判断是否为已死

      b、可达性分析(根搜索算法):GcRoots不可达时,已死。(通过一系列名为"GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时)

        哪些可以作为GC ROOT(在运行中的变量):虚拟机栈本地变量表引用的对象,类静态变量引用的对象,常量引用的对象,本地方法栈中JNI引用的对象

    4、垃圾回收算法

    a、标记-清除:

      缺点:标记和清除的效率都不高,以及标记清除后会产生大量的内存不连续的碎片

    b、复制算法:

      介绍:把内存分为俩快,一个内存满时,将活的对象移动的另一个内存,将满的内存清空

      缺点:浪费空间

      ps:eden -> survivor使用的就是复制算法,当eden区存活率高时,使用老年代空间(伊甸园和幸存区默认空间比例8:1)

        fromSurvivor -> toSurvivor也使用的是复制算法

    c、标记-整理算法:

      与标记-清除算法一样,但是这个是标记后让所有存活的对象移到一端,然后清空另一端

    d、分代收集算法:

      根据不同的区使用不同的回收机制

      ps:一般分为新生代和老年代,新手代存活率低使用复制算法,老年代存活率高使用标记清除或者标记整理算法。

     minor gc之前,进行担保空间等检查,不满足条件,直接full GC(major gc 对于老年代)

    5、FullGc的条件

    a、System.gc()方法调用

    b、老年代空间(old/Tenured)不足 

    c、永生代(元空间)空间不足

    d、CMS GC时出现promotion failed和concurrent mode failure 

    e、统一Minor Gc晋升到老年代的平均值大于老年代的剩余空间

    f、堆中分配很大的对象,老年代中没有足够的连续空间保存该大对象

    6、垃圾回收器

      垃圾回收有很多类型,这个主要回顾一下CMS和G1

    a、CMS:

      优点:减少程序的停顿时间(但是在初始标记和重新标记时依然会发生 stop the world)(Parallel Scavenge优点关注吞吐量)

       缺点:由于在gc时,程序仍然在运行,这导致垃圾回收并不一定完全,甚至可能发生错误导致执行fullGC,同时这也导致cms的回收频率比较高,影响应用程序的吞吐量(要求CPU),由于cms采用标记清楚算法,易产生大量空间碎片,这导致给大对象分配空间时可能无法找到连续空间,从而导致fullGC

    b、G1 

      g1回收器将堆空间划分为多个区域(即会有个多个Eden、多个Survivor、多个old区、多个Humongous区(用于保存大对象的区域))

      g1回收器或在第一时间处理垃圾最多的区域,虽然也会暂停应用,但是会花费较少的时间回收垃圾最多的区域。

      g1与CMS相比的优点:1、因为划分为多个区域,回收时减少了内存碎片的产生。2、g1适用与新生代和老年代,CMS只适用用老年代。

      

      

      

  • 相关阅读:
    已知sim3相似变换矩阵,如何求解出R, s, t ,从sim3相似变换矩阵中恢复和获得尺度、旋转、平移
    dynamic_cast用法总结
    为什么不建议用 equals 判断对象相等?
    玩转 Java 动态编译,秀了秀了~!
    如何不改表结构动态扩展字段?
    Java 中 long 是不是原子操作?
    7 个超实用的 MySQL 语句写法,让同事们眼前一亮!
    Spring Boot 集成 Flyway,数据库也能做版本控制,太牛逼了!
    Dubbo 的设计思想,真优秀!
    一个高性能、小而美的序列化工具!
  • 原文地址:https://www.cnblogs.com/jaxlove-it/p/9309262.html
Copyright © 2011-2022 走看看