JVM(二)——参数调优

news2024/12/26 21:50:51

JVM参数调优

前言

在这里插入图片描述

你说你做过JVM调优和参数配置,请问如何盘点查看JVM系统默认值

使用jps和jinfo进行查看

-Xms:初始堆空间  1/64
-Xmx:堆最大值    1/4
-Xss:栈空间

-Xms 和 -Xmx最好调整一致,防止JVM频繁进行收集和回收

JVM参数类型

cmd测试

  • 标配参数(从JDK1.0 - Java12都在,很稳定)
    • -version
    • -help
    • java -showversion
  • X参数(了解)
    • -Xint:解释执行
    • -Xcomp:第一次使用就编译成本地代码
    • -Xmixed:混合模式
  • XX参数(重点)
    • Boolean类型
      • 公式:-XX:+ 或者-某个属性 + 表示开启true,-表示关闭false
      • Case:-XX:-PrintGCDetails:表示关闭了GC详情输出
    • key-value类型
      • 公式:-XX:属性key=属性value
      • 不满意初始值,可以通过下列命令调整
      • case:如何:-XX:MetaspaceSize=21807104:查看Java元空间的值

查看运行的Java程序,JVM参数是否开启,具体值为多少?

首先我们运行一个HelloGC的java程序

/**
 * @author: wzq
 * @create: 2020-03-19-12:14
 */
public class HelloGC {

    public static void main(String[] args) throws InterruptedException {
        System.out.println("hello GC");
        Thread.sleep(Integer.MAX_VALUE);
    }
}

然后使用terminal下列命令查看它的默认参数

cls清除命令行。

jps:查看java的后台进程
jinfo:查看正在运行的java程序

具体使用:

jps -l 得到进程号
12608 com.moxi.interview.study.GC.HelloGC
15200 sun.tools.jps.Jps
15296 org.jetbrains.idea.maven.server.RemoteMavenServer36
4528
12216 org.jetbrains.jps.cmdline.Launcher
9772 org.jetbrains.kotlin.daemon.KotlinCompileDaemon

查看到HelloGC的进程号为:12608

我们使用jinfo -flag 然后查看是否开启PrintGCDetails这个参数

jinfo -flag PrintGCDetails 12608

得到的内容为

-XX:-PrintGCDetails

上面提到了,-号表示关闭,即没有开启PrintGCDetails这个参数

下面我们需要在启动HelloGC的时候,增加 PrintGCDetails这个参数,需要在运行程序的时候配置JVM参数

在这里插入图片描述

然后在VM Options中加入下面的代码,现在+号表示开启

-XX:+PrintGCDetails

然后在使用jinfo查看我们的配置

jps -l
jinfo -flag PrintGCDetails 13540

得到的结果为

-XX:+PrintGCDetails

我们看到原来的-号变成了+号,说明我们通过 VM Options配置的JVM参数已经生效了

使用下列命令,会把jvm的全部默认参数输出,查看是否开启,-是关闭,+是开启

jinfo -flags ***

题外话(坑题)

两个经典参数:-Xms 和 -Xmx,这两个参数 如何解释

这两个参数,还是属于XX参数,因为取了别名

  • -Xms 等价于 -XX:InitialHeapSize :初始化堆内存(默认只会用最大物理内存的64分1)
  • -Xmx 等价于 -XX:MaxHeapSize :最大堆内存(默认只会用最大物理内存的4分1)

查看JVM默认参数

  • -XX:+PrintFlagsInitial

    • 主要是查看初始默认值
    • 公式
      • java -XX:+PrintFlagsInitial -version
      • java -XX:+PrintFlagsInitial(重要参数)in ni shou

在这里插入图片描述

  • -XX:+PrintFlagsFinal:表示修改以后,最终的值

​ 会将JVM的各个结果都进行打印

​ 如果有 := 表示修改过的, = 表示没有修改过的

修改某参数,并执行类

在这里插入图片描述

-XX:+PrintCommandLineFlags -version 打印常用命令

在这里插入图片描述

工作中常用的JVM基本配置参数

在这里插入图片描述

查看堆内存

查看cpu核数:Runtime.getRuntime().availableProcessors()。

Runtime是jvm的运行时内存数据。

查看JVM的初始化堆内存 -Xms 和最大堆内存 Xmx

    public static void main(String[] args) {
        long maxMemory = Runtime.getRuntime().maxMemory();
        long totalMemory = Runtime.getRuntime().totalMemory();
        // jvm默认获取操作系统的最大内存和初始内存大小,本机物理的内存的4分之一和64分之一
        System.out.println("-Xmx:MAX_MEMORY = " + maxMemory + "字节、" + (maxMemory/(double)1024/1024) + "MB");
        System.out.println("-Xms:TOTAL_MEMORY = " + totalMemory + "字节、" + (totalMemory/(double)1024/1024) + "MB");
    }

结果如下:

-Xmx:MAX_MEMORY = 2839543808字节、2708.0MB
-Xms:TOTAL_MEMORY = 192937984字节、184.0MB

-Xms 初始堆内存为:物理内存的1/64

-Xmx 最大堆内存为:系统物理内存的 1/4

一般实际结果是相对于小一点的

生产:初始和最大一样大,理由避免GC和应用程序竞争内存,理论值和峰值峰谷忽高忽低。

打印JVM默认参数

使用idea的Edit Configurtion的vm-options设置 -XX:+PrintCommandLineFlags 打印出JVM的默认的简单初始化参数

比如我的机器输出为:

-XX:InitialHeapSize=266376000 -XX:MaxHeapSize=4262016000 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC 

生活常用调优参数

  • -Xms:初始化堆内存,默认为物理内存的1/64,等价于 -XX:initialHeapSize
  • -Xmx:最大堆内存,默认为物理内存的1/4,等价于-XX:MaxHeapSize
  • -Xss:设置单个线程栈的大小,一般默认为512K~1024K,等价于 -XX:ThreadStackSize
    • 使用 jinfo -flag ThreadStackSize 会发现 -XX:ThreadStackSize = 0
    • 这个值的大小是取决于平台的,0就是默认出厂值
    • Linux/x64:1024KB
    • OS X:1024KB
    • Oracle Solaris:1024KB
    • Windows:取决于虚拟内存的大小
  • -Xmn:设置年轻代大小
  • -XX:MetaspaceSize:设置元空间大小
    • 元空间的本质和永久代类似,都是对JVM规范中方法区的实现,不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存,因此,默认情况下,元空间的大小仅受本地内存限制。
    • -Xms10m -Xmx10m -XX:MetaspaceSize=1024m -XX:+PrintFlagsFinal
    • 但是默认的元空间大小:只有20多M
    • 为了防止在频繁的实例化对象的时候,让元空间出现OOM,因此可以把元空间设置的大一些
  • -XX:PrintGCDetails:输出详细GC收集日志信息
    • GC
    • Full GC

在这里插入图片描述

GC日志收集流程图

在这里插入图片描述

我们使用一段代码,制造出垃圾回收的过程

首先我们设置一下程序的启动配置: 设置初始堆内存为10M,最大堆内存为10M

idea设置VM options,初始值和最大值都是10M并打印堆过程信息

-Xms10m -Xmx10m -XX:+PrintGCDetails

然后用下列代码,创建一个 非常大空间的byte类型数组

    //模拟OOM Error
    String s = "123456";
    while(true){
        s = s + new Random().nextInt(888888) + new Random().nextInt(99999);
    }

    byte[] bytes = new byte[1024*1024*1024*1024];//大于实际jvm获得的内存大小

运行后,发现会出现下列错误,这就是OOM:java内存溢出,也就是堆空间不足

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at ‘com.moxi.interview.study.GC.HelloGC.main(HelloGC.java:22)

同时还打印出了GC垃圾回收时候的详情日志

[GC (Allocation Failure) [PSYoungGen: 1972K->504K(2560K)] 1972K->740K(9728K), 0.0156109 secs] [Times: user=0.00 sys=0.00, real=0.03 secs] 
[GC (Allocation Failure) [PSYoungGen: 504K->480K(2560K)] 740K->772K(9728K), 0.0007815 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Allocation Failure) [PSYoungGen: 480K->0K(2560K)] [ParOldGen: 292K->648K(7168K)] 772K->648K(9728K), [Metaspace: 3467K->3467K(1056768K)], 0.0080505 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[GC (Allocation Failure) [PSYoungGen: 0K->0K(2560K)] 648K->648K(9728K), 0.0003035 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Allocation Failure) [PSYoungGen: 0K->0K(2560K)] [ParOldGen: 648K->630K(7168K)] 648K->630K(9728K), [Metaspace: 3467K->3467K(1056768K)], 0.0058502 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
Heap
 PSYoungGen      total 2560K, used 80K [0x00000000ffd00000, 0x0000000100000000, 0x0000000100000000)
  eden space 2048K, 3% used [0x00000000ffd00000,0x00000000ffd143d8,0x00000000fff00000)
  from space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
  to   space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
 ParOldGen       total 7168K, used 630K [0x00000000ff600000, 0x00000000ffd00000, 0x00000000ffd00000)
  object space 7168K, 8% used [0x00000000ff600000,0x00000000ff69dbd0,0x00000000ffd00000)
 Metaspace       used 3510K, capacity 4500K, committed 4864K, reserved 1056768K
  class space    used 389K, capacity 392K, committed 512K, reserved 1048576K

在这里插入图片描述

java7打印信息,7是永久区,8是元空间还有新老区都一样:

在这里插入图片描述

问题发生的原因:

因为们通过 -Xms10m 和 -Xmx10m 只给Java堆栈设置了10M的空间,但是创建了50M的对象,因此就会出现空间不足,而导致出错

同时在垃圾收集的时候,我们看到有两个对象:GC 和 Full GC

GC垃圾收集

GC在新生区

[GC (Allocation Failure) 
[PSYoungGen: 1972K->504K(2560K)] 1972K->740K(9728K), 0.0156109 secs] 
[Times: user=0.00 sys=0.00, real=0.03 secs]

GC (Allocation Failure):表示分配失败,那么就需要触发年轻代空间中的内容被回收

[PSYoungGen: 1972K->504K(2560K)] 1972K->740K(9728K), 0.0156109 secs]

参数对应的图为:

在这里插入图片描述

Full GC垃圾回收

Full GC大部分发生在养老区

[Full GC (Allocation Failure) 
[PSYoungGen: 0K->0K(2560K)] 
[ParOldGen: 648K->630K(7168K)] 648K->630K(9728K), 
[Metaspace: 3467K->3467K(1056768K)], 0.0058502 secs] 
[Times: user=0.00 sys=0.00, real=0.01 secs] 

在这里插入图片描述

规律:

[名称: GC前内存占用 -> GC后内存占用 (该区内存总大小)]

当我们出现了老年代都扛不住的时候,就会出现OOM异常

-XX:SurvivorRatio

re xu o

调节新生代中 eden 和 S0、S1的空间比例,默认为 -XX:SuriviorRatio=8,Eden:S0:S1 = 8:1:1

加入设置成 -XX:SurvivorRatio=4,则为 Eden:S0:S1 = 4:1:1

SurvivorRatio值就是设置eden区的比例占多少,S0和S1相同

Java堆从GC的角度还可以细分为:新生代(Eden区,From Survivor区合To Survivor区)和老年代

在这里插入图片描述

  • eden、SurvivorFrom复制到SurvivorTo,年龄 + 1

首先,当Eden区满的时候会触发第一次GC,把还活着的对象拷贝到SurvivorFrom去,当Eden区再次触发GC的时候会扫描Eden区合From区域,对这两个区域进行垃圾回收,经过这次回收后还存活的对象,则直接复制到To区域(如果对象的年龄已经到达老年的标准,则赋值到老年代区),通知把这些对象的年龄 + 1

  • 清空eden、SurvivorFrom

然后,清空eden,SurvivorFrom中的对象,也即复制之后有交换,谁空谁是to

  • SurvivorTo和SurvivorFrom互换

最后,SurvivorTo和SurvivorFrom互换,原SurvivorTo成为下一次GC时的SurvivorFrom区,部分对象会在From和To区域中复制来复制去,如此交换15次(由JVM参数MaxTenuringThreshold决定,这个参数默认为15),最终如果还是存活,就存入老年代

在这里插入图片描述

-XX:NewRatio(了解)

配置年轻代new 和老年代old 在堆结构的占比

默认: -XX:NewRatio=2 新生代占1,老年代2,年轻代占整个堆的1/3

-XX:NewRatio=4:新生代占1,老年代占4,年轻代占整个堆的1/5,NewRadio值就是设置老年代的占比,剩下的1个新生代

新生代特别小,会造成频繁的进行GC收集

-XX:MaxTenuringThreshold

设置垃圾最大年龄,SurvivorTo和SurvivorFrom互换,原SurvivorTo成为下一次GC时的SurvivorFrom区,部分对象会在From和To区域中复制来复制去,如此交换15次(由JVM参数MaxTenuringThreshold决定,这个参数默认为15),最终如果还是存活,就存入老年代

这里就是调整这个次数的,默认是15,并且设置的值 在 0~15之间

查看默认进入老年代年龄:jinfo -flag MaxTenuringThreshold 17344

-XX:MaxTenuringThreshold=0:设置垃圾最大年龄。如果设置为0的话,则年轻对象不经过Survivor区,直接进入老年代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大的值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概念

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

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

相关文章

微信小程序项目实例——摇色子

微信小程序项目实例——摇色子 文章目录微信小程序项目实例——摇色子一、项目展示二、核心代码三、效果图文末项目代码见文字底部&#xff0c;点赞关注有惊喜 一、项目展示 摇色子是一款简易的游戏类小程序 用户可以投出1-9个色子 二、核心代码 dice.wxml <!--pages/dic…

编解码标准-H.264

H.264是MPEG-4家族中的一员&#xff0c;即MPEG-4系列文档ISO-14496的第10部分&#xff0c;因此被称作MPEG-4 AVC&#xff0c;MPEG-4重点考虑灵活性和交互性&#xff0c;而H.264着重强调更高的编码压缩率和传输的可靠性。 1、H.264 编码流程 1.1、slice&block 第一步&…

字节面试官: 让你设计一个MQ每秒要抗几十万并发,怎么做?

目录 1、页缓存技术 磁盘顺序写2、零拷贝技术3、最后的总结 这篇文章来聊一下Kafka的一些架构设计原理&#xff0c;这也是互联网公司面试时非常高频的技术考点。 Kafka是高吞吐低延迟的高并发、高性能的消息中间件&#xff0c;在大数据领域有极为广泛的运用。配置良好的Kaf…

电商项目之如何迁移千万级别的数据表

1 背景 电商系统一般都会有一张表记录买家的浏览器信息&#xff0c;包含但不限于浏览器ip、浏览器cookie信息、浏览器user-agent、当前页面的url、当前页面的refer。买家在电商网站上每一次操作&#xff0c;都会记录到该表。该表的数量量至少达到千万级级别。该表有什么用处&a…

07.优雅地断开套接字连接

优雅地断开套接字连接 本章将讨论如何优雅地断开相互连接的套接字。之前用的方法不够优雅是因为&#xff0c;我们是调用close或closesocket函数单方面断开连接的。 基于TCP的半关闭 TCP中的断开连接过程比建立连接过程更重要&#xff0c;因为连接过程中一般不会出现大的变数…

八、MySQL 常用函数汇总(1)

文章目录一、函数1.1 函数简介1.2 不同DBMS函数的差异二、数学函数2.1 绝对值函数ABS(x)和返回圆周率的函数PI()2.2 平方根函数SQRT(x)和求余函数MOD(x,y)2.3 获取整数的函数CEIL(x)、CEILING(x)和FLOOR(x)2.4 获取随机数的函数RAND()和RAND(x)2.5 函数ROUND(x)、ROUND(x,y)和T…

keytool 工具介绍

使用JDK自带的 keytool 工具&#xff1a; 简介 keytool 命令是一个密钥和证书管理的工具。它允许用户使用数字签名管理自己的公钥/私钥对和相关证书&#xff0c;用于自我身份验证(向其他用户和服务验证自己)或数据完整性和身份验证服务。keytool 命令还允许用户缓存通信对等体…

【七牛云 后端】笔试面

一、选择、填空知识点整理 1. fork() 函数 fork() 函数通过系统调用创建一个与原来进程相同的进程&#xff08;如果初始参数或者传入的变量不同&#xff0c;两个进程也可以做不同的事&#xff09; 示例 —— #include <stdio.h> int main() {for(int i0; i<2; i){…

centos7 安装git

一、查看是否安装过git git --version若出现以上版本号&#xff0c;则代表已经安装了git&#xff0c;不需要再次安装了&#xff0c;git安装&#xff0c;分为用yum安装和下载git源码编译安装&#xff0c;以下两种方法&#xff1a; 二、使用yum安装git yum -y install git安装…

磨金石教育摄影技能干货分享|如何在纪实摄影中体现艺术内涵

纪实摄影往往是摄影师在生活中或者旅行中随手拍下的&#xff0c;记录人们平常的瞬间。这类摄影往往强调真实性&#xff0c;在技巧上不会过多的追求。但有时候摄影师为了体现照片中更多的内涵&#xff0c;或者个人的情感思想&#xff0c;会运用一些摄影技巧来表现。下面就让我们…

动态内存与动态内存函数详解

文章目录前言一、动态内存函数的介绍1.malloc函数2.calloc3.realloc4.free二、两种常见的内存申请方法1.返回指针2.传二级指针三.常见的动态内存错误1.对NULL指针的解引用操作2.对动态开辟空间的越界访问3.对非动态开辟内存使用free释放4.使用free释放一块动态开辟内存的一部分…

6. 描述性统计函数:summary 、Fivenum、describe、describeBy、stat.desc、 Aggregate、summaryBy

b站课程视频链接&#xff1a; https://www.bilibili.com/video/BV19x411X7C6?p1 腾讯课堂(最新&#xff0c;但是要花钱&#xff0c;我花99&#x1f622;&#x1f622;元买了&#xff0c;感觉讲的没问题&#xff0c;就是知识点结构有点乱&#xff0c;有点废话&#xff09;&…

ESP32设备驱动-ADXL345三轴加速计驱动

ADXL345三轴加速计驱动 文章目录 ADXL345三轴加速计驱动1、ADXL345介绍2、硬件准备3、软件准备4、驱动实现1、ADXL345介绍 ADXL345 是一款小型、薄型、低功耗、3 轴加速度计,具有高达 16g 的高分辨率(13 位)测量值。数字输出数据采用 16 位二进制补码格式,可通过 SPI(3 线…

C进阶:动态内存函数 malloc calloc realloc free及常见动态内存开辟错误

本文主要讲解动态内存开辟的有关知识。 目录 一.malloc 与 free 1.malloc 2.free 3.实例&#xff1a; 二.calloc 三.realloc 四.常见的动态内存错误 1.对NULL指针的解引用操作 2.对动态开辟空间的越界访问 3.对非动态开辟内存使用free释放 4.使用free释放一块动态…

springboot 构建多模块项目

新建 spring initializr 父项目 Spring 官方提供了 Spring Initializr 来引导大家快速构建一个应用项目。在此不细说。 idea 创建 1、 new – project 注意jdk版本 和 勾选 default,然后next 2、 填写项目信息 3、选择项目组成部分,也可后期加上 4、选择项目位置 --选…

Docker入门:介绍Docker的常用命令、镜像的加载原理、Dockerfile打包、Docker网络、Docker Compose容器编排+监控

Docker入门 1&#xff09;从面向对象角度来看&#xff0c;Docker利用容器&#xff08;Container&#xff09;独立运行一个或一组应用&#xff0c;应用程序或服务运行在容器里面&#xff0c;容器就类似于一个虚拟化的运行环境&#xff0c;容器是用镜像创建出来的运行实例。就像是…

区块链笔记4--BTC实现

1 UTXO &#xff1a;区块链是一个去中心化的账本&#xff0c;比特币采用了 基于交易的账本模式。然而&#xff0c;系统中并无显示记录账户包含BTC数&#xff0c;实际上其需要通过交易记录进行推算。在比特币系统中&#xff0c;全节点需要维护一个名为 UTXO(UnspentTransaction …

Java抽象类:案例、特点、模板方法模式

一.抽象类的案例 案例&#xff1a;加油站支付卡 系统需求&#xff1a; 某加油站推出了2种支付卡&#xff1a; 1、预存1万元的金卡&#xff0c;后续加油享受8折优惠&#xff1b; 2、预存5千元的银卡&#xff0c;后续加油享受8.5折优惠。 请分别实现2种卡片进入收银系统后的…

记录每日LeetCode 2293.极大极小游戏 Java实现

题目描述&#xff1a; 给你一个下标从 0 开始的整数数组 nums &#xff0c;其长度是 2 的幂。 对 nums 执行下述算法&#xff1a; 设 n 等于 nums 的长度&#xff0c;如果 n 1 &#xff0c;终止 算法过程。否则&#xff0c;创建 一个新的整数数组 newNums &#xff0c;新数组…

分享66个HTMLCSS源码,总有一款适合您

HTML&CSS源码 分享66个HTML&CSS源码&#xff0c;总有一款适合您 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#xff0c;大家下载后可以看到。 源码下载链接&#xff1a;https://pan.baidu.com/s/1AeVqON7byvt-ngB_U…