大家好,over flow在线观看免费观看相信很多的网友都不是很明白,包括详解GC机制及Minor也是一样,不过没有关系,接下来就来为大家分享关于over flow在线观看免费观看和详解GC机制及Minor的一些知识点,大家可以关注收藏,免得下次来找不到哦,下面我们开始吧!
概述今天主要分享下GC相关概念,为啥要讲GC呢?因为作为运维,很多时候系统都会报错内存溢出之类,而这时候都不知道源头在哪?学习一下GC的机制及MinorGC和FullGC触发条件还是有用的。
GC机制GC,即就是Java垃圾回收机制。目前主流的JVM(HotSpot)采用的是分代收集算法。与C++不同的是,Java采用的是类似于树形结构的可达性分析法来判断对象是否还存在引用。即:从gcroot开始,把所有可以搜索得到的对象标记为存活对象。
要准确理解Java的垃圾回收机制,就要从:“什么时候”,“对什么东西”,“做了什么”三个方面来具体分析。
第一:“什么时候”即就是GC触发的条件。GC触发的条件有两种。(1)程序调用System.gc时可以触发;(2)系统自身来决定GC触发的时机。
系统判断GC触发的依据:根据Eden区和FromSpace区的内存大小来决定。当内存大小不足时,则会启动GC线程并停止应用线程。
第二:“对什么东西”笼统的认为是Java对象并没有错。但是准确来讲,GC操作的对象分为:通过可达性分析法无法搜索到的对象和可以搜索到的对象。对于搜索不到的方法进行标记。
第三:“做了什么”最浅显的理解为释放对象。但是从GC的底层机制可以看出,对于可以搜索到的对象进行复制操作,对于搜索不到的对象,调用finalize()方法进行释放。
具体过程:当GC线程启动时,会通过可达性分析法把Eden区和FromSpace区的存活对象复制到ToSpace区,然后把EdenSpace和FromSpace区的对象释放掉。当GC轮训扫描ToSpace区一定次数后,把依然存活的对象复制到老年代,然后释放ToSpace区的对象。
对于用可达性分析法搜索不到的对象,GC并不一定会回收该对象。要完全回收一个对象,至少需要经过两次标记的过程。
第一次标记:对于一个没有其他引用的对象,筛选该对象是否有必要执行finalize()方法,如果没有执行必要,则意味可直接回收。(筛选依据:是否复写或执行过finalize()方法;因为finalize方法只能被执行一次)。
第二次标记:如果被筛选判定位有必要执行,则会放入FQueue队列,并自动创建一个低优先级的finalize线程来执行释放操作。如果在一个对象释放前被其他对象引用,则该对象会被移除FQueue队列。
GC过程中用到的回收算法:
通过上面的GC过程不难看出,Java堆中的年轻代和老年代采用了不同的回收算法。年轻代采用了复制法;而老年代采用了标记-整理法
程序计数器:线程私有。是一块较小的内存,是当前线程所执行的字节码的行号指示器。是Java虚拟机规范中唯一没有规定OOM(OutOfMemoryError)的区域。
Java栈:线程私有。生命周期和线程相同。是Java方法执行的内存模型。执行每个方法都会创建一个栈帧,用于存储局部变量和操作数(对象引用)。局部变量所需要的内存空间大小在编译期间完成分配。所以栈帧的大小不会改变。存在两种异常情况:若线程请求深度大于栈的深度,抛StackOverflowError。若栈在动态扩展时无法请求足够内存,抛OOM。
Java堆:所有线程共享。虚拟机启动时创建。存放对象实例和数组。所占内存最大。分为新生代(Young区),老年代(Old区)。新生代分Eden区,Servior区。Servior区又分为Fromspace区和ToSpace区。Eden区和Servior区的内存比为8:1。当扩展内存大于可用内存,抛OOM。
方法区:所有线程共享。用于存储已被虚拟机加载的类信息、常量、静态变量等数据。又称为非堆(Non–Heap)。方法区又称“永久代”。GC很少在这个区域进行,但不代表不会回收。这个区域回收目标主要是针对常量池的回收和对类型的卸载。当内存申请大于实际可用内存,抛OOM。
本地方法栈:线程私有。与Java栈类似,但是不是为Java方法(字节码)服务,而是为本地非Java方法服务。也会抛StackOverflowError和OOM。
MinorGC和FullGC概念:新生代GC(MinorGC):指发生在新生代的垃圾收集动作,因为Java对象大多都具备朝生夕灭的特性,所以MinorGC非常频繁,一般回收速度也比较快。
老年代GC(MajorGC/FullGC):指发生在老年代的GC,出现了MajorGC,经常会伴随至少一次的MinorGCMajorGC的速度一般会比MinorGC慢10倍以上。
MinorGC,FullGC触发条件MinorGC触发条件:当Eden区满时,触发MinorGC。
FullGC触发条件:
(1)调用System.gc时,系统建议执行FullGC,但是不必然执行
(2)老年代空间不足
(3)方法区空间不足
(4)通过MinorGC后进入老年代的平均大小大于老年代的可用内存
(5)由Eden区、FromSpace区向ToSpace区复制时,对象大小大于ToSpace可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小
新生代可用的GC?新生代中对象存活的时间比较短,因此给予Copying算法实现,Eden区域存放新创建的对象,S0和S1区其中一块用于存放在MinorGC的时候作为复制存活对象的目标空间,另外一块清空。
串行GC(SerialGC)比较适合单CPU的情况,可以通过-XX:UseSerialGC来强行制定;
并行回收GC(ParallelScavenge),启动的时候按照设置的参数来划定Eden/S0/S1区域的大小,但是在运行时,会根据MinorGC的频率、消耗时间来动态调整三个区域的大小,可以用过-XX:UseAdaptiveSizePolicy来固定大小,不进行动态调整;
并行GC(ParNew)划分Eden、S1、S0的区域上和串行GC一样。并行GC需要配合旧生代使用CMSGC(这是他和并行回收GC的不同)(如果配置了CMSGC的方式,那么新生代默认采取的就是并行GC的方式);
旧生代可用的GC?串行GC(SerialMSC)、并行GC(ParallelMSC)、并发GC(CMS);
关于CMS?
采用CMS时候,新生代必须使用SerialGC或者ParNewGC两种。CMS共有七个步骤,只有InitialMarking和FinalMarking两个阶段是stop-the-world的,其他步骤均和应用并行进行。持久代的GC也采用CMS,通过-XX:CMSPermGenSweepingEnabled-XX:CMSClassUnloadingEnabled来制定。在采用cmsgc的情况下,ygc变慢的原因通常是由于oldgen出现了大量的碎片。
怎么读懂GC日志?GC基本上都是这种格式:回收前区域占用的大小->回收后区域占用的大小(区域设置的大小),占用的时间
假设报错日志如下:
2019-06-22T03:00:53.638+0800:35333.562:[GC35333.562:[ParNew(promotionfailed):1877376K->1877376K(1877376K),15.7989680secs]35349.361:[CMS:2144171K->2129287K(2146304K),10.4200280secns]3514052K->2129287K(4023680K),[CMSPerm:119979K->118652K(190132K)],26.2193500secs][Times:user=30.35sys=5.19,real=26.22secs]n
解释:
1877376K->1877376K(1877376K),15.7989680secsyoung区n2144171K->2129287K(2146304K),10.4200280secold区情况n3514052K->2129287K(4023680K)heap区情况n119979K->118652K(190132K)],26.2193500secsperm区情况n[Times:user=30.35sys=5.19,real=26.22secs]整个过程的时间消耗n
篇幅有限,这里主要介绍一下概念性的东西,后面介绍下怎么监控GC和GC的一些优化参数,感兴趣的朋友可以关注一下~
over flow在线观看免费观看和详解GC机制及Minor的问题分享结束啦,以上的文章解决了您的问题吗?欢迎您下次再来哦!
还没有评论,来说两句吧...