关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » JAVA »一次 JVM 调优的笔记

    一次 JVM 调优的笔记

    2015-10-12 00:00:00 出处:ImportNew
    分享

    1. JVM Tuning基础知识

    1.1 Java堆结构

    Java堆可以处于物理上不连续的内存空间上,只要逻辑上是连续的即可。Java堆就是各种对象分配和保存的内存空间,线程间共享。Java堆分为Eden区,Survivor区,tenured区和Permanent区,如下图所示。

    Java堆的分配原则如下:

    Java堆分布如下图所示,新的类的实例大部分在Eden(之所以用Eden这个词也就是表示初创起始的意思)区分配。 Eden区满的时候,或者需要GC时,依然存活的对象将被复制到Survivor区,一共有两个survivor区,当一个survivor区满时,依然存活的对象将被复制到另一个survivor区。 当survivor区全满时,从第一个survivor区复制过来的,且此时还存活的对象将被复制到Tenured Generation(年老代) Perm Generation用于存放静态文件,持久代大小可以通过MaxPermSize进行设置。

    一次JVM调优的笔记

    Perm Generation是JVM的驻留内存,用于存放JDK自身携带的CLASS,Interface的元数据等。被装载进此区域的数据是不会被垃圾回收器GC回收掉的,关闭JVM时,释放此区域所控制的内存。

    Java对象的声明周期在堆中从Young到Tenured,这个期间从Eden诞生到Tenured死亡。当EDEN区不够用时,将触发 minor gc,GC会对EDEN区进行垃圾回收,将不再使用的对象进行销毁,同时如果发现对象还被其他对象引用,则将对象移动到survivor区,后面依此类 推,当Tenured区发生GC时,称为major gc,由于java中大部分对象的生命周期都很短,所以GC一般发生在Eden区,因此minor gc发生的频率比major gc要高很多。如果最后整个堆空间都满了,则会爆出异常JVM对空间溢出:java.lang.OutOfMemoryError: java heap space。

    1.2 JVM GC算法枚举

    Mark-sweep算法

    即标记回收算法,将需要回收的对象标记,再统一回收。这种算法适合Perm代的对象,以为Perm代的存储空间比较大,需要回收的又不多。

    Copying算法

    即复制算法,直接拷贝。适合Eden区的对象向survivor区拷贝,因为Eden区的对象大部分都需要GC,而且Eden区的容量小。

    Mark-compact算法

    即标记整理算法,与标记清除算法不同,标记整理算法避免了内存碎片问题,它将所有存活的对象向内存的一端移动,“整理”完成后,一端是存活的对象一端是可回收内存,然后直接清除可回收内存。

    1.3 GC收集器

    Serial收集器

    最基本、最古老的收集器。这是一个单线程收集器,GC过程中,应用会被停掉,即stop-the-world。

    Parnew收集器

    实现代码与serial差不多,不同的是这是一个多线程回收器。

    Paralled scavenge收集器

    Paralled scavenger收集器是一个新生代回收器,使用复制算法,也是一个多线程并行收集器。parallel scavenge收集器专注于提高吞吐量,吞吐量定义为:

    吞吐量 = 用户程序执行时间/(用户程序执行时间 + 垃圾回收时间)

    Serial old收集器

    Serial old是Serial收集器的老年代版本。

    Parallel old收集器

    Parallel Scavenge收集器的老年代版本。使用标记-整理算法。

    CMS(concurrent mark sweep)收集器:并发标记清除收集器,以最短停顿时间为目标的收集器。采用标记—清除算法实现。

    2.VisualVM1实际监控JVM状态

    2.1 常用调优参数列表

    主要需要熟悉的是总存储空间大小,各个区的比例设置,针对不同的区设定不同的回收器和回收算法。在默认情况下有些选项是不打开的,因此需要手动配置,并且根据自己应用的情况选择适当的参数。

    参数 描述
    –XX:+UseSerialGC 使用串行GC收集器
    –XX:+UseParallelGC 使用并行GC收集器
    –XX:+UseParallelOldGC 使用parallel old收集器
    –XX:+UseConcMarkSweepGC 使用CMS收集器
    -Xms 初始状态堆大小
    -Xmx 堆的最大大小
    -XX:MaxPermSize=n 设置Permanent区的大小
    -XX:NewSize=n 设置Young generation大小
    -XX:NewRatio=n 设置年轻代和年老代的比值

    2.2 查看并分析GC日志

    对于应用程序,在eclipse中可以通过工程属性增加VM属性,将GC输出保存为日志文件。

    一次JVM调优的笔记

    GC输出选项:

      -XX:+PrintGC 输出GC日志
      -XX:+PrintGCDetails 输出GC的详细日志
      -XX:+PrintGCTimeStamps 输出GC的时间戳(以基准时间的形式)
      -XX:+PrintGCDateStamps 输出GC的时间戳(以日期的形式,如 2013-05-04T21:53:59.234+0800)
      -XX:+PrintHeapAtGC 在进行GC的前后打印出堆的信息
      -Xloggc:../logs/gc.log 日志文件的输出路径

    日志输出形式:

    Java HotSpot(TM) Client VM (25.45-b02) for windows-x86 JRE (1.8.0_45-b14), built on Apr 10 2015 10:46:40 by "java_re" with MS VC++ 10.0 (VS2010)
    Memory: 4k page, physical 2074576k(402044k free), swap 4149152k(1441572k free)
    CommandLine flags: -XX:InitialHeapSize=16777216 -XX:MaxHeapSize=268435456 -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:-UseLargePagesIndividualAllocation 
    Heap
     def new generation   total 4928K, used 885K [0x04600000, 0x04b50000, 0x09b50000)
      eden space 4416K,  20% used [0x04600000, 0x046dd5f0, 0x04a50000)
      from space 512K,   0% used [0x04a50000, 0x04a50000, 0x04ad0000)
      to   space 512K,   0% used [0x04ad0000, 0x04ad0000, 0x04b50000)
     tenured generation   total 10944K, used 0K [0x09b50000, 0x0a600000, 0x14600000)
       the space 10944K,   0% used [0x09b50000, 0x09b50000, 0x09b50200, 0x0a600000)
     Metaspace       used 98K, capacity 2242K, committed 2368K, reserved 4480K

    编写了一个简单的递归计算Fibbonaccy数列的程序,并在最后增加了一句System.gc()强制进行Full GC,得到的GC日志如下,回收后Eden区使用量为0。当服务器型的应用运行起来时,免不了会有多次GC,通过GC日志可以比较容易定位性能问题,比如 full gc次数过多等。

    {Heap before GC invocations=0 (full 0):
     def new generation   total 4928K, used 1522K [0x04600000, 0x04b50000, 0x09b50000)
      eden space 4416K,  34% used [0x04600000, 0x0477c9e8, 0x04a50000)
      from space 512K,   0% used [0x04a50000, 0x04a50000, 0x04ad0000)
      to   space 512K,   0% used [0x04ad0000, 0x04ad0000, 0x04b50000)
     tenured generation   total 10944K, used 0K [0x09b50000, 0x0a600000, 0x14600000)
       the space 10944K,   0% used [0x09b50000, 0x09b50000, 0x09b50200, 0x0a600000)
     Metaspace       used 259K, capacity 2280K, committed 2368K, reserved 4480K
    15.463: [Full GC (System.gc()) 15.477: [Tenured: 0K->776K(10944K), 0.0428098 secs] 1522K->776K(15872K), [Metaspace: 259K->259K(4480K)], 0.0688257 secs] [Times: user=0.02 sys=0.00, real=0.07 secs] 
    Heap after GC invocations=1 (full 1):
     def new generation   total 4992K, used 0K [0x04600000, 0x04b60000, 0x09b50000)
      eden space 4480K,   0% used [0x04600000, 0x04600000, 0x04a60000)
      from space 512K,   0% used [0x04a60000, 0x04a60000, 0x04ae0000)
      to   space 512K,   0% used [0x04ae0000, 0x04ae0000, 0x04b60000)
     tenured generation   total 10944K, used 776K [0x09b50000, 0x0a600000, 0x14600000)
       the space 10944K,   7% used [0x09b50000, 0x09c122f0, 0x09c12400, 0x0a600000)
     Metaspace       used 259K, capacity 2280K, committed 2368K, reserved 4480K
    }
    Heap
     def new generation   total 4992K, used 45K [0x04600000, 0x04b60000, 0x09b50000)
      eden space 4480K,   1% used [0x04600000, 0x0460b4a8, 0x04a60000)
      from space 512K,   0% used [0x04a60000, 0x04a60000, 0x04ae0000)
      to   space 512K,   0% used [0x04ae0000, 0x04ae0000, 0x04b60000)
     tenured generation   total 10944K, used 776K [0x09b50000, 0x0a600000, 0x14600000)
       the space 10944K,   7% used [0x09b50000, 0x09c122f0, 0x09c12400, 0x0a600000)
     Metaspace       used 259K, capacity 2280K, committed 2368K, reserved 4480K

    测试环境:

    JVM: Java HotSpot(TM) Client VM (25.60-b23, mixed mode, sharing)Java: version 1.8.0_60, vendor Oracle Corporation

    Step1:

    监控界面,能够直观地看到JVM各个区域的内存使用情况。除了监视虚拟机,还可以监视应用的内存使用情况。尝试对Eclipse的启动进行优化,可以很明显的看到eclipse启动时,S0的对象向S1拷贝,而old区的使用量略微增加。

    一次JVM调优的笔记

    还可以监控当前CPU和内存负载情况,类加载数量和线程数:

    一次JVM调优的笔记

    Step2:

    eclipse安装目录下有个.ini文件,即eclipse的配置文件,将需要的参数配置填写进去即可。启动eclipse后,查看GC日志,发现整个启动过程中共发生了27次GC,其中有3次Full GC,整个启动过程,我掐指一算大概6~7秒,相当慢了。

    通过参数-XX:NewSize=n 将Eden区重设为128m后,再次启动eclipse发现,这次就只发生了11次GC,下降了一般还多,启动速度也明显比原来快了一些。

    Step3:

    接着使用-Xverify:none禁掉类加载时的字节码验证过程 ,GC次数为10次, 现在启动速度基本为3秒多左右,比原来快了一倍。

    {Heap before GC invocations=10 (full 4):
     def new generation   total 36864K, used 35041K [0x04400000, 0x06bf0000, 0x0eea0000)
      eden space 32832K, 100% used [0x04400000, 0x06410000, 0x06410000)
      from space 4032K,  54% used [0x06410000, 0x06638570, 0x06800000)
      to   space 4032K,   0% used [0x06800000, 0x06800000, 0x06bf0000)
     tenured generation   total 57224K, used 40267K [0x0eea0000, 0x12682000, 0x24400000)
       the space 57224K,  70% used [0x0eea0000, 0x115f2ca0, 0x115f2e00, 0x12682000)
     Metaspace       used 31836K, capacity 33329K, committed 33408K, reserved 34176K
    5.742: [GC (Allocation Failure) 5.742: [DefNew: 35041K->4031K(36864K), 0.0193873 secs] 75308K->46613K(94088K), 0.0194649 secs] [Times: user=0.02 sys=0.00, real=0.02 secs]

    然而这种调优粒度太粗,服务器上程序需要定位更精确的时间,所以需要更多参数来调试。

    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    Destoon 模板存放规则及语法参考

    Destoon系统常量与变量

    Destoon系统目录文件结构说明

    Destoon 系统安装指南

    Destoon会员公司主页模板风格添加方法

    Destoon 二次开发入门

    Microsoft 将于 2026 年 10 月终止对 Windows 11 SE 的支持

    Windows 11 存储感知如何设置?了解Windows 11 存储感知开启的好处

    Windows 11 24H2 更新灾难:系统升级了,SSD固态盘不见了...

    小米路由器买哪款?Miwifi热门路由器型号对比分析

    IT头条

    Synology 对 Office 套件进行重大 AI 更新,增强私有云的生产力和安全性

    01:43

    StorONE 的高效平台将 Storage Guardian 数据中心占用空间减少 80%

    11:03

    年赚千亿的印度能源巨头Nayara 云服务瘫痪,被微软卡了一下脖子

    12:54

    国产6nm GPU新突破!砺算科技官宣:自研TrueGPU架构7月26日发布

    01:57

    公安部:我国在售汽车搭载的“智驾”系统都不具备“自动驾驶”功能

    02:03

    技术热点

    最全面的前端开发指南

    Windows7任务栏桌面下角的一些正在运行的图标不见了

    sql server快速删除记录方法

    SQL Server 7移动数据的6种方法

    SQL Server 2008的新压缩特性

    每个Java程序员必须知道的5个JVM命令行标志

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。