• 虚拟机知识点


    1、虚拟机的组成部分及作用

      1.1、类加载器(ClassLoader)

          根据给定的全限定类名加载Java代码,转化为字节码,传递给运行时数据内存区

      1.2、运行时数据内存区(Runtime data area)

      1.2.1、程序计数器(Program Counter Register)

        * 线程私有

        * 小块内容空间,不存在溢出情况

        * 用来确定指令位置

      1.2.2、虚拟机栈(VM Stack)

        * 线程私有

        * 描述的是Java方法执行的内存模型,方法的调用过程对应着入栈和出栈,栈中保存了局部变量、操作数栈、动态连接、方法出口等信息

        * 虚拟机规范中指明了两种内存溢出的场景:超出栈的深度、可变长栈的最大可获取深度被超出

      1.2.3、本地方法栈(Native Method Stack)

        * 基本上与虚拟机栈一样,Hot-Spot虚拟机两者直接合二为一,这块的规范并无强制规定

        * 与虚拟机栈不同的是,这边执行的是本地方法

      1.2.4、Java堆(Heap)

        * 最大的一块内存

        * 线程共享

        * 几乎存放对象实例、数组

        * 垃圾收集器管理的就是这里,所以也叫GC堆

        * 分代收集理论

        * 没内存完成实例分配也没办法扩展的时候,内存溢出

      1.2.5、方法区

        * 线程共享

        * 非堆

        * 6含之前基本上是永久代的实现方式,后续到8后基本废弃永久代,改为本地内存实现(这里指的是Hot-Spot,因为JRockit和J9本来就是这么做的)

        * 内存溢出和堆是一样的

        1.2.5.1、运行时常量池

          * 字面量和符号的引用

          * 常规的是字符串常量池应用

      1.2.6、直接内存,与这边的运行时数据内存无关,主要用于IO、NIO,也不受JVM限制,但受本地内存限制,也会有内存溢出

      1.3、执行引擎

      主要用于转化字节码为机器码,并执行指令

     

      1.4、本地库接口

      对接本地方法,比如调用C++语言的本地方法

    2、双亲委派模式

      指的是ClassLoader逐级往上的加载方式,简单来说,就是如果父类可以加载,就一直往上,可以解决的问题是:2个以上的类加载器会导致加载的类信息存在两个以上,会导致例如静态变量重复初始化的诡异场景

      注:Spring Boot的DevTools带的热加载机制,大致也是通过两个ClassLoader的形式来执行,其中一个加载器,加载我们自己写的Java代码,这样可以通过重新加载这部分的类信息,做到热部署的效果。

    3、常见的垃圾收集器

      3.1、Serial收集器:1.3.1之前新生代收集器唯一选择。

        串行单线程收集器,垃圾收集时候必须stop the world,暂停其他所有工作

        新生代-复制算法,老年代:标记-整理算法

      3.2、ParNew收集器:JDK7之前的首选新生代收集器

        * Serial收集器的多线程并行版本

        * -XX:ParalleGCThreads       限制垃圾收集线程数

        * 1.7之后已经算是退出历史舞台了,G1垃圾收集器是面向全堆的    

      3.3、CMS(Concurrent Mark SWEEP):并发的低延迟收集器

        * CPU敏感型,是老年代的收集器,默认与ParNew收集器共用

        * 真正意义上第一台支持并发的牢记收集器

      3.4、Parallel Scavenge:1.4新生代收集器,并无法和CMS一起使用

       3.5、G1:Java7之后的主流垃圾收集器,在Java8之后相对比较成熟了,Java9之后作为默认的垃圾收集器选择(Oracle现在对Java版本的长期支持是隔三代,目前是8、11、14,记得应该是维护三年,由于Spring框架目前仅支持Java8,所以现在用的最多的应该是Java8)

        * 面向全堆的垃圾收集器(不再是新生代一个收集器,老年代一个收集器)

        * 废弃了永久代的实现,改为和j9和JRocket一样的元数据空间实现;

          -XX:PermSize 和 -XX:MaxPermSize都将被忽略

          -XX:MetaspaceSize 初始化元空间的大小(默认12Mbytes在32bit client VM and 16Mbytes 在32bit server VM,在64bit VM上会更大些)

          -XX:MaxMetaspaceSize 最大元空间的大小(默认本地内存)

          -XX:MinMetaspaceFreeRatio 扩大空间的最小比率,当GC后,内存占用超过这一比率,就会扩大空间

          -XX:MaxMetaspaceFreeRatio 缩小空间的最小比率,当GC后,内存占用低于这一比率,就会缩小空间

        * 由于官方倾向G1的完全替换,所以取消了ParNew+Serial Old以及Serial+CMS的支持,ParNew只能和CMS配合使用 

      新生代 老年代
    Serial
    Serial Old
    ParNew
    Parallel Old
    Parallel Scavenge
    CMS(Concurrent Mark Sweep)
    G1(Garbage First)
         
         

                垃圾收集器对应新生代和老年代

      目标|优点 缺点
    Serial 单线程,极限性能,一定程度上适用于微服务的架构 糟糕的Stop the World体验
    Serial Old 同上 同上
    ParNew Serial的多线程版本 单核性能不占优
    Parallel Scavenge 以吞吐量为维度,旨在保证较高的吞吐量比例 用户体验(因侧重点在于有效利用CPU,会忽视响应速度的问题)
    Parallel Old 同上 同上
    CMS(Concurrent Mark Sweep) 并发、低延迟,关注服务的响应速度 1、CPU敏感;
    2、无法处理浮动垃圾导致Full GC,浮动垃圾大致是指在标记过程中会产生新的垃圾对象,这部分无法被识别,应是并发模式导致;
    3、由于采用标记-清除算法,所以有内存碎片的问题,可能因此提前触发Full GC
    G1(Garbage First) 1、面向全堆,而不再只是新生代或老年代
    2、软实时垃圾收集器目标
    3、Mixed GC模式:不再区分新老年代,而是以回收哪块内存收益最大为维度(Region堆内存布局)- 堆内存化整为零
    由于使用了Region内存布局,所以需要更多的堆内存来做卡表记录

    4、常见的垃圾回收算法:

      4.1、复制算法

    • 常见于新生代,原来是1:1内存分配两块内存区,GC的时候通过将存活对象复制到另一块内存,然后清除旧的内存区
    • 但实际上由于新生代对象的存活周期短,一般采用的8:1:1的 Eden(伊甸园):SurvivorRatio)(幸存者)*2;再通过老年代来做担保(因为使用的内存是8+1,存活的内存可能大于1,所以需要老年代来做保证有地方放溢出的存活对象)

      4.2、标记-清除算法

    • 常见于老年代,通过标记存活对象,来确定要GC的对象
    • 缺点是:内存碎片,且由于内存碎片的存在可能导致提前Full GC

      4.3、标记-整理算法  

    •  常见于老年代,也用于G1中Region;通过将存活的内存整理到同一个区域;再将边界之外的内存进行清理
    • 缺点是:必须要移动内存

    5、三项垃圾收集器的重要指标

    • 内存占用(Footprint)
    • 吞吐量(Throughput)
    • 延迟(Latency)

    6、Minor GC(新生代)、Major GC(老年代)、Full GC(全代)

  • 相关阅读:
    storm中DAU实时计算方案
    冒泡排序
    跨域
    关于java面试题
    vue+npm+Element插件+路由
    Android云端APP
    js图片预览带进度条
    jQuery上传文件显示进度条
    SSM+form表单文件上传
    SSM批量添加数据
  • 原文地址:https://www.cnblogs.com/gabin/p/13516255.html
Copyright © 2020-2023  润新知