JVM原理探究及调优方法论

1 此文目的

本文不准备从盘古开天地开始讲述JVM的种种,相关的文章网上太多了,大多也无非转来转去,连图都差不多。笔者只整理个提纲挈领的学习路线指南,并对自己学习过程中遇到的坑和容易混淆和忽视的地方作个总结。

2 JVM内存模型

2.1 内存模型

内存区域划分有多个维度,相同区域在不同维度的名称并不一样。如下图所示

可以看到,survivor区被划分为了survivor0和survivor1两个区域,但是在讲MinorGC的原理时,我们又会说survvior to和survivor from两个区域。事实上,survivor0和survivor1是物理维度的划分,而survivor to和survivor from是逻辑维度的划分,在MinorGC的过程中,survivor0和survivor1交替担当to区和from区。 来仔细解释一下MinorGC的过程: 在GC开始的时候,对象只会存在于Eden区和名为“From”的Survivor区,Survivor区“To”是空的。紧接着进行GC,Eden区中所有存活的对象都会被复制到“To”,而在“From”区中,仍存活的对象会根据他们的年龄值来决定去向。年龄达到一定值(年龄阈值,可以通过-XX:MaxTenuringThreshold来设置)的对象会被移动到年老代中,没有达到阈值的对象会被复制到“To”区域。经过这次GC后,Eden区和From区已经被清空。这个时候,“From”和“To”会交换他们的角色,也就是新的“To”就是上次GC前的“From”,新的“From”就是上次GC前的“To”。不管怎样,都会保证名为To的Survivor区域是空的。Minor GC会一直重复这样的过程,直到“To”区被填满,“To”区被填满之后,会将所有对象移动到年老代中。大致如下图所示:

2.2 方法区和永久代

这两个概念,很多时候都被当做是同一个概念。实际上,“方法区”是java虚拟机规范中对存放类信息,字段,方法,常量,静态变量,接口和常量池的内存区域的定义,而“永久代”则是HotSpot VM在1.8版本以前对于方法区的具体实现。由于java虚拟机规范并没有对方法区的具体实现作限制,所以HotSpot VM和JRocket VM对于方法区的实现都是不一样的,JRocket中就没有永久代的概念。而在1.8及1.8以后的版本中,HotSpot VM用"元空间"--metaspace来代替永久代,实现方法区。 这个变化带来的就是VM参数的变化,所有的PermGen都被替换成了MetaSpace。并且metaSpace不再使用堆内存,而是使用系统内存。但是该发生的OOM一样会发生。原因也基本都是加载到内存中的 class 数量太多或者体积太大。

3.GC

3.1 GC算法

GC算法和GC收集器也是两个维度的概念。 GC算法包括清除算法(也叫标记清除算法),复制算法,标记-整理算法。 不同垃圾收集器针对不同的内存区域,采用不同的GC算法。 具体介绍,网上相关资料很多,可以参考这篇文章:blog.csdn.net/xiaoping091…

3.2 垃圾收集器

垃圾收集器经历了从串行收集器到并行收集器,再到并发收集器的进化过程。这三者的区别如下图所示

串行和并行的区别比较容易理解,而CMS垃圾收集器的原理要注意的是,虽然它是并发收集器,但它的GC线程并不是完完全全地与应用的进程并发进行,它只是通过用两次短暂停来代替并行GC的一次长暂停,以期达到减少应用线程暂停的目的,详见CMS垃圾回收机制

不同版本默认使用的垃圾收集器以及支持开发者定制的垃圾收集器都是不一样的 jdk1.7 默认垃圾收集器Parallel Scavenge(新生代)+Parallel Old(老年代) jdk1.8 默认垃圾收集器Parallel Scavenge(新生代)+Parallel Old(老年代) jdk1.9 默认垃圾收集器G1 与此同时,通过设置JVM参数也可以自己选择垃圾收集器。如要开启G1垃圾回收器,可以用-XX:+UseG1GC,支持G1垃圾回收器的JDK最低版本为JDK 7u4。在用户自己选择垃圾收集器的时候,要注意JDK版本的问题。 笔者用表格的形式列出了新生代和老年代的GC收集器的常见搭配方案:

3.3 Full GC触发条件

频繁FullGC导致的stop the world的现象,会大大影响系统的稳定性。尽管一代又一代的垃圾收集器的优化,使得stop the world的时间越来越短,但是在大型应用中,还是避之不及。 出发FullGC的情况有以下几种:

  1. System.gc()方法的调用
  2. 老年代不足
  3. 方法区不足
  4. concurrent mode failure concurrent mode failure是在执行CMS GC的过程中同时有对象要放入老年代,而此时老年代空间不足造成的(有时候“空间 不足”是CMS GC时当前的浮动垃圾过多导致暂时性的空间不足触发Full GC)。
  5. promotion failed minor gc时年轻代的存活区空间不足而晋升老年代,老年代又空间不足而触发full gc
  6. 统计得到的Minor GC晋升到旧生代的平均大小大于老年代的剩余空间 当准备要触发一次young GC时,如果发现统计数据说之前young GC的平均晋升大小比目前old gen剩余的空间大,则不会触发young GC而是转为触发full GC(因为HotSpot VM的GC里,除了CMS的concurrent collection之外,其它能收集old gen的GC都会同时收集整个GC堆,包括young gen,所以不需要事先触发一次单独的young GC)。

3.3.1 OOM的类型

通常情况下,JVM的GC机制能保证应用的正常运行,导致系统频繁FullGC的原因百分之九十都是内存溢出(OOM)。OOM分为以下几类:

  1. Java.lang.OutOfMemeoryError:Java heap space 堆空间的内存溢出,可能的原因是某个可达性分析认为不能被回收的对象随着时间推移变得越来越大,例如某个static类型的map对象,被不停地塞入键值对,也可能是大循环或者死循环不断创建对象,而对象分配内存的速度超过了GC清理内存的速度。
  2. Java.lang.OutOfMemeoryError:GC overhead limit exceeded 这种OOM异常是Hotspot VM 1.6定义的一个策略,通过统计GC时间来预测是否要OOM了,提前抛出异常,防止OOM发生。Sun 官方对此的定义是:“并行/并发回收器在GC回收时间过长时会抛出OutOfMemroyError。过长的定义是,超过98%的时间用来做GC并且回收了不到2%的堆内存。用来避免内存过小造成应用不能正常工作。” 那么为什么会出现这种GC效率低下的现象呢?通常是因为老年代内存占有过多导致的频繁GC,这种情况下,可以增加-verbose:gc -XX:+PrintGCDetails来分析具体原因,也可以加-XX:+HeapDumpOnOutOfMemoryError,这样OOM时会自动做Heap Dump,第二种方法适用于所有OOM异常的排查。
  3. Java.lang.OutOfMemoryError: PermGen space(JAVA8引入了Metaspace区域)方法区内存溢出,通常是因为加载的类过多,可以先排除程序问题导致的重复类加载,或者加大方法区内存的分配
  4. Java.lang.OutOfMemoryError: unable to create new native thread 产生这种异常的原因是由于系统在不停地创建大量的线程,且不进行释放。

4. JVM调优

4.1 调优参数

正确设置JVM参数,可以尽可能多地避免系统资源浪费,尽可能详细地掌握系统运行情况,并且对可能出现的问题防患于未然。

Xms:堆初始空间

Xmx:堆最大空间

Xmn:年轻代大小

XX:MaxNewSize 新生代最大空间 建议设置为整个堆的1/3到1/4

XX:NewSize

XX:MaxTenuringThreshold survivor中到老年代中的年龄阈值

Xss:每个线程的栈大小

java -XX:+PrintCommandLineFlags -version 得到JDK建议的内存分配大小

tomcat设置catalina.sh:

export JAVA_OPTS="-server –Xms1024m -Xmx1024m -XX:+UseParallelOldGC -verbose:gc -Xloggc:../logs/gc.log

-XX:+PrintGCDetails -XX:+PrintGCTimeStamps"

-XX:+PrintCommandLineFlagsjvm参数可查看默认设置收集器类型

-XX:+PrintGCDetails亦可通过打印的GC日志的新生代、老年代名称判断

4.2 JVM监控

  • 1.本机环境下,推荐一款idea上的插件VisualVM Launcher,实际就是联动了JDK开发包中自带的jvisualvm.exe监控软件。也可以设置远程监控。具体使用方法,可以参考这篇文章https://blog.csdn.net/wngpenghao/article/details/82884874IDEA Java性能分析插件VisualVM Launcher 配置(JAVA VisualVM 与Jconsole配置相同)

  • 2.Linux的相关命令: jstat命令可以对jvm从各维度进行统计,详细使用参考jstat命令查看jvm的GC情况

  • 3.VM参数设置时,指定打印出gc日志 -Xloggc:../logs/gc.log -XX:+PrintGCDetails -XX:+PrintGCTimeStamps 详细的参数设置以及gc日志该如何阅读,可以参考java之GC日志该怎么看

4.3 JVM异常排查

  1. 保存dump 当使用监控软件或者命令查看发现JVM异常时,应第一时间保存下dump现场。 命令是jmap -dump:format=b,file=文件名[pid] pid是服务进程

如果是使用jvisualvm就更方便了,直接点击如图所示的按钮即可:

2. 分析dump eclipse有一款插件叫做Memory Analyzer(MAT),但是目前idea并没有这款插件 此外,jhat是sun 1.6及以上版本中自带的一个用于分析JVM 堆DUMP 文件的工具,基于此工具可分析JVM HEAP 中对象的内存占用情况 jhat -J-Xmx1024M [file] 执行后等待console 中输入start HTTP server on port 7000 即可使用浏览器访问 IP:7000 可以特别关心下图标出的这个选项 这对于排查堆内存溢出非常有效

4.4 实战例子

由于实际工作中,能接触到JVM机会的机会并不多,所以笔者整理了一些经典实例

Metaspace溢出排查过程

分享一次 Java 内存泄漏的排查

一次生产的 JVM 优化案例

JVM成长之路,记录一次内存溢出导致频繁FGC的问题排查及解决

非常详细的jvm调优实例,性能瓶颈定位

转载于:https://juejin.im/post/5cf500c7f265da1b855c40c3

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

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

相关文章

超方便、最简单版本:java 邮件发送 (半分钟写完代码)

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. jar 和 邮箱设置 <!--邮件--><dependency><groupId>org.simplejavamail</groupId><artifactId>simpl…

OpenCL(CUDA5.0) + Visual Studio 2010 环境配置

1.安装步骤 1&#xff09;安装CUDA5.0本文默认的安装目录为&#xff1a;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA \v5.0 CUDA SDK的默认安装目录为&#xff1a;C:\ProgramData\NVIDIA Corporation\CUDA Samples\v5.0 其他路径请自行修改路径&#xff01;2&#xff…

Q-Dir

Q-dir&#xff0c;可以分界面&#xff0c;分文件夹&#xff0c;快捷选择等优势&#xff0c;非常好用的工具&#xff0c;可以替代微软的File Explorer。 官网&#xff1a;https://www.softwareok.com/?seiteFreeware/Q-Dir转载于:https://www.cnblogs.com/JTCLASSROOM/p/109719…

一行代码 实现集合去重

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 代码写法&#xff1a;&#xff08;这是针对元素为基本数据类型的集合&#xff09; 针对引用类型元素去重&#xff0c;可根据元素内多…

《Mali OpenCL SDK v1.1.0》教程样例之一“Hello World”

1、算法简述 实现矩阵相加&#xff1a;Cn An Bn。这个例子虽然很简单&#xff0c;但是由于矩阵元素之间相互独立&#xff0c;每个元素可以非常容易地进行并行计算&#xff0c;可以非常理想地在OpenCL中实现。 2. C/C实现 [cpp] view plaincopyprint?/* * This confidential…

PHP商城数据库安全事务处理方法

现在是一个电商时代&#xff0c;做电商的首先得有一个商城&#xff0c;所以商城的安全也是不容忽视的&#xff0c;一个数据安全的商城离不开数据库的事务处理&#xff0c;商城在资金、商品、下单、结账等重要步骤加上事务控制这是不一定不可少的&#xff0c;像市场上的一些开源…

职业规划之ABZ,未雨绸缪35岁危机

35岁的中年人正面临着上有老下有小&#xff0c;房贷车贷等生活压力&#xff0c;然而在职场上又面临被裁员或在招聘中年龄超限的尴尬局面。那么&#xff0c;我们如何应对此危机呢&#xff1f;ABZ理论为我们打开了一扇天窗。 ABZ理论由著名的创业者投资人&#xff0c;LinkedIn和P…

集合去重 (集合元素为引用类型)--- java 8 新特性 --- 根据元素单属性、多属性实现去重

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 代码写法&#xff1a; &#xff08;要求 JDK 1.8 或 1.8 以上&#xff09; package gentle.entity;import lombok.Data; /**** auth…

Django--Forms组件使用

Forms组件的使用 在html表单验证中&#xff0c;需要通过各种信息的验证&#xff0c;比如注册界面的姓名、密码、邮箱、电话等的验证&#xff0c;是否符合定义好的规则&#xff0c;不可能每次都要取出对应的字段一一判断&#xff0c;django内置了Forms组件&#xff0c;可以方便的…

yii2关联表

asArray()这个方法很好用&#xff0c;返回数组是1版本想要的形式&#xff0c;这种方式有种tp框架的感觉转载于:https://www.cnblogs.com/peipeiyu/p/10974487.html

详细程序注解学OpenCL一 环境配置和入门程序

本专栏是通过注解程序的方法学习OpenCL&#xff0c;我觉得一个一个地去抠原理也不是办法&#xff0c;干脆直接学习程序&#xff0c;然后把相关原理都直接注解到程序语句当中。 原创地址&#xff1a;http://blog.csdn.net/kenden23/article/details/14101657 一开始要配置好环境…

解决 IDEA 在 commit 代码时 git 日志乱码 (提交时填写的中文说明乱码)

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1.问题描述&#xff1a; idea 开发代码中的 中文正常&#xff0c;但提交到码云时填写的提交日志是乱码。 提交到码云后是这样的&#…

Box 类

public class Box extends JComponent implements Accessible使用 BoxLayout 对象作为其布局管理器的一个轻量级容器。Box 提供几个对使用 BoxLayout 的容器&#xff08;甚至非 Box 容器&#xff09;有用的类方法。 Box 类可以创建几种影响布局的不可见组件&#xff1a;glue、s…

神奇的pdfkit工具——将字符串保存为pdf文件

神奇的pdfkit工具——将字符串保存为pdf文件 1、安装工具包 pip install pdfkit 2、上干货 import pdfkitdef create_pdf(str_data, to_file):将字符串生成pdf文件 # &#xff08;需下载wkhtmltox&#xff09;将程序路径传入config对象config pdfkit.configuration(wkhtmltopd…

OpenCL结构

原标题&#xff1a;从零开始学习OpenCL开发&#xff08;一&#xff09;架构 1 异构计算、GPGPU与OpenCL OpenCL是当前一个通用的由很多公司和组织共同发起的多CPU\GPU\其他芯片 异构计算&#xff08;heterogeneous&#xff09;的标准&#xff0c;它是跨平台的。旨在充分利用GP…

docker-compose 使用小例

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 只是一个很简单的小例。 1. 原本有的容器 2. docker-compose.yml 写法&#xff1a; gentle 处可以任意写&#xff0c;gentle 是我的项…

2019.6.20

今日内容 MongoDB可视化工具 一、Scrapy爬虫框架 二、微信机器人 转载于:https://www.cnblogs.com/jrc123/p/11062606.html

PCL点云 Lebel:Research

https://blog.csdn.net/wokaowokaowokao12345/article/details/73741957 https://blog.csdn.net/u010696366/article/category/3108337转载于:https://www.cnblogs.com/radiumlrb/p/10986918.html

AMD GPU+VS2010的OpenCL配置

安装开发环境可以参照DE4-530的OpenCL开发环境搭建&#xff08;最终版&#xff09;&#xff0c;这篇文章的大部分内容转载自&#xff1a;http://www.verydemo.com/demo_c92_i226325.html AMD的Heterogeneous Computing有很多AMD的OpenCL资料&#xff0c;包括各种分析工具&#…

ABP开发框架前后端开发系列---(9)ABP框架的权限控制管理

在前面两篇随笔《ABP开发框架前后端开发系列---&#xff08;7&#xff09;系统审计日志和登录日志的管理》和《ABP开发框架前后端开发系列---&#xff08;8&#xff09;ABP框架之Winform界面的开发过程》开始介绍了权限管理的内容&#xff0c;其中只是列出了内部的权限系统的审…