首页 > 其他分享 >浅谈JVM整体架构与调优参数

浅谈JVM整体架构与调优参数

时间:2024-04-02 09:24:07浏览次数:28  
标签:存储 浅谈 XX 调优 线程 JVM 方法

本文分享自华为云社区《【性能优化】JVM整体架构与调优参数说明》,作者: 冰 河。

JVM的分类

这里,我们先来说说什么是VM吧,VM的中文含义为:虚拟机,指的是使用软件的方式模拟具有完整硬件系统功能、运行在一个完全隔离环境中的完整计算机系统,是物理机的软件实现。

常用的虚拟机有:VMWare、Virtual Box,Java Virtual Machine(JVM,Java虚拟机)。

这里,我们重点聊的就是JVM,Java虚拟机。看下图。

825b2eec70954776a8fe95791340256c.png

这张图看起来还是比较简单的,JVM运行于操作系统之上,操作系统是运行在计算机硬件上的。

关于JVM,其实有很多大厂开发了不同版本的JVM,比较知名的有:Sun HotSpot VM、BEA JRockit VM、IBM J9 VM、 Azul VM、 Apache Harmony、 Google Dalvik VM、 Microsoft JVM等等。

现在使用的比较多的JDK8版本就是Sun HotSpot VM与BEA JRockit VM合并之后开发出的JDK版本。

JVM的构成

JVM主要由三个子系统构成,分别为:类加载器子系统、运行时数据区(内存结构)和字节码执行引擎。

fa4b9d489ffb407ba6e9ffaf9b4ed420.png

为了更好的理解JVM,我们来看一下JVM的全貌图。

06afe983572e4c529d6b49c5b57f055f.png

当我们开发Java程序时,首先会编写.java文件,之后,会将.java文件编译成.class文件。

JVM中,会通过类装载子系统将.class文件的内容装载到JVM的运行时数据区,而JVM的运行时数据区又会分为:方法区、堆、栈、本地方法栈和程序计数器 几个部分。

在装载class文件的内容时,会将class文件的内容拆分为几个部分,分别装载到JVM运行时数据区的几个部分。其中,值得注意的是:程序计数器的作用是:记录程序执行的下一条指令的地址。

方法区也叫作元空间,主要包含了:运行时常量池、类型信息、字段信息、方法信息、类加载器的引用、对应的Class实例的引用等信息。

在JVM中,程序的执行是通过执行引擎进行的,执行引擎会调用本地方法的接口来执行本地方法库,进而完成整个程序逻辑的执行。

我们常说的垃圾收集器是包含在执行引擎中的,在程序的运行过程中,执行引擎会开启垃圾收集器,并在后台运行,垃圾收集器会不断监控程序运行过程中产生的内存垃圾信息,并根据相应的策略对垃圾信息进行清理。

这里,大家需要注意的是:栈、本地方法栈和程序计数器是每个线程运行时独占的,而方法区和堆是所有线程共享的。所以,栈、本地方法栈和程序计数器不会涉及线程安全问题,而方法区和堆会涉及线程安全问题。

方法区(元空间)

很多小伙伴一看到方法区三个字,脑海中的第一印象可能是存储方法的地方吧。

实则不然,方法区的另一个名字叫作元空间,相信不少小伙伴或多或少的听说过元空间。这个区域是JDK1.8中划分出来的。主要包含:运行时常量池、类型信息、字段信息、方法信息、类加载器的引用、对应的Class实例的引用等信息。方法区中的信息能够被多个线程共享。

例如,在程序中声明的常量、静态变量和有关于类的信息等的引用,都会存放在方法区,而这些引用所指向的具体对象 一般都会在堆中开辟单独的空间进行存储,也可能会在直接内存中进行存储。

622d2f8cbaf5494a8f00c10756eeeb4a.png

堆中主要存储的是实际创建的对象,也就是会存储通过new关键字创建的对象,堆中的对象能够被多个线程共享。堆中的数据不需要事先明确生存期,可以动态的分配内存,不再使用的数据和对象由JVM中的GC机制自动回收。对JVM的性能调优一般就是对堆内存的调优。

Java中基本类型的包装类:Byte、Short、Integer、Long、Float、Double、Boolean、Character类型的数据是存储在堆中的。

堆一般会被分成年轻代和老年代。而年轻代又会被进一步分为1个Eden区和2个Survivor区。在内存分配上,如果保持默认配置的话,年轻代和老年代的内存大小比例为1 : 2,年轻代中的1个Eden区和2个Survivor区的内存大小比例为:8 : 1 : 1。

3412dfc8c91049e2a0837b78e0cf5db2.png

栈一般又叫作线程栈或虚拟机栈,一般存储的是局部变量。在Java中,每个线程都会有一个单独的栈区,每个栈中的元素都是私有的,不会被其他的栈所访问。栈中的数据大小和生存期都是确定的,存取速度比较快。

在Java中,所有的基本数据类型(byte、short、int、long、float、double、boolean、char)和引用变量(对象引用)都是在栈中的。一般情况下,线程退出或者方法退出时,栈中的数据会被自动清除。

程序在执行过程中,会在栈中为不同的方法创建不同的栈帧,在栈帧中又包含了:局部变量表、操作数栈、动态链接和方法出口。

e2e7eae6e0d5405ca6647c6ca5777162.png

关于局部变量表、操作数栈、动态链接和方法出口的具体作用,会在《架构师进阶系列》中的后续文章中详细阐述。

栈中一般会存储对象的引用,这些引用所指向的具体对象一般都会在堆中开辟单独的地址空间进行存储,也有可能存储在直接内存中。

3fadd1a139fd40978e76284614d84575.png

注意: 这里说的是这些引用所指向的具体对象一般都会在堆中开辟单独的地址空间进行存储,也有可能存储在直接内存中。

因为在JVM中,如果开启了逃逸分析和标量替换,则可能不会再在堆上创建对象,可能会将对象直接分配到栈上,也可能不再创建对象,而是进一步分解对象中的成员变量,将其直接在栈上分配空间并赋值。

本地方法栈

本地方法栈相对来说比较简单,就是保存native方法进入区域的地址。

例如,在Java中创建线程,调用Thread对象的start()方法时,会通过本地方法start0()调用操作系统创建线程的方法。此时,本地方法栈就会保存start0()方法进入区域的内存地址。

程序计数器

程序计数器也叫作PC计数器,只要存储的是下一条将要执行的命令的地址。

JVM调优参数

在JVM中,主要是对堆(新生代)、方法区和栈进行性能调优。各个区域的调优参数如下所示。

  • 堆:-Xms、-Xmx
  • 新生代:-Xmn
  • 方法区(元空间):-XX:MetaspaceSize、-XX:MaxMetaspaceSize
  • 栈(线程):-Xss

为了更加直观的表述,我们可以将JVM的内存区域和对应的调优参数总结成下图所示。

d2e8e09e945d434da6dfc9de1a6043b1.png

在设置JVM启动参数时,需要特别注意方法区(元空间)的参数设置。

关于方法区(元空间)的JVM参数主要有两个:-XX:MetaspaceSize和-XX:MaxMetaspaceSize。

-XX:MetaspaceSize: 指的是方法区(元空间)触发Full GC的初始内存大小(方法区没有固定的初始内存大小),以字节为单位,默认为21M。达到设置的值时,会触发Full GC,同时垃圾收集器会对这个值进行修改。

如果在发生Full GC时,回收了大量内存空间,则垃圾收集器会适当降低此值的大小;如果在发生Full GC时,释放的空间比较少,则在不超过设置的-XX:MetaspaceSize值或者在没设置-XX:MetaspaceSize的值时不超过21M,适当提高此值。

-XX:MaxMetaspaceSize: 指的是方法区(元空间)的最大值,默认值为-1,不受堆内存大小限制,此时,只会受限于本地内存大小。

最后需要注意的是: 调整方法区(元空间)的大小会发生Full GC,这种操作的代价是非常昂贵的。如果发现应用在启动的时候发生了Full GC,则很有可能是方法区(元空间)的大小被动态调整了。

所以,为了尽量不让JVM动态调整方法区(元空间)的大小造成频繁的Full GC,一般将-XX:MetaspaceSize和-XX:MaxMetaspaceSize设置成一样的值。例如,物理内存8G,可以将这两个值设置为256M

最后,我们一起看下在物理内存8G的情况下,启动应用程序时,可以设置的JVM参数。当然,我这里给出的是一些经验值,实际部署到生产环境时,需要经过压测找到最佳的参数值。

  • 启动SpringBoot
java ‐Xms2048M ‐Xmx2048M ‐Xmn1024M ‐Xss512K ‐XX:MetaspaceSize=256M ‐XX:MaxMetaspaceSize=256M ‐jar xxx.jar
  • 启动Tomcat(Linux)

在Tomcat bin目录下catalina.sh文件里配置。

‐Xms2048M ‐Xmx2048M ‐Xmn1024M ‐Xss512K ‐XX:MetaspaceSize=256M ‐XX:MaxMetaspaceSize=256M
  • 启动Tomcat(Windows)

在Tomcat bin目录下catalina.bat文件里配置。

‐Xms2048M ‐Xmx2048M ‐Xmn1024M ‐Xss512K ‐XX:MetaspaceSize=256M ‐XX:MaxMetaspaceSize=256M

总结

今天,我们一起学习了JVM的整体架构和调优参数,主要包括:JVM的总体结构、JVM的分类、JVM的构成和调优参数。你学会了吗?欢迎在文末留言说出你的想法,如果你有更好的见解,也可以在文末留言和大家交流。

点击关注,第一时间了解华为云新鲜技术~

 

标签:存储,浅谈,XX,调优,线程,JVM,方法
From: https://www.cnblogs.com/huaweiyun/p/18109833

相关文章

  • 在Linux中,有哪些性能调优工具?
    在Linux中,有多种性能调优工具可以帮助管理员和开发者分析和优化系统的性能。以下是一些常用的性能调优工具:top命令:top是最常用的查看系统负载的工具,提供了一个不断更新的进程和性能的仪表板。可以查看内存使用量、负载平均值以及哪些进程正在使用最多的资源等信息。vmsta......
  • Java基础-JDK,JRE,JVM面试题
    目录1、JDK2、JRE3、JVM(1)JVM的跨语言特性(2)垃圾回收机制(GC)(3)内存溢出(OOM)(4)内存泄漏(5)内存溢出与内存泄漏的关系1、JDKJavaDevelopmentKit,Java开发工具包,包含JRE、开发工具(javac编译、java运行、jdb调试、jar打包);2、JREJavaRuntimeEnvironment,Java运行时环境,包含JV......
  • 模型调优的艺术:超参数调整与集成方法
    目录1.前言2.超参数搜索策略2.1.网格搜索(GridSearch)2.2.随机搜索(RandomSearch)3.模型集成技术3.1.Bagging(BootstrapAggregating)3.2.Boosting4.实例:优化现有模型性能5.总结1.前言         模型调优是机器学习实践中至关重要的一环,它关乎模型能否在新......
  • 对JDK,JRE,JVM的理解
    编程语言分类:编译型语言            将代码一次性编译成编译器能翻译的文件格式解释型语言            逐行翻译逐行执行java的执行机制,将源代码编译成字节码文件(平台中立文件.class),再将字节码文件进行解释执行Java专有名词介绍: ......
  • 面试题:JVM 调优
    一、JVM参数设置1.tomcat的设置vm参数修改TOMCAT_HOME/bin/catalina.sh文件,如下图JAVA_OPTS="-Xms512m-Xmx1024m"2.springboot项目jar文件启动通常在linux系统下直接加参数启动springboot项目nohupjava-Xms512m-Xmx1024m-jarxxxx.jar--spring.pro......
  • 浅谈AI未来发展趋势与挑战
    对于AI大模型未来发展趋势与挑战的个人看法:1、未来的发展趋势:AI大模型未来发展趋势可以从以下几个关键方面来讨论:1. 能源与计算效率绿色计算与节能技术:随着硬件技术的发展,预计未来的AI大模型将进一步降低能源消耗,采用更高效的处理器、专门针对AI任务设计的定制芯片(如TPU......
  • 在Java中什么是JVM?
    在Java中,JVM(JavaVirtualMachine)是Java平台的一个核心组成部分,它允许Java程序能够在多种硬件和操作系统平台上运行而无需做任何修改。JVM的跨平台特性是通过“一次编写,到处运行”(WriteOnce,RunAnywhere)的理念实现的。下面详细介绍JVM的工作原理和其关键组成部分。JVM的工......
  • 浅谈Windows发展史
    简介从微软发布Windows1.0开始,到现在已经有快40年历史了,接下来让我们浅浅的谈一下微软的发展史(只记录大家都知道的)Windows1.0Windows1.0是微软于1985年11月20日发布的操作系统,这也是微软第一个图形化操作系统。基本的功能也是有了。Windows2.0Windows2.0是微软于1987......
  • JVM——堆
    注:以下所有内容基于JDK1.8定义:线程共享区域:用来保存对象实例,数组等,当堆中没有内存空间可以分配给实例,也无法扩展时,则抛出OutOfMemoryError(OOM)。JDK1.8后将方法区从堆中移出,转移到本地内存元空间中,主要是为了防止OOM。空间划分:老年代(2/3FUllGC):主要保存生命周期较长的对象,......
  • [树上背包浅谈]
    树上背包在这个树中选取一定数量的点或边(也可能是其他属性),使得某种与点权或者边权相关的花费最大或者最小。解决这类问题,一般要考虑使用树上背包。dp[i][j]表示在以i为根的树中选择j个结点所获得的最大值/最小值有线电视网#include<cstdio>#include<cstring>#include<ios......