文档章节

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

算法之名
 算法之名
发布于 06/24 08:03
字数 2714
阅读 49
收藏 8
点赞 0
评论 0

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分配(或者老年代分配,根据对象大小)。

 

 

© 著作权归作者所有

共有 人打赏支持
算法之名
粉丝 6
博文 66
码字总数 34582
作品 0
广州
JVM系列一:Java虚拟机与操作系统结构比较

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

那位先生
2014/10/04
0
0
面试中关于Java虚拟机(jvm)的问题看这篇就够了

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

snailclimb
05/12
0
0
JVM内存结构 VS Java内存模型 VS Java对象模型

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

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

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

长沙千锋
05/17
0
0
《深入理解Java虚拟机》之Java虚拟机内存结构(1)

这个是很重要的一个基础认识。 java虚拟机规范规定的java虚拟机内存其实就是java虚拟机运行时数据区,其架构如下: 其中方法区和堆是由所有线程共享的数据区。 Java虚拟机栈,本地方法栈和程...

lixiyuan
2014/04/10
0
1
《Java从小白到大牛精简版》之第1章 开篇综述

Java诞生到现在已经有20多年了,但是Java仍然是非常热门的编程语言之一,很多平台中使用Java开发。表1-1所示的是TIOBE社区发布的2016年5月和2017年5月的编程语言排行榜,可见Java语言的热度,...

tony关东升
06/26
0
0
我所理解的JVM(一):内存结构

Java Memory Model 简称JMM,译为Java内存模型,属于Java虚拟机规范的一部分 java虚拟机运行时的内存区域分为:程序计数器、虚机机栈、本地方法栈、堆、方法区5部分。其中前3部分是线程独享的...

康斯但丁
2017/10/28
0
0
深入探索Java工作原理:JVM,内存回收及其他

Java语言引入了Java虚拟机,具有跨平台运行的功能,能够很好地适应各种Web应用。同时,为了提高Java语言的性能和健壮性,还引入了如垃圾回收机制等新功能,通过这些改进让Java具有其独特的工...

AlphaJay
2010/04/14
0
0
JVM 内存初学 (堆(heap)、栈(stack)和方法区(method) )

这两天看了一下深入浅出JVM这本书,推荐给高级的java程序员去看,对你了解JAVA的底层和运行机制有 比较大的帮助。 废话不想讲了.入主题: 先了解具体的概念: JAVA的JVM的内存可分为3个区:堆...

-蒋全忠-
2015/05/15
0
0
[Java学习探讨]为什么学Java虚拟机的Java程序员更值钱?

[Java学习探讨]为什么学Java虚拟机的Java程序员更值钱? 曾经的我经常害怕处理与JVM相关的异常,对JVM的配置参数也一无所知,那时候我天真地认为,JVM的出现本身就是想让程序员屏蔽实现细节,...

原创小博客
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

虚拟机怎么安装vmware tools

https://blog.csdn.net/tjcwt2011/article/details/72638977

AndyZhouX
8分钟前
0
0
There is no session with id[xxx]

参考网页 https://blog.csdn.net/caimengyuan/article/details/52526765 报错 2018-07-19 23:04:35,330 [http-nio-1008-exec-8] DEBUG [org.apache.shiro.web.servlet.SimpleCookie] - Found......

karma123
8分钟前
0
0
vue-router懒加载

1. vue-router懒加载定义 当路由被访问的时候才加载对应组件 2. vue-router懒加载作用 当构建的项目比较大的时候,懒加载可以分割代码块,提高页面的初始加载效率。 ###3. vue-router懒加载实...

不负好时光
16分钟前
0
0
庆祝法国队夺冠:用Python放一场烟花秀

天天敲代码的朋友,有没有想过代码也可以变得很酷炫又浪漫?今天就教大家用Python模拟出绽放的烟花庆祝昨晚法国队夺冠,工作之余也可以随时让程序为自己放一场烟花秀。 这个有趣的小项目并不...

猫咪编程
17分钟前
0
0
SpringBoot | 第七章:过滤器、监听器、拦截器

前言 在实际开发过程中,经常会碰见一些比如系统启动初始化信息、统计在线人数、在线用户数、过滤敏高词汇、访问权限控制(URL级别)等业务需求。这些对于业务来说一般上是无关的,业务方是无需...

oKong
31分钟前
4
0
存储结构分四类:顺序存储、链接存储、索引存储 和 散列存储

存储结构分四类:顺序存储、链接存储、索引存储 和 散列存储 存储结构分四类:顺序存储、链接存储、索引存储 和 散列存储。 顺序结构和链接结构适用在内存结构中。 顺序表每个单元都是按物理...

DannyCoder
42分钟前
1
0
Firefox 61已经为Ubuntu 提供支持

最新和最好的Mozilla Firefox 61 “Quantum”网络浏览器已经为Ubuntu Linux操作系统的用户提供了支持,现在可以通过官方软件库进行更新。 Mozilla于2018年6月26日发布了Firefox 61版本,该版...

六库科技
今天
0
0
Win10升级后执行系统封装(Sysprep)报错

开始封装 一年多以前开始给公司封装Win10系统,便于统一给公司电脑初始化携带各种软件的系统,致力于装完既可以开发的状态。那时候最新的版本是Win10 1703版本,自然就以他为母盘,然后结合V...

lyunweb
今天
40
0
php 性能优化

#什么情况下会遇到性能问题 PHP 语法使用的不恰当

to_be_better
今天
0
0
Jenkins 构建触发器操作详解

前言 跑自动化用例每次用手工点击jenkins出发自动化用例太麻烦了,我们希望能每天固定时间跑,这样就不用管了,坐等收测试报告结果就行。 一、定时构建语法 * * * * * (五颗星,中间用空格隔...

覃光林
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部