JVM内存模型简介

一、什么是JVM

     JVM 全称是Java Virtual Machine ,Java 虚拟机。

     所有的Java程序都在Java虚拟机中运行,存在于内存中。

二、执行过程

    1、装载 :二进制字节码并加载至JVM中

    2、链接:字节码校验,解析接口、类。初始化静态变量赋值。校验属性、方法的存在

    3、初始化:静态代码块、构造函数、静态属性

  

三、JVM内存模型

  寄存器:PC寄存器是用于存储每个线程下一步将执行的JVM指令

  方法区:类信息(名称、修饰符等),类中的静态变量、类中定义为final类型的常量、类中的Field信息、类中的方法信息。方法区域也是全局共享的。

  本地方法堆栈:此区域用于存储每个native方法调用的状态。

  JVM栈:线程私有的,基本类型(int,double)、对象地址(指向堆),每个方法就是一个栈帧。

  一个Native Method就是一个Java调用非Java代码的接口。一个Native Method是这样一个Java的方法:该方法的实现由非Java语言实现,比如C或C++。

四、类加载机制

  双亲委派机制。类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,

     如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。

   

五、堆内存分析

  

        JVM将内存划分为

            New(年轻代)

           Tenured(年老代)

           永久代(Perm)

六、垃圾回收机制

  1、引用计数(reference counting)
      原理:此对象有一个引用,则+1;删除一个引用,则-1。只用收集计数为0的对象。
    
  2、复制
      原理:把内存空间划分为2个相等的区域,每次只使用一个区域。垃圾回收时,遍历当前使用区域,把正在使用的对象复制到另外一个区域。
      优点:不会出现碎片问题。
      缺点:1、暂停整个应用。2、需要2倍的内存空间。


  3、标记-清扫
      原理:对于“活”的对象,一定可以追溯到其存活在堆栈、静态存储区之中的引用。这个引用链条可能会穿过数个对象层次。第一阶段:从GC roots开始遍历 所有的引用,对有活的对象进行标记。第二阶段:对堆进行遍历,把未标记的对象进行清除。这个解决了    循环引用的问题。
      缺点:1、暂停整个应用;2、会产生内存碎片。

  4、标记-压缩
      原理:第一阶段标记活的对象,第二阶段把为标记的对象压缩到堆的其中一块,按顺序放。
      优点:1、避免标记扫描的碎片问题;2、避免停止复制的空间问题。
      
  5、分代
      原理:基于对象生命周期分析得出的垃圾回收算法。把对象分为年轻代、年老代、持久代,对不同的生命周期使用不同的算法(2-3方法中的一个即4自适应)进行回收。

     (1) minor gc

     (2)full  gc

            

                1、Full GC将会同时回收年轻代、年老代

                2、当永久代满时也会引发Full GC,会导致Class、Method元信息的卸载

  七、内存调优      

  系统崩溃前的一些现象

    1、每次垃圾回收的时间越来越长,由之前的10ms延长到50ms左右,FullGC的时间也有之前的0.5s延长到4、5s

    2、FullGC的次数越来越多,最频繁时隔不到1分钟就进行一次FullGC

    3、年老代的内存越来越大并且每次FullGC后年老代没有内存被释放

     

          Q:为什么崩溃前垃圾回收的时间越来越长?

          A:根据内存模型和垃圾回收算法,垃圾回收分两部分:内存标记、清除(复制),标记部分只要内存大小固定时间是不变的,变的是复制部分,因为每次垃圾回收都有一些回收不掉的内存,所以增加了复制量,导致时间延长。所以,垃圾回收的时间也可以作为判     断内存泄漏的依据

      Q:为什么Full GC的次数越来越多?

      A:因此内存的积累,逐渐耗尽了年老代的内存,导致新对象分配没有更多的空间,从而导致频繁的垃圾回收

      Q:为什么年老代占用的内存越来越大?

      A:因为年轻代的内存无法被回收,越来越多地被Copy到年老代

 

    内存调优原则

      1、多数的Java应用不需要在服务器上进行GC优化;

      2、多数导致GC问题的Java应用,都不是因为我们参数设置错误,而是代码问题;

      3、在应用上线之前,先考虑将机器的JVM参数设置到最优(最适合);

      4、减少创建对象的数量;

      5、减少使用全局变量和大对象;

      6、GC优化是到最后不得已才采用的手段;

      7、在实际使用中,分析GC情况优化代码比优化GC参数要多得多;

   GC优化的目的

                 1、将转移到老年代的对象数量降低到最小;

                  2、减少full GC的执行时间;

 

  为了达到上面的目的,一般地,你需要做的事情有

      1、减少使用全局变量和大对象;

      2、调整新生代的大小到最合适;

      3、设置老年代的大小为最合适;

      4、选择合适的GC收集器;

posted @ 2016-05-05 16:50  浮生若云  阅读(641)  评论(0编辑  收藏  举报