java 内存区域,垃圾回收

来源:互联网 发布:数据库系统基础知识 编辑:程序博客网 时间:2024/06/04 18:06

          1,jvm内存区域

                jvm内存区主要包括线程私有的程序计数器,虚拟机栈,本地方法栈,和线程共有的堆,方法区,

                程序计数器:指示当前线程所执行的字节码执行到了第几行,字节码解释器工作时,会改变计数器的值取下条指令。

                虚拟机栈:一个线程的每个方法在执行时,都会创建一个栈帧,栈帧存储方法执行所需参数和产生的局部变量。当方法被调用时栈帧入栈,完成时出栈

                局部变量表中存储着方法的相关局部变量,包括各种基本数据类型,对象的引用,返回地址等。局部变量表是在编译时就已经确定好的,方法运行所需要分配的空间在栈帧中是完全确定的,在方法的生命周期内都不会改变。

                 虚拟机栈中定义了两种异常,如果线程调用的栈深度大于虚拟机允许的最大深度,则抛出StatckOverFlowError(栈溢出);不过多数Java虚拟机都允许动态扩展虚拟机栈的大小(有少部分是固定长度的),所以线程可以一直申请栈,直到内存不足,此时,会抛出OutOfMemoryError(内存溢出)。

                 本地方法栈:用来执行native方法,其他和虚拟机栈差不多

                 堆:存储对象的实例,虚拟机启动时创建,逻辑上连续,Java GC所管理的主要内存区,如果在垃圾回收后任然没有足够内存分配,将会抛OutOfMemoryError:Java heap space异常

               方法区:各个线程共享存储已被虚拟机加载的类信息,常量,静态变量,既编译器编译后的代码。可以选择是否进行垃圾回收

                运行时常量池,方法区的一部分,class文件还包括常量池,存放存储编译期就生成的字面常量、符号引用、翻译出来的直接引用。除编译器常量外,还可以存运行时常量。

               对象的引用,有句柄引用和直接引用

                 Object obj = new Object

                 Object obj 存储在Java栈本地变量表中(reference类型),  new object()作为实例存在堆中, 方法区中存储Object类型信息

              句柄引用

              

  通过句柄访问的实现方式中,JVM堆中会专门有一块区域用来作为句柄池,存储相关句柄所执行的实例数据地址(包括在堆中地址和在方法区中的地址)。好处是reference存储的是稳定的句柄地址,对象被移动(垃圾回收移动对象很普遍)只需改变句柄的实例数据指针,reference不需改变

              

         直接指针访问,reference存储的就是对象地址,好处速度块,节省一次指针定位开销。

           Java内存分配和回收机制;分代分配,分代回收,对象根据存活的时间分为:年轻代,年老代,永久代(方法区)。

年轻代(Young Generation):对象被创建时,内存的分配首先发生在年轻代(大对象可以直接被创建在年老代),大部分的对象在创建后很快就不再使用,因此很快变得不可达,于是被年轻代的GC机制清理掉(IBM的研究表明,98%的对象都是很快消亡的),这个GC机制被称为Minor GC或叫Young GC。注意,Minor GC并不代表年轻代内存不足,它事实上只表示在Eden区上的GC。

         对象存活的两种判定方法

       1,引用计数法:给对象加引用计数器,每到一个对象引用时加 1, 引用失效时减1,计数器为0时,表示不被使用。

                   好处:实现简单,判定效率高,   缺点:难以解决对象相互引用问题

       2 可达性分析算法:通过一系列称为“GC Roots”的对象作为起始点,当从、gc-roots到一个对像不可达时,证明对象不可用。

        Java对象引用;希望描述一类对像,当内存够用时,保留内存中,如果进行垃圾回收后还很紧张,则抛弃这些对象

         1 强引用:如object obj = new object() 这样的,只要引用存在,对象就不会回收

          2 软引用:有用但非必须对象,在发生内存溢出前,列进回收范围进行二次回收,如果这此回收还没有足够内存,就会抛出异常;

          3 弱引用:非必须对象,只能生存到下次垃圾回收前:

         4 虚引用:最弱引用,无法通过虚引用获取对象实例,目的是在对象回收时收到一个系统通知

          方法区的垃圾回收主要有:废弃常量和无用类  无用类条件:类的实例全回收,2 加载该类的类加载器回收,3 类对应的Class对象没有被引用

          垃圾收集算法

】         1 :标记-清除,算法先标出所有需要回收的对象,回收被标记的对象缺点:标记和清楚效率不高,产生大量不连续碎片

        2 : 标记复制:将内存分为俩块,每次只使用一块,当一块使用完后,将还存在的对象复制到另一块。由于新生代中对象%98朝生夕死,所以是将空间分为较大的Eden,和两块娇小的survior,  当回收时将Eden和survior中存活的对象复制到另一个survior,当survior不够用时,依赖其他内存(老年代)分配担保。

         3:标记-整理,标记过程与标记清除相同,后续让所有存活对象向一端移动,清理边界以外内存。

          内存分配机制:

          1  绝大多数刚创建的对象会被分配在Eden区,其中的大多数对象很快就会消亡。Eden区是连续的内存空间,因此在其上分配内存极快,Eden区是连续的空间,且Survivor总有一个为空。经过一次GC和复制,一个Survivor中保存着当前还活着的对象,而Eden区和另一个Survivor区的内容都不再需要了,可以直接清空,到下一次GC时,两个Survivor的角色再互换。因此,这种方式分配内存和清理内存的效率都极高,这种垃圾回收的方式就是著名的标记复制,

         2 年老代(Old Generation):对象如果在年轻代存活了足够长的时间而没有被清理掉(即在几次Young GC后存活了下来),则会被复制到年老代,用-XX:MaxTenuringThreshold控制,大于该值进入老年代年老代的空间一般比年轻代大,能存放更多的对象,在年老代上发生的GC次数也比年轻代少。当年老代内存不足时,将执行Major GC,也叫 Full GC,执行依次Full GC需要很长时间。一般是young GC 的10倍以上。如果对象比较大(比如长字符串或大数组),Young空间不足,则大对象会直接分配到老年代上(大对象可能触发提前GC,应少用,更应避免使用短命的大对象)。用-XX:PretenureSizeThreshold来控制直接升入老年代的对象大小,大于这个值的对象会直接分配在老年代上。

            3 在发生Minor GC时,虚拟机会检查每次晋升进入老年代的大小是否大于老年代的剩余空间大小,如果大于,则触发一次Minor GC安全,否则,就查看是否设置了-XX:+HandlePromotionFailure(允许担保失败),如果允许,检查老年代可用最大连续空间是否大于历次晋升到老年代对象的品均大小,如果大于,尝试进行MinorGC,此时可以容忍内存分配失败;如果小于或不允许,则仍然进行Full GC

                并发是指用户线程与GC线程同时执行(不一定是并行,可能交替,但总体上是在同时执行的),不需要停顿用户线程(其实在CMS中用户线程还是需要停顿的,只是非常短,GC线程在另一个CPU上执行);

     并行收集是指多个GC线程并行工作,但此时用户线程是暂停的;
所以,Serial是串行的,Parallel收集器是并行的,而CMS收集器是并发的.

原创粉丝点击