文档章节

Java虚拟机基本结构的简单记忆

算法之名
 算法之名
发布于 06/24 08:03
字数 2714
阅读 59
收藏 8

Java堆:一般是放置实例化的对象的地方,堆分新生代和老年代空间,不断未被回收的对象越老,被放入老年代空间。分配最大堆空间:-Xmx     分配初始堆空间:-Xms,分配新生代空间:-Xmn,新生代的大小一般为整个堆空间的1/3到1/4。新生代一般分为eden和survivor(from,to)区。新生代被GC15(配置参数-XX:MaxTenuringThreshold,默认15)次后仍存活,进入老年代,但也可能提前晋升,由survivor区决定。新生代和老年代都属于JVM的Heap区,另外还有一个持久代Perm区,又叫永久区,是一块线程共享的内存区域,大小决定了系统可以保存多少个类,定义太多的类,会抛出内存溢出错误。分配永久区空间:-XX:PermSize和-XX:MaxPermSize(默认为64M)。

Java栈:放置对象的方法函数的地方,所有的方法的内部变量在Java栈中,以后进先出的方式不断进栈出栈,出栈即被销毁。对于完全不会被其他线程访问的对象,可以分配在栈上,而不是分配在堆上,当方法结束后便自行销毁。分配栈空间:-Xss

JVM垃圾回收的几种方法:

1、标记清除法,标记所有从根节点开始的可达对象,未被标记的对象就是未被引用的垃圾对象,标记清除算法可能产生的最大问题就是空间碎片。标记操作完成后,系统回收所有不可达的空间。

2、复制算法。将原有的内存空间分为两块,每次只使用其中一块,通过标记清除法后,将存活对象复制到另一块内存空间,并保持连续,没有空间碎片。然后清空原内存空间。主要用在新生代的垃圾回收中,因为在新生代,垃圾对象通常会多于存活对象。

3、标记压缩法。在标记清除法的基础上,再进行一次碎片整理。使得没有空间碎片,通常用于老年代。

4、分代算法。根据新生代和老年代的不同,分别使用以上算法。另外为了高效回收新生代,在老年代的扫描中通常使用卡表。卡表用来表示老年代的某一区域中的所有对象是否持有新生代对象的引用,在新生代GC时可以不用花大量时间扫描所有老年代对象,只有卡表的标记为1时,才扫描给定区域的老年代对象,卡表为0则不扫描。

5、分区算法。将整个堆空间划分成连续的不同小空间,每个小空间都独立使用,独立回收。在相同条件下,堆空间越大,一次GC所需要的时间越长,从而产生的停顿也越长,为了更好的控制GC的停顿时间,每次合理地回收若干小区间,而不是整个堆空间,从而减少一次GC所产生的停顿。

垃圾收集器的种类(以下凡是只指定新生代的,老年代都是使用串行回收器)

1、串行回收器。单线程,独占式。串行回收时,所有线程都需要暂停。使用-XX:+UseSerialGC,表示新生代和老年代都使用串行回收器,新生代是复制,老年代是标记压缩。新生代日志标记DefNew,老年代日志标记Full GC.

2.1、并行回收器。ParNew回收器,新生代的垃圾收集器。简单将串行回收器多线程化,独占式。在并发能力比较强的CPU上,产生的停顿时间短于串行回收器。使用-XX:+UseParNewGC。线程数量使用-XX:ParallelGCThreads指定。最好与CPU数量相当,CPU数量小于8时,值为CPU数量,大于8时,值为3+((5*CPU_Count)/8)。日志标记ParNew。-XX:PretenureSizeThreshold设置对象直接晋升老年代的阈值,只对以上两种回收器有效。

2.2、并行回收器。新生代ParallelGC回收器,非常关注系统吞吐量。使用-XX:+UseParallelGC。控制系统吞吐量的两个重要参数,-XX:MaxGCPauseMillis:设置最大垃圾收集停顿时间,值大于0的整数,工作时会调整Java堆大小,如果值设的很小,JVM会使用较小的堆,导致垃圾收集变的很频繁。-XX:GCTimeRatio:设置吞吐量大小。值0到100之间的整数。值为n时,系统花费不超过1/(1+n)的时间用于垃圾收集。-XX:+UseAdaptiveSizePolicy可以打开自适应GC策略,自动调整eden,survivior的比例,晋升老年代的对象年龄等。以达到在堆大小,吞吐量和停顿时间之间的平衡点。手工调困难场合下使用,指定最大堆-Xmx,目标吞吐量-XX:GCTimeRatio,停顿时间-XX:MaxGCPauseMillis,让JVM自动调优。日志标记,PSYoungGen.注:吞吐量和吞吐时间是互相矛盾的,减少停顿时间会减少系统吞吐量,增加吞吐量会增加最大停顿。

2.3、并行回收器。老年代ParallelOldGC回收器。使用-XX:+UseParallelOldGC,新生代则会使用ParallelGC回收器。-XX:ParallelGCThreads设置线程数量。日志标志Full GC[PSYoungGen].

3、CMS回收器:标记型多线程回收器,一般工作在老年代,新生代使用ParNew回收器。分初始标记,并发标记,预清理,重新标记,并发清理,并发重置几个阶段,其中初始标记跟重新标记是系统独占的。预清理是并发的(垃圾回收线程跟应用线程同时进行),可以关闭开关-XX:-CMSPrecleaningEnabled,不进行预清理。启用CMS回收器的参数:-XX:+UseConcMarkSweepGC。默认并发线程数(ParallelGCThreads+3)/4,ParallelGCThreads表示GC并行(应用程序停止,同时多个线程一起执行GC)时使用的线程数量。并发线程数量也可以通过-XX:ConcGCThreads或者-XX:ParallelCMSThreads参数设置。因为CMS总体不是独占的,在回收过程中,应用程序依然会产生垃圾,所以当堆内存达到一定阈值是开始回收,该阈值可以使用-XX:CMSInitiatingOccupancyFraction来设置,默认是68。调优方法,当内存增长缓慢,增大阈值,降低CMS触发频率,当内存增长很快,降低阈值,避免频繁触发老年代串行收集器(老年代收集时,应用程序将完全停止,停顿时间较长)。-XX:+UseCMSCompactAtFullCollection开关可以使CMS在垃圾收集完成后进行一次碎片整理。-XX:CMSFullGCsBeforeCompaction参数可以设置多少次CMS回收后,进行一次碎片整理。日志标记:初始标记[CMS-initial-mark],开始并发标记 [CMS-concurrent-mark-start],开始并发结束标记 [CMS-concurrent-mark],预清理标记 [CMS-concurrent-preclean-start] ,预清理标记费时 [CMS-concurrent-preclean: 0.017/0.018 secs] ,预清理开始[CMS-concurrent-abortable-preclean-start],预清理结束费时[CMS-concurrent-abortable-preclean: 0.011/0.014 secs],重新标记[CMS-remark],开始并发清理 [CMS-concurrent-sweep-start] ,并发重置 [CMS-concurrent-reset-start] 。CMS回收器是一个关注停顿的垃圾收集器。如果要回收Perm(永久区),需要打开-XX:+CMSClassUnloadingEnabled开关。

4、G1回收器,分代分区回收器,实现了分代分区算法。可以使用-XX:+UseG1GC标记打开G1收集器开关。回收过程有4个阶段。1、新生代GC.2、并发标记周期.3、混合收集.4、如果需要,可能会进行Full GC。新生代GC的主要工作时回收eden区和survivor区,一旦eden区被占满,就会启动,清空eden区,并复制到survivor区,所以GC一次,eden区变0,survivor增大。日志标记[GC pause (young)]。并发标记阶段跟CMS类似,分初始标记,根区域扫描,并发标记,重新标记,独占清理,并发清理。并发标记周期并不清理大量垃圾,只是标记了一些含有大量垃圾的G区域,交给混合收集去清理。混合收集阶段会清理标记为G的区域,并把存活的对象移动到其他区域。日志标记[GC pause (mixed)]。必要时的Full GC,因为应用程序跟GC线程交替工作,难免出现内存不足,这种情况时会产生一次Full GC.目标最大停顿时间参数-XX:MaxGCPauseMillis,如果设的过短,新生代GC次数会增加,老年代在混合收集时,会减少收集的区域数量,从而增加了Full GC的可能性。并行回收时,工作线程数量参数-XX:ParallelGCThreads。-XX:InitiatingHeapOccupancyPercent参数指定堆使用率多少时,触发并发标记周期的执行,默认为45,即整个堆占用率达到45%时,执行并发标记周期。设置过大会导致并发周期迟迟不启动,引起Full GC的可能性增大。过小会使得并发周期非常频繁,大量GC线程抢占CPU,导致应用程序的性能下降。

5、TLAB,线程本地分配缓存,线程专属分配对象区间,避免多线程冲突。本身占用eden区的空间。开启为-XX:+UseTLAB(关闭为-UseTLAB)。使用-XX:TLABSize指定一个TLAB的大小,-XX:-ResizeTLAB禁用重新分配大小。当分配的对象大于TLAB剩余空间时,由-XX:TLABRefillWasteFraction来设置一个阈值,假如为n(默认值为64),表示为1/n的空间大小,当对象大小大于1/n时,分配在堆上,如果小于,则废弃该TLAB,新建TLAB来分配该对象。日志,desired_size为TLAB大小,slow allocs上一次新生代GC到现在为止慢分配(对象直接分配到堆上)次数,refill waste分配阈值,alloc当前线程的TLAB分配比例和使用评估量,refills表示该线程的TLAB空间被重新分配并填充的次数,waste表示空间的浪费比例。TLAB totals中,thrds相关线程总数,refills所有线程refills的总数,其后的max表示refills次数最多的线程的refills次数。

最后说一下new一个对象的过程,先栈上分配(一般在方法中)(不成功)->TLAB分配(不成功)->eden分配(或者老年代分配,根据对象大小)。

 

 

© 著作权归作者所有

共有 人打赏支持
算法之名
粉丝 12
博文 85
码字总数 48622
作品 0
广州
JVM 虚拟机(对象创建,类加载器,执行引擎等),

1.揭开 Java 对象创建的奥秘? 2.class 文件结构详解? 3.详解 Java 类的加载过程? > Java 对象创建,class 文件结构 Java对象模型 。Java对象保存在堆内存中。在内存中,一个Java对象包含三...

desaco
08/29
0
0
面试中关于Java虚拟机(jvm)的问题看这篇就够了

最近看书的过程中整理了一些面试题,面试题以及答案都在我的文章中有所提到,希望你能在以问题为导向的过程中掌握虚拟机的核心知识。面试毕竟是面试,核心知识我们还是要掌握的,加油~~~ 下面...

snailclimb
05/12
0
0
JVM系列一:Java虚拟机与操作系统结构比较

在了解jvm的结构之前,我们有必要先来了解一下操作系统的内存基本结构: 操作系统中的jvm ![在此输入图片描述][2] 为什么jvm的内存是分布在操作系统的堆中呢??因为操作系统的栈是操作系统管...

那位先生
2014/10/04
0
0
JVM内存结构 VS Java内存模型 VS Java对象模型

Java作为一种面向对象的,跨平台语言,其对象、内存等一直是比较难的知识点。而且很多概念的名称看起来又那么相似,很多人会傻傻分不清楚。比如本文我们要讨论的JVM内存结构、Java内存模型和...

Java架构
07/11
0
0
培训云计算学校,虚拟机基本结构讲解

我们要对JVM虚拟机的结构有一个感性的认知。毕竟我们不是编程人员,认知程度达不到那么深入。一个运行时的Java虚拟机实例的天职是:负责运行一个java程序。当启动一个Java程序时,一个虚拟机...

长沙千锋
05/17
0
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周四乱弹 —— 毒蛇当辣条

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @ 达尔文:分享花澤香菜/前野智昭/小野大輔/井上喜久子的单曲《ミッション! 健?康?第?イチ》 《ミッション! 健?康?第?イチ》- 花澤香菜/前野智...

小小编辑
今天
4
2
java -jar运行内存设置

java -Xms64m #JVM启动时的初始堆大小 -Xmx128m #最大堆大小 -Xmn64m #年轻代的大小,其余的空间是老年代 -XX:MaxMetaspaceSize=128m # -XX:CompressedClassSpaceSize=6...

李玉长
今天
1
0
Spring | 手把手教你SSM最优雅的整合方式

HEY 本节主要内容为:基于Spring从0到1搭建一个web工程,适合初学者,Java初级开发者。欢迎与我交流。 MODULE 新建一个Maven工程。 不论你是什么工具,选这个就可以了,然后next,直至finis...

冯文议
今天
1
0
RxJS的另外四种实现方式(四)——性能最高的库(续)

接上一篇RxJS的另外四种实现方式(三)——性能最高的库 上一篇文章我展示了这个最高性能库的实现方法。下面我介绍一下这个性能提升的秘密。 首先,为了弄清楚Most库究竟为何如此快,我必须借...

一个灰
今天
1
0
麒麟AI首席科学家现世

8月31日,华为发布了新一代顶级人工智能手机芯片麒麟980,成为全球首款7nm工艺手机芯片,AI方面也实现飞跃,支持人脸识别、物体识别、物体检测、图像分割、智能翻译等。 虽然如今人人都在热议...

问题终结者
昨天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部