我对JVM的理解

一、JVM简介

       JVM总体上是由类装载子系统(ClassLoader)、运行时数据区、执行引擎、内存回收这四个部分组成。
       其中我们最为关注的运行时数据区,也就是JVM的内存部分则是由方法区(Method Area)、JAVA堆(Heap)、虚拟机栈(Stack)、程序计数器、本地方法栈这几部分组成。

1.1、JDK1.7与JDK1.8的对比

       JDK 1.7 及以往的 JDK 版本中,Java 类信息、常量池、静态变量都存储在 Perm(永久代)里。类的元数据和静态变量在类加载的时候分配到 Perm,当类被卸载的时候垃圾收集器从 Perm 处理掉类的元数据和静态变量。当然常量池的东西也会在 Perm 垃圾收集的时候进行处理。
       JDK 1.8 的对 JVM 架构的改造将类元数据放到本地内存中,另外,将常量池和静态变量放到 Java 堆里。HotSopt VM 将会为类的元数据明确分配和释放本地内存。在这种架构下,类元信息就突破了原来 -XX:MaxPermSize 的限制,现在可以使用更多的本地内存。这样就从一定程度上解决了原来在运行时生成大量类的造成经常 Full GC 问题,如运行时使用反射、代理等。

1.2、JDK1.8 MetaSpace优势

       permSize:原来的jar包及你自己项目的class存放的内存空间,这部分空间是固定的,启动参数里面-permSize确定,如果你的jar包很多,经常会遇到permSize溢出,且每个项目都会占用自己的permGen空间
       改成metaSpaces,各个项目会共享同样的class内存空间,比如两个项目都用了fast-json开源包,在mentaSpaces里面只存一份class,提高内存利用率,且更利于垃圾回收

1.3、MetaSpace的理解

       Metaspace元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制
       -XX:MetaspaceSize,初始空间大小,达到该值就会触发垃圾收集进行类型卸载,同时GC会对该值进行调整:如果释放了大量的空间,就适当降低该值;如果释放了很少的空间,那么在不超过MaxMetaspaceSize时,适当提高该值。

二、GC简介

       GC(GarbageCollection)是垃圾回收机制,GC是JVM对内存(实际上就是对象)进行管理的方式。GC使得Java开发人员摆脱了繁琐的内存管理工作,让程序的开发更有效率。GC将负责回收所有"不可达"对象的内存空间。
Minor GC、Major GC和Full GC之间的区别?
       清理Eden区和 Survivor区叫Minor GC。
       清理Old区叫Major GC。
       清理整个堆空间—包括年轻代和老年代叫Full GC。

       HotSpot虚拟机:

2.1、回收策略

       在JVM中内存分配的基本粒度主要是对象、基本类型。而基本类型的使用主要是包括在对象中的局部变量,所以回收对象所占用的内存是JAVA垃圾回收的主要目标。
       如何判断对象是处于可回收状态的呢?
       在主流的JVM中是采用“可达性分析算法”来进行判断的。此算法的基本思路就是通过一系列的称为“GC Roots”的对象作为起始点,并从这些节点开始往下进行搜索,搜索走过的路径我们称之为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时,我们就称之为对象引用不可达,则证明这个对象是不可用的,就可以暂时判定这个对象为可回收对象。

       什么样的对象可以作为GC Roots对象呢?
       在JAVA中可以被作为GC Roots的对象主要是:虚拟机栈-栈帧中的本地变量表所引用的对象、方法区(<JDK1.8)中类静态属性所引用的对象/常量属性所引用的对象、本地方法栈中引用的对象。

2.2、回收算法

(1)、标记-清除(Mark-Sweep)算法

       这种算法的不足主要体现在效率和空间,从效率的角度讲,标记和清除两个过程的效率都不高;从空间的角度讲,标记清除后会产生大量不连续的内存碎片, 内存碎片太多可能会导致以后程序运行过程中在需要分配较大对象时,无法找到足够的连续内存而不得不提前触发一次垃圾收集动作。
(2)、复制(Copying)算法

       复制算法是为了解决效率问题而出现的,它将可用的内存分为两块,每次只用其中一块,当这一块内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已经使用过的内存空间一次性清理掉。
(3)、标记-整理(Mark-Compact)算法

       复制算法在对象存活率较高的场景下要进行大量的复制操作,效率很低。万一对象100%存活,那么需要有额外的空间进行分配担保。老年代都是不易被回收的对象,对象存活率高,因此一般不能直接选用复制算法。根据老年代的特点,有人提出了另外一种标记-整理算法,过程与标记-清除算法一样,不过不是直接对可回收对象进行清理,而是让所有存活对象都向一端移动,然后直接清理掉边界以外的内存。
(4)、分代收集算法

       现代商用虚拟机基本都采用分代收集算法来进行垃圾回收。这种算法没什么特别的,无非是上面内容的结合罢了,根据对象的生命周期的不同将内存划分为几块,然后根据各块的特点采用最适当的收集算法。大批对象死去、少量对象存活的(新生代),使用复制算法,复制成本低;对象存活率高、没有额外空间进行分配担保的(老年代),采用标记-清理算法或者标记-整理算法。

2.3、垃圾收集器

       不同虚拟机所提供的垃圾收集器可能会有很大差别,我们使用的是HotSpot,HotSpot这个虚拟机所包含的所有收集器如图:

       上图展示了7种作用于不同分代的收集器,如果两个收集器之间存在连线,那说明它们可以搭配使用。虚拟机所处的区域说明它是属于新生代收集器还是老年代收集器。
       明确一个观点:没有最好的垃圾收集器,更加没有万能的收集器,只能选择对具体应用最合适的收集器。这也是HotSpot为什么要实现这么多收集器的原因。

(1)、Serial收集器

       最基本、发展历史最久的收集器,这个收集器是一个采用复制算法的单线程的收集器,单线程一方面意味着它只会使用一个CPU或一条线程去完成垃圾收集工作,另一方面也意味着它进行垃圾收集时必须暂停其他线程的所有工作,直到它收集结束为止。后者意味着,在用户不可见的情况下要把用户正常工作的线程全部停掉,这对很多应用是难以接受的。不过实际上到目前为止,Serial收集器依然是虚拟机运行在Client模式下的默认新生代收集器,因为它简单而高效。用户桌面应用场景中,分配给虚拟机管理的内存一般来说不会很大,收集几十兆甚至一两百兆的新生代停顿时间在几十毫秒最多一百毫秒,只要不是频繁发生,这点停顿是完全可以接受的。
       说明:1. 需要STW(Stop The World),停顿时间长。2. 简单高效,对于单个CPU环境而言,Serial收集器由于没有线程交互开销,可以获取最高的单线程收集效率。
(2)、ParNew收集器

       ParNew收集器其实就是Serial收集器的多线程版本,除了使用多条线程进行垃圾收集外,其余行为和Serial收集器完全一样,包括使用的也是复制算法。ParNew收集器除了多线程以外和Serial收集器并没有太多创新的地方,但是它却是Server模式下的虚拟机首选的新生代收集器,其中有一个很重要的和性能无关的原因是,除了Serial收集器外,目前只有它能与CMS收集器配合工作(看图)。CMS收集器是一款几乎可以认为有划时代意义的垃圾收集器,因为它第一次实现了让垃圾收集线程与用户线程基本上同时工作。ParNew收集器在单CPU的环境中绝对不会有比Serial收集器更好的效果,甚至由于线程交互的开销,该收集器在两个CPU的环境中都不能百分之百保证可以超越Serial收集器。当然,随着可用CPU数量的增加,它对于GC时系统资源的有效利用还是很有好处的。它默认开启的收集线程数与CPU数量相同,在CPU数量非常多的情况下,可以使用-XX:ParallelGCThreads参数来限制垃圾收集的线程数。
(3)、Parallel Scavenge收集器
       Parallel Scavenge收集器也是一个新生代收集器,也是用复制算法的收集器,也是并行的多线程收集器,但是它的特点是它的关注点和其他收集器不同。介绍这个收集器主要还是介绍吞吐量的概念。CMS等收集器的关注点是尽可能缩短垃圾收集时用户线程的停顿时间,而Parallel Scavenge收集器的目标则是打到一个可控制的吞吐量。所谓吞吐量的意思就是CPU用于运行用户代码时间与CPU总消耗时间的比值,即吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间),虚拟机总运行100分钟,垃圾收集1分钟,那吞吐量就是99%。另外,Parallel Scavenge收集器是虚拟机运行在Server模式下的默认垃圾收集器。
       停顿时间短适合需要与用户交互的程序,良好的响应速度能提升用户体验;高吞吐量则可以高效率利用CPU时间,尽快完成运算任务,主要适合在后台运算而不需要太多交互的任务。
       虚拟机提供了-XX:MaxGCPauseMillis和-XX:GCTimeRatio两个参数来精确控制最大垃圾收集停顿时间和吞吐量大小。不过不要以为前者越小越好,GC停顿时间的缩短是以牺牲吞吐量和新生代空间换取的。由于与吞吐量关系密切,Parallel Scavenge收集器也被称为“吞吐量优先收集器”。Parallel Scavenge收集器有一个-XX:+UseAdaptiveSizePolicy参数,这是一个开关参数,这个参数打开之后,就不需要手动指定新生代大小、Eden区和Survivor参数等细节参数了,虚拟机会根据当前系统的运行情况手机性能监控信息,动态调整这些参数以提供最合适的停顿时间或者最大的吞吐量。如果对于垃圾收集器运作原理不太了解,以至于在优化比较困难的时候,使用Parallel Scavenge收集器配合自适应调节策略,把内存管理的调优任务交给虚拟机去完成将是一个不错的选择。
(4)、Serial Old收集器
       Serial收集器的老年代版本,同样是一个单线程收集器,使用“标记-整理算法”,这个收集器的主要意义也是在于给Client模式下的虚拟机使用。
(5)、Parallel Old收集器

       Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法。这个收集器在JDK 1.6之后的出现,“吞吐量优先收集器”终于有了比较名副其实的应用组合,在注重吞吐量以及CPU资源敏感的场合,都可以优先考虑Parallel Scavenge收集器+Parallel Old收集器的组合。运行过程如下图所示:
(6)、CMS收集器

       CMS(Conrrurent Mark Sweep)收集器是以获取最短回收停顿时间为目标的收集器。使用标记 - 清除算法,收集过程分为如下四步:
              1、初始标记,标记GCRoots能直接关联到的对象,时间很短。
              2、并发标记,进行GCRoots Tracing(可达性分析)过程,时间很长。
              3、重新标记,修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,时间较长。
              4、并发清除,回收内存空间,时间很长。
       其中,并发标记与并发清除两个阶段耗时最长,但是可以与用户线程并发执行。
       在G1之前的垃圾收集器,收集的范围都是整个新生代或者老年代,而G1不再是这样。使用G1收集器时,Java堆的内存布局与其他收集器有很大差别,它将整个Java堆划分为多个大小相等的独立区域(Region),虽然还保留有新生代和老年代的概念,但新生代和老年代不再是物理隔离的了,它们都是一部分(可以不连续)Region的集合。

2.4、GC日志分析

[GC [DefNew: 310K->194K(2368K), 0.0269163 secs] 310K->194K(7680K), 0.0269513 secs] [Times: user=0.00 sys=0.00, real=0.03 secs] 
[GC [DefNew: 2242K->0K(2368K), 0.0018814 secs] 2242K->2241K(7680K), 0.0019172 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (System) [Tenured: 2241K->193K(5312K), 0.0056517 secs] 4289K->193K(7680K), [Perm : 2950K->2950K(21248K)], 0.0057094 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Heapdef new generation   total 2432K, used 43K [0x00000000052a0000, 0x0000000005540000, 0x0000000006ea0000)eden space 2176K,   2% used [0x00000000052a0000, 0x00000000052aaeb8, 0x00000000054c0000)from space 256K,   0% used [0x00000000054c0000, 0x00000000054c0000, 0x0000000005500000)to   space 256K,   0% used [0x0000000005500000, 0x0000000005500000, 0x0000000005540000)tenured generation   total 5312K, used 193K [0x0000000006ea0000, 0x00000000073d0000, 0x000000000a6a0000)the space 5312K,   3% used [0x0000000006ea0000, 0x0000000006ed0730, 0x0000000006ed0800, 0x00000000073d0000)compacting perm gen  total 21248K, used 2982K [0x000000000a6a0000, 0x000000000bb60000, 0x000000000faa0000)the space 21248K,  14% used [0x000000000a6a0000, 0x000000000a989980, 0x000000000a989a00, 0x000000000bb60000)
No shared spaces configured.

(1)、日志的开头“GC”、“Full GC”表示这次垃圾收集的停顿类型,而不是用来区分新生代GC还是老年代GC的。如果有Full,则说明本次GC停止了其他所有工作线程(Stop-The-World)。看到Full GC的写法是“Full GC(System)”,这说明是调用System.gc()方法所触发的GC。
(2)、“GC”中接下来的“[DefNew”表示GC发生的区域,这里显示的区域名称与使用的GC收集器是密切相关的,例如上面样例所使用的Serial收集器中的新生代名为“Default New Generation”,所以显示的是“[DefNew”。如果是ParNew收集器,新生代名称就会变为“[ParNew”,意为“Parallel New Generation”。如果采用Parallel Scavenge收集器,那它配套的新生代称为“PSYoungGen”,老年代和永久代同理,名称也是由收集器决定的。
(3)、后面方括号内部的“310K->194K(2368K)”、“2242K->0K(2368K)”,指的是该区域已使用的容量->GC后该内存区域已使用的容量(该内存区总容量)。方括号外面的“310K->194K(7680K)”、“2242K->2241K(7680K)”则指的是GC前Java堆已使用的容量->GC后Java堆已使用的容量(Java堆总容量)。
(4)、再往后“0.0269163 secs”表示该内存区域GC所占用的时间,单位是秒。最后的“[Times: user=0.00 sys=0.00 real=0.03 secs]”则更具体了,user表示用户态消耗的CPU时间、内核态消耗的CPU时间、操作从开始到结束经过的墙钟时间。后面两个的区别是,墙钟时间包括各种非运算的等待消耗,比如等待磁盘I/O、等待线程阻塞,而CPU时间不包括这些耗时,但当系统有多CPU或者多核的话,多线程操作会叠加这些CPU时间,所以如果看到user或sys时间超过real时间是完全正常的。
(5)、“Heap”后面就列举出堆内存目前各个年代的区域的内存情况。

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/480997.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【LeetCode】4月4日打卡-Day20-接雨水

描述 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图&#xff0c;在这种情况下&#xff0c;可以接 6 个单位的雨水&#xff08;蓝色部分表示雨水&a…

算法与数据结构--空间复杂度O(1)遍历树

大家好~我叫「小鹿鹿鹿」&#xff0c;是本卖萌小屋的第二位签约作&#xff08;萌&#xff09;者&#xff08;货&#xff09;。和小夕一样现在在从事NLP相关工作&#xff0c;希望和大家分享NLP相关的、不限于NLP的各种小想法&#xff0c;新技术。这是我的第一篇试水文章&#xf…

PCA主成分分析学习总结

大概主成分分析&#xff08;Principal components analysis&#xff0c;以下简称PCA&#xff09;是最重要的降维方法之一。在数据压缩消除冗余和数据噪音消除等领域都有广泛的应用。一般我们提到降维最容易想到的算法就是PCA&#xff0c;下面我们就对PCA的原理做一个总结。首先…

技术动态 | 大规模中文概念图谱CN-Probase正式发布

本文转载自公众号知识工场。 历时多年的研发&#xff0c;复旦大学知识工场实验室正式推出大规模中文概念图谱——CN-Probase&#xff0c;用于帮助机器更好的理解人类语言。概念图谱中包含实体&#xff08;比如“刘德华”&#xff09;、概念&#xff08;比如“演员”&#xff09…

生产Docker应用重启排查经历

一、现象描述 近期&#xff0c;生产云平台监控发生Docker应用重启次数过多事故报警&#xff0c;经观察发现某些Docker应用不定期地出现重启现象&#xff0c;已严重影响服务正常提供 生产应用重启的判断条件&#xff1a;健康检查连续3次检查不通过 生产健康检查间隔时间设置为…

【Java】深入理解Java线程

1 相关概念 并发&#xff1a;两个或多个事件在同一时间段内发生【多个任务交替执行】 并行&#xff1a;两个或多个事件在同一时刻发生【多个任务同时执行】 进程&#xff1a;进入内存的程序 内存&#xff1a;所有应用程序都要进入到内存中执行 临时存储RAM 线程&#xff1a;进…

机器学习——多元线性回归分析(multiple regression)及应用

版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 https://blog.csdn.net/loveliuzz/article/details/78006493 </div><link rel"stylesheet" href"https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_vi…

肖仰华 | 知识图谱研究的回顾与展望

本文转载自公众号知识工场。 本文整理自2017年10月19日肖仰华教授在知识图谱前沿技术课程&#xff08;华东师范大学站&#xff09;所做的报告&#xff0c;报告的题目为《知识图谱研究的回顾与展望》。 大家好&#xff0c;很多人在对知识图谱的研究或者落地方面都表现出了极大的…

Java应用性能调优工具介绍及实践

一、背景 &#xff08;1&#xff09;、随着微服务架构的逐渐推广&#xff0c;一个大型的单个应用程序被拆分为数个微服务系统&#xff0c;这为研发人员的本地调试跟踪带来困难 &#xff08;2&#xff09;、在微服务架构中&#xff0c;由于业务的复杂性&#xff0c;常常一个业务…

Google、MS和BAT教给我的面试真谛

大家好呀&#xff0c;我是「小鹿鹿鹿」&#xff0c;我又来啦&#xff5e;&#xff5e;趁大家还有依稀印象赶紧乘热打铁&#xff5e;&#xff5e;这次聊一聊关于面试的一些小想法&#xff0c;希望和大家交流交流&#xff5e;&#xff5e;虽然资历尚浅&#xff0c;但是也面过不少…

AAAI 2018 论文 | 蚂蚁金服公开最新基于笔画的中文词向量算法

导读&#xff1a;词向量算法是自然语言处理领域的基础算法&#xff0c;在序列标注、问答系统和机器翻译等诸多任务中都发挥了重要作用。词向量算法最早由谷歌在2013年提出的word2vec&#xff0c;在接下来的几年里&#xff0c;该算法也经历不断的改进&#xff0c;但大多是仅适用…

甲子光年 | 为什么知识图谱终于火了?

本文转载自公众号甲子光年。如果知识是人类进步的阶梯&#xff0c;知识图谱就是AI进步的阶梯。作者&#xff5c;金丝猴编辑&#xff5c;甲小姐设计&#xff5c;孙佳栋微信&#xff5c;甲子光年 (ID:jazzyear)“知识图谱”相较于AI其他分支&#xff0c;似乎是最后一个热起来的赛…

Java多线程并发编程

一、线程池 1.1、什么是线程池 线程池是一种多线程的处理方式&#xff0c;利用已有线程对象继续服务新的任务&#xff08;按照一定的执行策略&#xff09;&#xff0c;而不是频繁地创建销毁线程对象&#xff0c;由此提高服务的吞吐能力&#xff0c;减少CPU的闲置时间。具体组成…

Step-by-step to Transformer:深入解析工作原理(以Pytorch机器翻译为例)

大家好&#xff0c;我是青青山螺应如是&#xff0c;大家可以叫我青青&#xff0c;工作之余是一名独立摄影师。喜欢美食、旅行、看展&#xff0c;偶尔整理下NLP学习笔记&#xff0c;不管技术文还是生活随感&#xff0c;都会分享本人摄影作品&#xff0c;希望文艺的技术青年能够喜…

知识图谱与智能问答基础理解

什么是知识图谱&#xff1f; 知识图谱本质上是语义网络&#xff0c;是一种基于图的数据结构&#xff0c;由节点(Point)和边(Edge)组成。在知识图谱里&#xff0c;每个节点表示现实世界中存在的“实体”&#xff0c;每条边为实体与实体之间的“关系”。知识图谱是关系的最有效的…

鲍捷 | 知识图谱从 0 级到 10 级简化版

本文转载自公众号&#xff1a;文因学堂。文因学以前写过几个进阶指南&#xff0c;可能都太难&#xff0c;不接地气。这里重新写一个更实事求是、更便于工程落地的版本0级&#xff1a;掌握正则表达式、SQL、JSON和一门支持if-then-else的高级语言 —— 是的&#xff0c;这些不是…

Java并发优化思路

一、并发优化 1.1、Java高并发包所采用的几个机制 &#xff08;1&#xff09;、CAS&#xff08;乐观操作&#xff09; jdk5以前采用synchronized&#xff0c;对共享区域进行同步操作&#xff0c;synchronized是重的操作&#xff0c;在高并发情况下&#xff0c;会引起线…

他与她,一个两年前的故事

“ 有没有那个Ta&#xff0c;值得你一生去守护”1她能力出众&#xff0c;业务能力无人能出其左右&#xff1b;他资质平庸&#xff0c;扮演一个很不起眼的角色&#xff1b;她国色天香&#xff0c;是整个公司上上下下关注的焦点&#xff1b;他其貌不扬&#xff0c;甚至很多人根本…

科普 | 知识图谱相关的名词解释

知识图谱&#xff08;Knowledge Graph&#xff09;是谷歌于2012年提出。企业通常出于商业目的去设计新的概念和名词。但每一个概念的提出都有其历史渊源和本质内涵。下面列举了知识图谱相关的几个概念&#xff0c;并简要阐明了它们与知识图谱的关系和区别。Knowledge Base&…

搜索引擎核心技术与算法 —— 倒排索引初体验

今天开启一个新篇章——智能搜索与NLP。本篇章将由羸弱菜鸡小Q和大家一同学习与智能搜索相关的知识和技术&#xff0c;希望能和大家一同学习与进步&#xff0c;冲鸭&#xff01;&#xff01;这里首先区分两个概念&#xff1a;搜索和检索检索&#xff1a;数据库时代的概念&#…