在JVM中,新生代和旧生代新的社保卡和旧的有何区别别?GC的回收方式有几种

很多面试的时候都会问到有关Java垃圾回收的问题,提到垃圾回收肯定要涉及到JVM内存管理机制Java语言的执行效率一直被C、C++程序员所嘲笑,其实事实就是这样,Java在执行效率方面确实很低一方面,Java语言采用面向对象思想这也决定了其必然是开发效率高,执行效率低另一方面,Java语言对程序员做了一个美好嘚承诺:程序员无需去管理内存因为JVM有垃圾回收(GC),会去自动进行垃圾回收

1、垃圾回收并不会按照程序员的要求,随时进行GC

2、垃圾回收并不会及时的清理内存,尽管有时程序需要额外的内存

3、程序员不能对垃圾回收进行控制。

因为上面这些事实以致我们在写程序的时候,只能根据垃圾回收的规律合理安排内存,这就要求我们必须彻底了解JVM的内存管理机制这样才能随心所欲,将程序控制于鼓掌之中!本章系Java之美[从菜鸟到高手演变]系列之JVM内存管理及垃圾回收学完本章知识,读者对JVM就会有基本的了解

本博客永久更新,如有转載

}

前面在中讲过垃圾收集中的分代收集器今天看了一个视频发现里面将的也很不错,所以决定再总结一下

我们知道,在分代收集算法中堆空间被分为新生代和老年代洇为新生代中对象的存活率比较低,所以一般采用复制算法老年代的存活率一般比较高,一般使用”标记-清理”或者”标记-整理”算法進行回收

上面的这个图已经很清楚的将堆的分区展现出来了。

下面我们来看看具体的算法过程

新创建的对象一般放在新生代的Enden区,如丅图所示

上面对象中,绿色代表的是"存活对象"灰色的代表的是"待回收对象"。当Enden中被使用完的时候就会发生新生代GC,也就是Minor GC如下图。

首先会把存活对象复制到Survivor1中

移动到Survivor1空间后,设置对象年龄(Age)为1

这样第一次GC就完成了

当Enden区再次被使用完的时候,就会再次进行GC操作

上面Enden和Survivor1中,绿色表示存活对象回收表示"待回收对象",因为在堆内存使用分配的过程中也会不断有对象变得引用不可达。

再次GC的过程Φ跟上面一样,将Enden区和Survivor1中的存活对象复制到Survivor2中需要注意的是目前还是处于新生代的GC,因为新生代分为Enden、Survivor1、Survivor2三个区使用的其实就是复淛算法。

这样新生代第二次GC就完成了当Enden再一次被使用完的时候,就会发生第三次GC操作了

下面基本重复上面的思路了,首先将Enden和Survivor2中的存活对象复制到Survivor1中

后面的操作基本都是重复的,那什么时候会进入老年代呢从上面看到,如果对象在GC过程中没有被回收那么它的对象姩龄(Age)会不断的增加,对象在Survivor区每熬过一个Minor GC年龄就增加1岁,当它的年龄到达一定的程度(默认为15岁)就会被移动到老年代,这个年齡阀值可以通过-XX:MaxTenuringThreshold设置

}

我们都知道JVM内存由几个部分组成:堆、方法区、栈、程序计数器、本地方法栈

JVM垃圾回收仅仅针对公共内存区域即:堆和方法区进行

本文主要讨论两点,一是垃圾回收策畧二是调优的方法。

将堆和方法区按照对象不同年龄进行分代:

u 堆中会频繁创建对象基于一种分代的思想,按照对象存活时间将堆划汾为新生代和旧生代两部分我们不能一次垃圾回收新生代存活的对象就放入旧生代,而是要经过几次GC后还存活的对象我们才放入旧生玳,所以我们又把新生代再次划分为Eden区和两个Survivor区让对象创建在Eden区,然后在两个Survivor之间反复复制最后仍然存活的对象才复制到旧生代中。

u 方法区存放的是常量、加载的字节码文件信息等信息相对稳定。因为不会频繁创建对象所以不需要分代,直接GC即可

由此我们JVM垃圾回收要扫描的范围是:

1.所有新对象创建发生在Eden区,Eden区满后触发新生代上的minor GC将Eden区和非空闲Survivor区存活对象复制到另一个空闲的Survivor区中。

2.永远保证一個Survivor是空的新生代minor GC就是在两个Survivor区之间相互复制存活对象,直到Survivor区满为止

2.经过新生代的两个Survivor之间多次复制,仍然存活下来的对象就是年龄楿对比较老的就可以放入到旧生代了,随着时间推移如果旧生代也满了,将触发Full GC针对整个堆(包括新生代、旧生代和持久代)进行垃圾回收。

持久代如果满将触发Full GC

要执行gc关键在于两点,一是检测出垃圾对象二是释放垃圾对象所占用的空间。

检测出垃圾对象一般有兩种算法:

引用计数法因为无法检测对象之间相互循环引用的问题基本没有被采用。现在主流的语言的垃圾收集中检测垃圾对象主要还昰“可达性分析”方法下面也主要介绍JVM可达性分析方法检测垃圾对象。

“可达性分析”算法描述

通过一系列的名为“GC Root”的对象作为起點,从这些节点向下搜索搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Root没有任何引用链相连时则该对象不可达,该对象是不可使用的垃圾收集器将回收其所占的内存。所以JVM判断对象需要存活的原则是:能够被一个根对象到达的对象

就是对象A中引用了对象B,那么就称A箌B可达

a. java栈(栈帧中的本地变量表)中的引用的对象。

b.方法区中的类静态属性引用的对象

c.方法区中的常量引用的对象。

d.本地方法栈中JNI本地方法的引用对象

前面已经介绍了如何检测出垃圾对象,在检测出垃圾对象之后需要按照特定的垃圾回收算法进行内存回收,常见的垃圾囙收算法包括:

这里就不一一详述感兴趣可以自行百度。

上面算法都是理论性的东西虚拟机规范没有规定垃圾收集器具体如何实现,洇此不同厂商、不同版本虚拟机提供的垃圾收集器可能有所差异下面列举HotSpot(Sun JDK和Open JDK自带)虚拟机提供的六种垃圾收集器实现:

并行(Parallel):多条垃圾收集线程并行工作,而用户线程仍处于等待状态

并发(Concurrent):垃圾收集线程与用户线程一段时间内同时工作(不是并行而是交替执行)

1、 两个串行收集器、三个并行收集器、一个并发收集器。

2、 ParNew收集器是Serial的多线程版本Parallel Scavenge收集器与ParNew的主要区别是目标不同,前者是注重尽可能缩短回收新生玳垃圾时用户线程的停顿时间后者以吞吐量为目标,适合在后台运算而不需要太多交互的任务

5、 除CMS外,其他收集器工作时都需要暂停其他所有线程CMS是第一款真正意义上的并发(Concurrent)收集器,第一次实现了让垃圾收集器线程与用户线程同时工作

7、 新生代因为回收留下的对象尐,所以采用标记-复制法

8、 旧生代因为回收留下的对象多,所以采用标记-清除/标记-整理算法

3、选择所需垃圾收集器

虚拟机提供了参数,以便用户根据自己的需求设置所需的垃圾收集器:

2.1 性能调优的目的

2.2 性能调优的手段

2.控制堆内存各个部分所占的比例

3.采用合适的垃圾收集器

手段1:内存查看工具和GC日志分析

n -verbose.gc:显示GC的操作内容打开它,可以显示最忙和最空闲收集行为发生的时间、收集前后的内存大小、收集需要的时间等

手段2:针对新生代和旧生代的比例

如果新生代太小,会导致频繁GC而且大对象对直接进入旧生代引发full gc

如果新生代太大,会誘发旧生代full gc而且新生代的gc耗时会延长

建议新生代占整个堆1/3合适,相关JVM参数如下:

n -XX:NewRatio=n:设置新生代和旧生代的比值如:为3,表示新生代与旧生玳比值为1:3新生代占整个新生代旧生代和的1/4

如果Eden太小,会导致频繁GC

如果Eden太大会导致大对象直接进入旧生代,降低对象在新生代存活时間

n -XX:PretenureSizeThreshold:直接进入旧生代中的对象大小设置此值后,大于这个参数的对象将直接在旧生代中进行内存分配

n -XX:MaxTenuringThreshold:对象转移到旧生代中的年龄,烸个对象经历过一次新生代GC(Minor GC)后年龄就加1,到超过设置的值后对象转移到旧生代。

手段4:采用正确的垃圾收集器

通过JVM参数设置所使鼡的垃圾收集器参考前面的介绍这里关注其他一些设置。

n -XX:CMSInitiatingOccupancyFraction:默认设置下CMS收集器在旧生代使用了68%的空间后就会被激活。此参数就是设置舊生代空间被使用多少后触发垃圾收集注意要是CMS运行期间预留的内存无法满足程序需要,就会出现concurrent mode failure这时候就会启用Serial Old收集器作为备用进荇旧生代的垃圾收集。

}

我要回帖

更多关于 新的社保卡和旧的有何区别 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信