zoukankan      html  css  js  c++  java
  • jvm相关知识点学习(一)

    1、Class loader类加载器: 

          负责加载class文件,class文件在文件开头有特定的文件标识,并且classLoader只负责class文件的加载,至于它是否可以运行,则由Execution English 决定

         

    2、Native Interfice

          本地接口的作用是融合不同的编程语言为java 所用,它的初衷是融合 c/c++程序。它的具体做法是Native Method Stack中登记native方法,在Execution Engine执行时加载native libraies.

         目前该方法使用的越来越少,除非是与硬件有关的应用。

    3、method Area方法区

          方法区是被所有的线程共享,所有的字段和方法字节码,以及一些特殊方法如构造函数,接口代码也在此进行定义,简单说,所有定义的方法的信息都保存在该区域,此区属于共享区间。

          静态变量+常量+类信息+运行时常量池存在方法区中+实例变量存在堆内存中

    4、PC Register 程序计数器

       每个线程都有一个程序计数器,就是一个指针,指向方法区中的方法字节码(下一个将要执行的指令代码),由执行引擎读取下一条指令,是一个非常小的内存空间,几乎可以忽略不计。

    5、Native Method Stack 本地方法栈

         它的具体做法是Native Method Stack中登记的native方法,在Execution Engine执行时加载native libraise.

    6、Stack栈是什么

          栈也叫栈内存,主管java 程序的运行,是在线程创建时创建,它的生命期是跟随线程的生命期,线程结束栈内存也就会释放,对于栈来说不存在垃圾回收的问题,只要线程一结束该栈就over,生命周期和线程一致,是线程私有的。基本类型的变量和对象的引用变量都是在函数的栈内存中分配。

    6.1、栈存储什么

          栈帧中主要保存3类数据:

          本地变量(local variables):输入参数和输出参数以及方法内的变量

         栈操作(Operand Stack): 记录出栈、入栈的操作

         栈帧数据(Frame Data): 包括类文件方法等

    6.2 、栈运行的原理

        栈中的数据都是以栈帧(Stack Frame)的格式存在,栈帧是一个内存区块,是一个数据集,是一个有关方法(Method)和运行期数据的数据集,当一个方法A被调用时就产生了一个栈帧F1,并被压入到栈中,A方法有调用了B方法,于是产生的栈帧F2也被压入栈,B方法又调用了C方法,于是产生的栈帧F3也被压入栈,。。。。。执行完毕后,先弹出F3栈帧,再弹出F2栈帧,在弹出F1栈帧,遵循着“先进后出”“后进先出”的原则

    三种JVM

    sun公司的HotSpot

    BEA公司的JRockit

    IBM公司的J9 VM

    堆内存示意图:

          

      

    注:伊侚区(Eden Space) 幸存0区(Survivor 0 Space) 幸存1区(Survivor 1 Space) 养老区(Tenure Generation Space) 永久存储区(Permanent Space)

    7.1 新生区

         新生区是类的诞生、成长、消亡的区域,一个类在这里产生,应用,最后被垃圾回收器收集,结束生命。新生区又分为两部分:伊甸区(Eden space )和幸存者区(Survicor space),所有的类都是在伊甸区被new 出来的。幸存区有两个:0区(Survicor 0 space)和 1区(Survivor 1 space)。当伊甸园的空间用完时,程序有需要创建对象,JVM的垃圾回收器将对伊甸园区进行垃圾回收(Minor GC),将伊甸园区中的不在被其他对象引用的对象进行销毁。然后将伊甸园中剩余对象移动到幸存0区。若幸存0区也满了,在对该区进行垃圾回收,然后移动到1区。如果1区也满了,在移动到养老区。若养老区也满了,那么这个时候产生Major GC(FullGC ),进行养老区内存清理。若养老区执行了Full GC之后发现依然无法进行对象的保存,就会产生OOM异常“outofmemoyrError”

    如果出现java.lang.OutofMemoryError:Java heap space异常,说明java虚拟机的堆内存不够。原因有二:

      (1)java虚拟机的堆内存设置的不够,可以通过参数-Xms、-Xmx来调整。

       (2)代码中创建了大量的大对象,并且长时间不能被垃圾收集器手机(存在被引用)

    7.2 养老区

         养老区用于保存从新生区筛选出来的JAVA对象,一般池对象都在这个区域活跃。

     7.3 永久区

        永久存储区是一个常驻内存区域,用于存放JDK自身所携带的Class,Interface的元数据,也就是说它存储的是运行环境必须的类信息,被装载进此区域的数据是不会被垃圾回收器回收掉的,关闭JVM才会释放此区域所占的内存。

        如果出现java.lang.outofmemoryError:PermGen space,说明是java虚拟机对永久代Prem内存设置不够。一般出现这种情况,都是程序启动需要加载大量的第三方jar包。例如:在一个Tomcat下部署了太多的应用。或者大量动态反射生成的类不断的被加载,最终导致Prem区被占满。

    JDK1.6及以前:有永久代,常量池1.6在方法区

    JDK1.7:有永久代,但已经逐步“去永久代”,常量池1.7在堆

    JDK1.8:无永久代,常量池1.8在元空间

    实际而言,方法区(Method)和对一样,是各个线程共享的内存区域,它用于存储虚拟机加载的:类信息+普通常量+静态常量+编译器编译后的代码等,虽然JVM规范将方法区描述为堆的一个逻辑部分,但它还有一个别名叫做Non-Heap(非堆),目的就是要和对分开

         对于HotSpot虚拟机,很多开发者习惯于将方法区称之为“永久代”,但严格本质上说两者是不同的,或者说使用永久代来实现方法区而已,永久代是方法区(相当于一个接口interface)的一个实现,jdk1.7的版本中,已经将原本放在永久代的字符串常量池移走。

        常量池(Constant pool)是方法区的一部分,class文件除了有类的版本、字段、方法、接口等描述信息外,还有一项信息就是常量池,这部分内容将在类加载后进入方法区的运行时常量池中存放 。

      

      

    jdk 1.8之后将最初的永久代取消了,有元空间取代

    目的:将HotSpot 与 JPockit 两个虚拟机的标准合起来了

    堆内存调优简介:

      -Xms :  设置初始分配大小,默认为物理内存的“1/64”

     -Xmx : 最大分配内存,默认为物理内存的“1/4”

    -xx+PrintGCDetail: 输出详细的GC处理日志

    一般什么时候发生GC,如何处理;

      java中的GC会有两种回收: 年轻代的Minor GC,另外一种就是老年代的FUll GC,新对象创建的时候,如果伊甸园的空间不足会触发MinorGC,如果此时老年代的内存空间不足会触发FULL GC,如果空间都不足就会抛出OutOf MemoryError。

    GC回收策略的理解:

    年轻代(伊甸园+两个幸存区),GC回收策略为“复制”

    老年代的保存空间一般较大,GC回收策略为“整理-压缩”;

    JVM在进行GC时,并非每次都对上面三个内存区域一起回收,大部分时候收的都是指新生代。

    因此GC按照回收的区域又分为了两种类型,一种是普通GC(minor GC),一种是全局GC(major GC or FUll GC),普通GC(minor GC):只针对新生代区域的GC

     全局GC(major GC or full GC ): 针对老年代GC,偶尔伴随对新生代GC以及对永久代的GC。

    GC的三种算法:

    1、年轻代中使用的是Minor GC,这种GC算法采用的是复制算法(Coping)

    原理:Minor GC 会把Eden中的所有活的对象都移到Survivor区域中,如果Survivor区中放不下,那么剩下的活的对象就被移到Old generation中,也即一旦收集后,Eden就变成空的了

    当对象在Eden(包括一个Survivor区域,这里假设是from区域)出生后,在经过一次Minor GC后,如果对象还存活,并且能够被另外的一块Survivor区域所容纳(上面已经假设为from区域,这里应为to区域,即to区域又足够的内存空间来存储Eden和from区域中存活的对象,)则使用复制算法将这些任然还存活的对象复制到另外一块Survivor区域(即to区域),然后清理所使用过的Eden以及Survivor区域(即from区域),并且将这些对象的年龄设置为1,以后对象在Survivor区每熬过一次Minor GC,就将对象的的年龄+1,当对象的年龄达到某个值时(默认是15岁,通过-xx:maxTenuringThreshold来设定参数),这些对象就会成为老年代

    -XX:MaxTenuringThreshold --设置对象在新生代中存活的次数

    年轻代中的GC,主要是复制算法(Copying)

    HotSpot JVM把年轻代分为了三部分:1个Eden区和2个Survivor区(分别叫from和to),默认比例是8:1:1,一般情况下,新创建的对象都会被分配到Eden区(一些大对象特殊处理),这些对象经过第一次Minor GC后,如果任然存活,将会被移到Survivor区,对象在Survivor区中每熬过一次Minor GC,年龄就会增加1岁,当他的年龄增加到一定的程度的时候,就会被移动到年老代中。因为年轻代中的对象基本都是朝生夕死的(80%)以上,所以在年轻代的垃圾回收算法使用的是复制算法,复制算法的基本思想就是将内存分为两块,每次只用其中的一块,当这一块内存用完,就将还活着的对象复制到另一块上。复制算法不会产生内存碎片。

       在GC开始的时候,对象只会存在于Eden区和名为“from”的Survivor区,Survivor区“to”是空的,紧接着进行GC,Eden区所有存活的对象都会被复制到“To”,而在from区中,任存活的对象会根据他们的年龄值来决定去向,年龄达到一定的值(年龄域值,可以通过-XX:MaxTenuringThreshold来设置)的对象会被移动到老年代中,没有达到阈值的对象会被复制到“To”区域,经过这次GC后,Eden和From区已经被清空,这个时候,“from”和“To”会交换他们的角色,也就是新的“To”就是上次GC前的From,新的“from”就是上次GC前的“To”,不管怎样,不管怎样都会保证名为To的Survivor区域是空的,Minor GC会一直重复这样的过程,知道“To”区被填满之后,会将多有的对象移动代老年代中。

        因为Eden区对象一般存活率低,一般的,使用两块10%的内存作为空闲和活动区间,而另外80%的内存,则是用来给新建对象分配内存的。一旦发生GC,将10%的活动区与另外80%中存活的对象转移到10%的空闲区间,接下来,将之前90%的内存全部的释放,一次类推。

       复制算法的优点和缺点:

        复制算法弥补了标记/清除算法中,内存布局混乱的缺点,不过与此同时,它的缺点也是相当明显的。

       1、它浪费了一半的内存,这太要命了

       2、如果对象的存活率很高,我们可以极端一点,假设是100%的存活,那么我们需要将所有的对象都复制一遍,并将所有的引用地址重复一遍。复制这一工作所花费的时间,在对象存活率达到一定程度时,将会变得不可忽视,所以从以上描述不难看出,复制算法要想使用,最起码对象的存活时间要非常低才行,而且最重要的是我们必须要克服50%的内存浪费。

    标记清除/标记整理算法:FULLGC又叫MajorGC(全局GC)

    老年代一般是由标记清除或者是标记清除与标记整理的混合实现。

    标记清除: 1、标记:从根集合开始扫描,对存活的对象进行标记。

                        2、清除: 扫描整个内存空间,回收未被标记的对象,使用free-list记录可以标记的区域。

    标记清除的优点和缺点:

                 1、首先,他的缺点是效率比较低(递归与全堆对象遍历),而且在进行GC的时候,需要停止应用程序,这会导致用户体验非常的差劲。

                 2、其次,主要的缺点是这种方式清理出来的空闲内存不是连续的,这点不难理解,我们的死亡对象都是随即的出现在内存的各个角落的,现在把他们清除之后,内存的布局自然会乱七八糟。而为了应付这一点,JVM就不得不维持一个内存的空闲列表。这又是一种开销,而且在分配数组对象的时候,寻找连续的内存空间会不太好找。

     标记整理:标记整理算法唯一的缺点就是效率也不高,不仅要标记所有存活的对象,还要整理所有存活对象的引用地址。从效率上来说,标记/整理算法要低于复制算法。

    内存效率:复制算法>标记清除算法>标记整理算法(此处的效率只是简单的对比时间复杂度,实际情况不一定如此)

    内存整齐度:复制算法=标记整理算法>标记清除算法

    内存利用率:标记整理算法=标记清除算法>复制算法

    有没有最有的GC算法:没有,只有最合适的算法======> 分代收集算法

  • 相关阅读:
    浅谈Cauchy不等式
    终于结束的起点——CSP-S 2019 第二轮游记
    LOJ 10172 涂抹果酱
    数字表格
    CSP-S 2019 第一轮 游记
    20191011模拟赛
    Luogu 2327 扫雷
    NOIAC 30 candy
    FormData文件上传
    sde表空间无法导入数据和编辑
  • 原文地址:https://www.cnblogs.com/wcgstudy/p/11216475.html
Copyright © 2011-2022 走看看