一次 JVM 调优的笔记

JVM 11 的优化指南:如何进行JVM调优,JVM调优参数有哪些 在实际的Java应用开发中,JVM(Java Virtual Machine)调优是提升应用性能的关键步骤。合理的调优可以显著提升应用的响应速度、吞吐量,并且减少内存消耗和GC(Garbage Collection)停顿时间。本文将详细介绍JVM 11的优化指南,包含如何进行JVM调优以及常见的JVM调优参数,并提供3个实用的代码示例。 阅读详情

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]

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

JVM 21 的优化指南:如何进行JVM调优,JVM调优参数有哪些 这篇文章将详细介绍如何进行JVM 21调优,包括JVM 21调优参数及其应用。此外,我将提供12个实用的代码示例,每个示例都会结合和Java代码。本文已收录于,我的技术网站,有大厂完整,工作技术,架构师成长之路,等经验分享随着JVM版本的不断更新,JVM 21 在性能和功能上都带来了显著的提升。合理的JVM调优不仅可以提高应用程序的性能,还能显著减少内存消耗和GC(垃圾回收)停顿时间。本文将详细介绍JVM 21 的优化指南,包含如何进行JVM调优以及常见的JVM调优参数,并提供3个实用的代码示例。 阅读详情

相关推荐

JVM调优经历

JVM参数调优过程

zxg的博客 2960

JVM GC日志解析

在我们看GC日志时,我们需要对垃圾回收器的工作流程比较熟悉,这样比较方便我们查看gc日志,大家可以看看我上一篇GC理论。 JVM启动参数: -Xmn2M 年轻代分配2M -Xmx6M 给java堆分配6M -XX:+PrintGCDetails 打印GC详细信息 -XX:+PrintHeapAtGC 在GC发生之前与之后打印堆的详细信息 -XX:+PrintGCTimeStamps 允许在每个GC上打印时间戳。 -XX:+UseSerialGC 设置垃圾回收器serial+serialOld -XX:+Us

qq_41882485的博客 1778

告别代码恐惧!用KRobot图形化编程,10分钟搞定Arduino巡线小车(附完整接线图)

本文介绍如何使用KRobot图形化编程工具快速搭建Arduino巡线小车,无需编写代码。从硬件准备到逻辑构建,详细讲解传感器数据处理、电机控制优化及高级功能扩展,帮助教育工作者和创客爱好者10分钟内完成项目。

weixin_30632089的博客 393

Java JVM 学习笔记

JVM 结构概览 ClassLoader概述 public class MyApp { public static void main(String[] args) { //输出null,即BootstrapClassLoader,是由c++启动的 System.out.println(MyApp.class.getClassLoader().getPare...

q42368773的博客 540

UFS 3.1协议分析(第一至四章) -- UFS概述

Contents协议规范规范参考术语和定义简单概述通用特性接口特性功能特性 协议规范     UFS3.1协议规定了UFS电气接口和存储器件的特性以及系统架构。 特性:低功耗、高数据吞吐量、低电磁干扰、大容量存储器子系统效率的优化 电气接口:使用基于MIPI M-PHY的高级差分接口;M-PHY作为物理层,MIPI UniPro作为链路层,二者结合形成UFS接口的互联。 架构模型:参考 INCITS T10(SCSI) SAM 标准,命令协议基于 INCITS T1

Frank_sample的专栏 1万+

ks-快手滑块验证码-Js逆向

本文分析了快手滑块验证码的破解过程。首先通过抓包找到验证码背景图接口,发现需要动态获取captchaSession参数。然后深入分析验证流程,发现verifyParam参数被加密处理,需要追踪其生成逻辑。文章详细解析了加密参数c的构成,包括captchaSn、滑动距离、轨迹信息等,并指出轨迹验证较为严格。最后通过对比浏览器和本地生成的加密值,确认加密逻辑正确,但指出轨迹生成仍需优化。作者建议参考相关文章深入分析轨迹逻辑,并提供了验证成功的截图作为参考。

2302_76420666的博客 1876

垃圾回收器机制(三):正确姿势解读GC日志

年轻代log解读 年轻代以ParNew收集器为例, 采用的是复制算法, log如下: 2019-02-01T21:18:15:00.382+0800: 718675.758: Application time: 0.7177964 seconds {Heap before GC invocations=65632 (full 18): par new generation total 471872K, used 421490K [0x0000000080000000, 0x00000000a0000

大模型学习路线 601

物联网开发笔记(34)- 使用Micropython开发ESP32开发板之控制步进电机(28BYJ-48)

使用Micropython开发ESP32开发板之控制步进电机(28BYJ-48)

zhusongziye的博客 1万+

JVM垃圾回收调试

jvm运行调试参数 jdk.18 参数 - -Xms30M -Xmx30M 堆空间30M -Xmn10m 新生代10m -XX:SurvivorRatio=8 设置Eden和Survivor比例 默认8:1:1 -XX:+UseParallelGC jdk8默认使用的收集器 -XX:+PrintGCDetails 打印gc详情 -XX:-UseAdaptiveSizePolicy 禁止survivor变化 -XX:+PrintCommandLineFlags 打印jv

weixin_40313351的博客 385

2023-07-04 Fast-Lio论文中公式(6)与BCH公式中近似雅可比公式的一致性推导

将(1)式代入(6)式,就有。

wmorries的博客 475

人形机器人骨骼材料选型实战:从铝合金到碳纤维的5种方案对比

本文深入探讨人形机器人骨骼材料的选型策略,对比铝合金、镁合金、钛合金、碳纤维复合材料及3D打印材料等5种方案的性能优劣。通过建立强度-重量比、疲劳寿命等核心评价维度,结合具体应用场景,提供科学的材料决策方法论,助力开发者优化机器人结构设计,实现性能与成本的平衡。

weixin_29199873的博客 436

JVM垃圾回收(GC)原理

一、相关概念 基本回收算法 1. 引用计数(Reference Counting) 比较古老的回收算法。原理是此对象有一个引用,即增加一个计数,删除一个引用则减少一个计数。垃圾回收时,只用收集计数为0的对象。此算法最致命的是无法处理循环引用的问题。 2. 标记-清除(Mark-Sweep) 此算法执行分两阶段。第一阶段从引用根节点开始标记所有被引用的对象,第二阶段遍历整个堆,把未标记的对象清除。此...

chenchendefeng的专栏 393

stable-diffusion-webui的逐步部署教程

本文主要介绍了stable-diffusion-webui的逐步部署教程,希望能对使用Stable Diffusion的同学们有所帮助。 文章目录 1. 前言 2. 逐步部署教程 2.1 创建Python环境 2.2 安装依赖库 2.3 运行代码

weixin_43178406的博客 6万+

一次JVM调优的笔记

1. JVM Tuning基础知识 1.1 Java堆结构   Java堆可以处于物理上不连续的内存空间上,只要逻辑上是连续的即可。Java堆就是各种对象分配和保存的内存空间,线程间共享。Java堆分为Eden区,Survivor区,tenured区和Permanent区,如下图所示。   Java堆的分配原则如下: Java堆分布如下图所示,新的类的实例大部分在Eden(之所以用Ed...

weixin_34254823的博客 84

2、Elixir与Erlang:构建高可用系统的利器

本文介绍了Elixir与Erlang在构建高可用系统方面的优势,深入探讨了Erlang的并发机制、容错能力以及分布式特性,并结合实际应用场景展示了其在服务器端开发中的强大能力。此外,还提供了学习资源和交流平台,帮助开发者快速上手并深入实践。

grape的博客 124

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

【JVM调优】如何进行JVM调优?一篇文章就够了!

深入解读JVM性能的监控、定位和调优方案,阐述jps/stat/jstack、MAT等常用性能分析工具的使用,提出JVM参数、内存溢出、内存泄漏、CPU飙升、GC频繁等实际场景下JVM调优的方案。

种一棵树最好的时间是十年前,其次是现在 4万+

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

jvm调优

一、jvm内存调优 主要的目的是减小GC的频率和Full GC的次数。 1.Full GC 会对整个堆进行整理,包括Young、Tenured和Perm。Full GC由于须要对整个堆进行回收,因此比较慢,所以应该尽量减小Full GC的次数。数组 2.致使Full GC的缘由缓存 1)年老代(Tenured)被写满服务器 调优时尽可能让对象在新生代GC时被回收、让对象在新生代多存活一段时间和不要建立过大的对象及数组避免直接在旧生代建立对象 。并发 2)持久代Pemanet Generation空间不

白大锅的博客,毕设WangLoveBai_999 12万+

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

JVM性能调优详解

前面我们学习了整个JVM系列,最终目标的不仅仅是了解JVM的基础知识,也是为了进行JVM性能调优做准备。这篇文章带领大家学习JVM性能调优的知识。 性能调优 性能调优包含多个层次,比如:架构调优、代码调优、JVM调优、数据库调优、操作系统调优等。 架构调优和代码调优是JVM调优的基础,其中架构调优是对系统影响最大的。 性能调优基本上按照以下步骤进行:明确优化目标、发现性能瓶颈、性能调优、通过监控及...

程序新视界 7705

JVM优化:如何进行JVM调优,JVM调优参数有哪些

Java虚拟机(JVM)是Java应用运行的核心环境。JVM的性能优化对于提高应用性能、减少资源消耗和提升系统稳定性至关重要。本文将深入探讨JVM的调优方法和相关参数,以帮助开发者和系统管理员有效地优化他们的Java应用。本文,已收录于,我的技术网站,有大厂完整面经,工作技术,架构师成长之路,等经验分享JVM调优通常涉及到对堆内存、垃圾回收策略和线程堆栈大小等方面的调整。优化的目标是确保JVM在执行Java应用时能够高效地使用系统资源。

架构师专栏 5071

JVM调优

因此,建议在调优之前先进行性能分析和监测,针对性地调整参数,并进行实际测试和验证,以确保优化的效果和稳定性。每个参数都有特定的作用和含义,根据具体需求和应用程序的特点,选择适当的参数进行配置和调整。:垃圾回收是JVM的重要功能,但不恰当的垃圾回收策略可能导致长时间的停顿和性能下降。JVM调优旨在选择合适的垃圾回收器、调整垃圾回收参数,平衡吞吐量和停顿时间,减少垃圾回收对应用程序的影响。通过选择合适的垃圾回收器算法和参数,调整垃圾回收策略,可以降低垃圾回收的频率,提高系统的运行效率。

CA优快云的博客 8853

JVM调优实践:记录初次JVM调优经历

JVM调优实践:记录初次JVM调优经历前言JVM调优工具参考文章初步调优基本指令选择垃圾收集器初步确定堆大小 前言 之前关于 JVM 调优大部分都只是一些理论依据,具体经验没有,这回正好记录下。 中间一些碰壁与返工的部分就跳过了。 JVM调优工具 jps: 用来显示本地的java进程,可以查看本地运行着几个java程序,并显示他们的进程号。 jinfo: 可以根据进程号输出并修改运行时的java 进程的opts。 jstat: 一个极强的监视VM内存工具。可以用来监视VM内存内的各种堆和非堆的大

乐之终曲 2284

【JVM】JVM性能调优详解

前面我们学习了整个JVM系列,最终目标的不仅仅是了解JVM的基础知识,也是为了进行JVM性能调优做准备。这篇文章带领大家学习JVM性能调优的知识。

DreamSun的博客 5506

JVM 11 调优指南:如何进行JVM调优,JVM调优参数

JVM调优是通过调整Java虚拟机的配置参数来提升应用程序的性能和资源利用效率的过程。这包括调整堆内存大小、选择合适的垃圾收集器,以及调整其他性能相关的参数。合理的JVM调优可以显著提升应用的性能和稳定性。不过,请记得调优是一个持续的过程,需要根据应用的具体表现来不断调整和优化。本文已收录于,我的技术网站ddkk.com,有大厂完整面经,工作技术,架构师成长之路,等经验分享。

架构师专栏 2490
上一篇: Java虚拟机工作原理详解
下一篇: 用Redis构建分布式锁
breaknull
博客等级 码龄14年 15粉丝 29原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值