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

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: JVM 11的优化指南:如何进行JVM调优,以及JVM调优参数有哪些”这篇文章将包含JVM 11调优的核心概念、重要性、调优参数,并提供12个实用的代码示例,每个示例都会结合JVM调优参数和Java代码

JVM 11的优化指南:如何进行JVM调优,以及JVM调优参数有哪些”这篇文章将包含JVM 11调优的核心概念、重要性、调优参数,并提供12个实用的代码示例,每个示例都会结合JVM调优参数和Java代码

本文已收录于,我的技术网站 ddkk.com,有大厂完整面经,工作技术,架构师成长之路,等经验分享

JVM 11的优化指南

JVM调优简介

JVM调优是通过调整Java虚拟机的配置参数来提升应用程序的性能和资源利用效率的过程。这包括调整堆内存大小、选择合适的垃圾收集器,以及调整其他性能相关的参数。

JVM调优的重要性

  • 提高性能:通过调优,可以提升应用程序的响应速度和处理能力。
  • 资源优化:合理的配置可以使应用更高效地利用系统资源。
  • 稳定性增强:避免过度的资源消耗和频繁的垃圾回收,从而提高应用的稳定性。

JVM 11调优参数

  • 堆内存设置-Xms-Xmx 设置堆的起始大小和最大大小。
  • 垃圾收集器选择-XX:+UseG1GC 使用G1垃圾收集器,适用于大堆和多核处理器。
  • 性能监控-XX:+PrintGCDetails-XX:+PrintGCDateStamps 打印垃圾收集细节。

企业级 JVM 11 的调优参数,机器配置是8核32G

为配置有8核和32GB内存的机器推荐JVM 11调优参数时,需考虑应用的类型、负载特性等。以下是一套企业级的JVM调优参数推荐,适用于大多数中大型Java应用:

1、堆内存设置

  • -Xms16g:设置初始堆内存为16GB。这个设置使得JVM在启动时即分配较大内存,减少运行时动态扩展带来的性能损耗。
  • -Xmx16g:设置最大堆内存为16GB。这样做可以防止频繁的垃圾回收,并保证应用程序有足够的内存。

2、垃圾收集器选择

  • -XX:+UseG1GC:使用G1垃圾收集器,适用于需要快速响应和大内存管理的应用。

3、G1垃圾收集器的进一步优化

  • -XX:MaxGCPauseMillis=200:尽可能将GC暂停时间控制在200毫秒以内,以减少应用停顿。
  • -XX:ParallelGCThreads=8:设置并行GC线程数,通常设置为CPU核心数。
  • -XX:ConcGCThreads=4:设置G1垃圾回收器的并发线程数,通常为ParallelGCThreads的一半。

4、元空间设置

  • -XX:MetaspaceSize=256m:设置初始元空间大小为256MB。
  • -XX:MaxMetaspaceSize=512m:设置最大元空间大小为512MB,以防止元空间过度使用内存。

5、GC日志记录

  • -Xlog:gc*:file=gc.log:time,level:filecount=5,filesize=20M:配置GC日志输出,包括日志文件的位置、大小和轮转。

6、性能调优

  • -XX:+UseStringDeduplication:开启字符串去重功能,减少堆内存的占用。
  • -XX:+DisableExplicitGC:禁用显式GC调用(如System.gc() ),避免不必要的GC操作。

7、高级调优选项

  • -XX:+UnlockExperimentalVMOptions:解锁实验性VM选项,用于开启一些最新的优化功能。
  • -XX:+UseLargePages:启用大页面支持,有助于提高大内存机器的性能。

注意事项

  • 根据应用的实际性能和资源使用情况调整这些参数。
  • 应用性能监控工具可以帮助您更好地理解应用运行情况。
  • 在生产环境中逐渐调整参数,并密切关注每次调整后的影响。

合理的JVM调优可以显著提升应用的性能和稳定性。不过,请记得调优是一个持续的过程,需要根据应用的具体表现来不断调整和优化。

实用代码示例

示例1:设置和监控堆内存大小

JVM启动参数:

java -Xms512m -Xmx1g -jar YourApp.jar
  • -Xms512m:设置初始堆内存为512MB。
  • -Xmx1g:设置最大堆内存为1GB。

Java代码:

public class HeapSizeMonitoring {
   
    public static void main(String[] args) {
   
        // 获取运行时环境
        Runtime runtime = Runtime.getRuntime();

        // 打印JVM的初始内存和最大内存配置
        System.out.println("JVM初始内存大小:" + runtime.totalMemory() / (1024 * 1024) + " MB");
        System.out.println("JVM最大内存大小:" + runtime.maxMemory() / (1024 * 1024) + " MB");
    }
}

此代码示例演示了如何在Java应用程序中监控当前JVM的堆内存使用情况。

示例2:使用G1垃圾收集器并监控GC

JVM启动参数:

java -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -jar YourApp.jar
  • -XX:+UseG1GC:使用G1垃圾收集器。
  • -XX:MaxGCPauseMillis=200:设置期望的最大GC暂停时间为200毫秒。
  • -XX:+PrintGCDetails-XX:+PrintGCDateStamps:打印GC的详细信息和时间戳。

Java代码:

import java.util.ArrayList;
import java.util.List;

public class G1GCExample {
   
    public static void main(String[] args) {
   
        List<byte[]> list = new ArrayList<>();
        while (true) {
   
            list.add(new byte[1024 * 1024]); // 每次分配1MB的空间
            if (list.size() > 100) {
   
                list.clear(); // 清空列表以释放内存
            }
        }
    }
}

此代码示例展示了在使用G1垃圾收集器时的内存分配和清理过程。

示例3:线程堆栈大小的设置与监控

JVM启动参数:

java -Xss256k -jar YourApp.jar
  • -Xss256k:设置每个线程的堆栈大小为256KB。

Java代码:

javaCopy code
public class ThreadStackSizeExample {
   
    public static void main(String[] args) {
   
        // 创建并启动一个新线程
        Thread thread = new Thread(() -> {
   
            try {
   
                Thread.sleep(10000); // 让线程休眠一段时间
            } catch (InterruptedException e) {
   
                e.printStackTrace();
            }
        });
        thread.start();

        System.out.println("线程堆栈大小设置为256KB...");
    }
}

这段代码展示了如何设置线程的堆栈大小,并创建一个简单的线程来展示这一设置的实际应用。

示例4:使用G1垃圾收集器并调优

JVM启动参数:

java -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:InitiatingHeapOccupancyPercent=45 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -jar YourApp.jar
  • -XX:+UseG1GC:使用G1垃圾收集器。
  • -XX:MaxGCPauseMillis=200:尝试将GC的最大暂停时间控制在200毫秒以内。
  • -XX:InitiatingHeapOccupancyPercent=45:当堆占用率达到45%时开始GC。
  • -XX:+PrintGCDetails-XX:+PrintGCDateStamps:打印详细的GC信息和时间戳。

Java代码:

import java.util.ArrayList;
import java.util.List;

public class G1GCExample {
   
    public static void main(String[] args) {
   
        System.out.println("G1垃圾收集器已启用,GC的详细信息和时间戳将被打印...");

        // 创建一个列表,用于存储分配的内存块
        List<byte[]> list = new ArrayList<>();
        for (int i = 0; i < 1000; i++) {
   
            // 每次循环分配1MB的内存块
            list.add(new byte[1024 * 1024]);

            // 每当列表中有100个内存块时,清空列表,释放内存
            if (list.size() >= 100) {
   
                list.clear();
                // 建议执行一次垃圾收集
                System.gc();
            }
        }
    }
}

此代码示例展示了如何在使用G1垃圾收集器的情况下进行内存分配和清理。

示例5:监控垃圾收集信息

JVM启动参数:

java -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -jar YourApp.jar
  • -XX:+PrintGC:打印基本的GC信息。
  • -XX:+PrintGCDetails:打印GC的详细信息。
  • -XX:+PrintGCDateStamps:在GC日志中加入时间戳。

Java代码:

import java.util.concurrent.TimeUnit;

public class GCMonitoringExample {
   
    public static void main(String[] args) throws InterruptedException {
   
        System.out.println("垃圾收集信息监控已启用,GC的基本信息、详细信息和时间戳将被打印...");

        // 分配内存并稍作等待,以便观察GC的行为
        byte[] allocation1 = new byte[512 * 1024 * 1024]; // 分配约512MB的空间
        TimeUnit.SECONDS.sleep(10); // 睡眠10秒

        byte[] allocation2 = new byte[512 * 1024 * 1024]; // 再分配约512MB的空间
        TimeUnit.SECONDS.sleep(10); // 睡眠10秒

        // 提示垃圾收集
        System.gc();
    }
}

此代码示例演示了如何通过分配大量内存并加入等待时间来观察GC的行为,同时启用了详细的GC信息打印。

示例6:设置线程堆栈大小

JVM启动参数:

java -Xss1024k -jar YourApp.jar
  • -Xss1024k:设置每个线程的堆栈大小为1024KB。

Java代码:

public class ThreadStackSizeExample {
   
    public static void main(String[] args) {
   
        System.out.println("线程堆栈大小已设置为1024KB...");

        // 创建并启动一个新线程,展示设置的堆栈大小
        Thread thread = new Thread(() -> {
   
            recursiveMethod(0);
        });
        thread.start();
    }

    // 一个简单的递归方法,用于演示堆栈的深度
    private static void recursiveMethod(int depth) {
   
        if (depth < 1000) {
   
            recursiveMethod(depth + 1);
        } else {
   
            System.out.println("达到递归深度:" + depth);
        }
    }
}

这段代码设置了线程的堆栈大小,并通过递归调用来测试堆栈深度的限制。

示例7:监控类的加载和卸载

JVM启动参数:

java -XX:+TraceClassLoading -XX:+TraceClassUnloading -jar YourApp.jar
  • -XX:+TraceClassLoading:启用类加载跟踪。
  • -XX:+TraceClassUnloading:启用类卸载跟踪。

Java代码:

public class ClassLoadingMonitoring {
   
    public static void main(String[] args) {
   
        System.out.println("类加载和卸载监控已启动,相关信息将打印到控制台...");

        // 这里不需要特定的Java代码来触发类的加载或卸载
        // 类加载和卸载的信息将通过JVM参数直接打印到控制台
        // 可以考虑加载一些额外的类或使用ClassLoader来观察输出
    }
}

此代码示例用于展示如何开启和查看JVM的类加载和卸载信息,对于理解类的生命周期非常有用。

示例8:监控垃圾回收行为

JVM启动参数:

java -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log -jar YourApp.jar
  • -XX:+PrintGCDetails:打印垃圾回收的详细信息。
  • -XX:+PrintGCDateStamps:在垃圾回收日志中加入时间戳。
  • -Xloggc:gc.log:将垃圾回收日志记录到指定文件。

Java代码:

import java.util.ArrayList;
import java.util.List;

public class GCMonitoringExample {
   
    public static void main(String[] args) {
   
        System.out.println("垃圾回收监控已启用,详细信息将记录到日志文件...");

        // 创建一个列表,用于模拟内存占用
        List<Object> list = new ArrayList<>();
        for (int i = 0; i < 10000; i++) {
   
            list.add(new Object());

            // 每1000个对象后进行一次清理,模拟内存释放
            if (i % 1000 == 0) {
   
                list.clear();
                System.gc(); // 手动请求垃圾回收
            }
        }
    }
}

此代码示例展示了如何通过创建对象并在特定时刻清理,以触发和监控垃圾回收过程。

示例9:配置和使用字符串去重功能

JVM启动参数:

java -XX:+UseStringDeduplication -XX:+PrintStringDeduplicationStatistics -jar YourApp.jar
  • -XX:+UseStringDeduplication:开启JVM的字符串去重功能。
  • -XX:+PrintStringDeduplicationStatistics:打印字符串去重的统计信息。

Java代码:

public class StringDeduplicationExample {
   
    public static void main(String[] args) {
   
        System.out.println("字符串去重功能已启用,相关统计信息将打印...");

        // 创建一个字符串列表
        List<String> stringList = new ArrayList<>();

        // 添加大量重复字符串,触发字符串去重
        for (int i = 0; i < 100000; i++) {
   
            stringList.add("Hello, JVM!"); // 添加重复的字符串
        }

        // 触发垃圾回收,以便观察字符串去重效果
        System.gc();
    }
}

此代码示例通过创建大量重复的字符串,并触发垃圾回收,来展示字符串去重功能的效果。

示例10:使用并行垃圾收集器

JVM启动参数:

java -XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:+PrintGCDetails -jar YourApp.jar
  • -XX:+UseParallelGC:使用并行垃圾收集器。
  • -XX:GCTimeRatio=4:设置吞吐量目标,表示99%的时间用于应用程序,1%的时间用于垃圾收集。
  • -XX:+PrintGCDetails:打印垃圾收集的详细信息。

Java代码:

public class ParallelGCMonitoring {
   
    public static void main(String[] args) {
   
        System.out.println("并行垃圾收集器已启用,GC详细信息正在打印...");
        // 这里模拟一些内存分配以触发GC
        List<byte[]> list = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
   
            list.add(new byte[1024 * 1024]); // 每次分配1MB的空间
        }
        // 清理引用,触发GC
        list.clear();
        System.gc(); // 建议执行垃圾收集
    }
}

这段代码用于演示并行垃圾收集器的使用,通过分配内存并清理来触发垃圾收集。

示例11:配置和使用String去重功能

JVM启动参数:

java -XX:+UseStringDeduplication -XX:+PrintStringDeduplicationStatistics -jar YourApp.jar
  • -XX:+UseStringDeduplication:开启JVM的字符串去重功能。
  • -XX:+PrintStringDeduplicationStatistics:打印字符串去重的统计信息。

Java代码:

public class StringDeduplicationExample {
   
    public static void main(String[] args) {
   
        System.out.println("字符串去重功能已启用,统计信息正在打印...");
        // 创建重复的字符串
        String repeatedString = "Hello, World!";
        List<String> stringList = new ArrayList<>();
        for (int i = 0; i < 10000; i++) {
   
            stringList.add(new String(repeatedString)); // 通过new创建新的字符串实例
        }
        // 建议执行垃圾收集来触发字符串去重
        System.gc();
    }
}

这段代码通过创建大量重复的字符串实例,演示了字符串去重功能的效果。

示例12:设置和监控ZGC垃圾收集器

JVM启动参数:

java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xlog:gc -jar YourApp.jar
  • -XX:+UnlockExperimentalVMOptions:解锁实验性VM选项。
  • -XX:+UseZGC:使用ZGC垃圾收集器。
  • -Xlog:gc:开启GC日志。

Java代码:

import java.util.concurrent.TimeUnit;

public class ZGCMonitoring {
   
    public static void main(String[] args) throws InterruptedException {
   
        System.out.println("ZGC垃圾收集器已启用,GC日志正在输出...");
        // 创建对象并模拟短暂的暂停,触发GC
        for (int i = 0; i < 100; i++) {
   
            byte[] allocation = new byte[10 * 1024 * 1024]; // 分配约10MB的空间
            TimeUnit.MILLISECONDS.sleep(100); // 暂停100毫秒
        }
    }
}

此代码示例演示了如何使用ZGC垃圾收集器,并通过分配内存和短暂暂停来触发垃圾收集。

结语

合理的JVM调优可以显著提升应用的性能和稳定性。不过,请记得调优是一个持续的过程,需要根据应用的具体表现来不断调整和优化。

本文已收录于,我的技术网站 ddkk.com,有大厂完整面经,工作技术,架构师成长之路,等经验分享

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
11天前
|
Arthas 监控 Java
JVM进阶调优系列(9)大厂面试官:内存溢出几种?能否现场演示一下?| 面试就那点事
本文介绍了JVM内存溢出(OOM)的四种类型:堆内存、栈内存、元数据区和直接内存溢出。每种类型通过示例代码演示了如何触发OOM,并分析了其原因。文章还提供了如何使用JVM命令工具(如jmap、jhat、GCeasy、Arthas等)分析和定位内存溢出问题的方法。最后,强调了合理设置JVM参数和及时回收内存的重要性。
|
9天前
|
监控 Java 编译器
Java虚拟机调优实战指南####
本文深入探讨了Java虚拟机(JVM)的调优策略,旨在帮助开发者和系统管理员通过具体、实用的技巧提升Java应用的性能与稳定性。不同于传统摘要的概括性描述,本文摘要将直接列出五大核心调优要点,为读者提供快速预览: 1. **初始堆内存设置**:合理配置-Xms和-Xmx参数,避免频繁的内存分配与回收。 2. **垃圾收集器选择**:根据应用特性选择合适的GC策略,如G1 GC、ZGC等。 3. **线程优化**:调整线程栈大小及并发线程数,平衡资源利用率与响应速度。 4. **JIT编译器优化**:利用-XX:CompileThreshold等参数优化即时编译性能。 5. **监控与诊断工
|
20天前
|
存储 监控 Java
JVM进阶调优系列(8)如何手把手,逐行教她看懂GC日志?| IT男的专属浪漫
本文介绍了如何通过JVM参数打印GC日志,并通过示例代码展示了频繁YGC和FGC的场景。文章首先讲解了常见的GC日志参数,如`-XX:+PrintGCDetails`、`-XX:+PrintGCDateStamps`等,然后通过具体的JVM参数和代码示例,模拟了不同内存分配情况下的GC行为。最后,详细解析了GC日志的内容,帮助读者理解GC的执行过程和GC处理机制。
|
28天前
|
Arthas 监控 数据可视化
JVM进阶调优系列(7)JVM调优监控必备命令、工具集合|实用干货
本文介绍了JVM调优监控命令及其应用,包括JDK自带工具如jps、jinfo、jstat、jstack、jmap、jhat等,以及第三方工具如Arthas、GCeasy、MAT、GCViewer等。通过这些工具,可以有效监控和优化JVM性能,解决内存泄漏、线程死锁等问题,提高系统稳定性。文章还提供了详细的命令示例和应用场景,帮助读者更好地理解和使用这些工具。
|
1月前
|
监控 架构师 Java
JVM进阶调优系列(6)一文详解JVM参数与大厂实战调优模板推荐
本文详述了JVM参数的分类及使用方法,包括标准参数、非标准参数和不稳定参数的定义及其应用场景。特别介绍了JVM调优中的关键参数,如堆内存、垃圾回收器和GC日志等配置,并提供了大厂生产环境中常用的调优模板,帮助开发者优化Java应用程序的性能。
|
1月前
|
存储 安全 Java
jvm 锁的 膨胀过程?锁内存怎么变化的
【10月更文挑战第3天】在Java虚拟机(JVM)中,`synchronized`关键字用于实现同步,确保多个线程在访问共享资源时的一致性和线程安全。JVM对`synchronized`进行了优化,以适应不同的竞争场景,这种优化主要体现在锁的膨胀过程,即从偏向锁到轻量级锁,再到重量级锁的转变。下面我们将详细介绍这一过程以及锁在内存中的变化。
37 4
|
9天前
|
Java Linux Windows
JVM内存
首先JVM内存限制于实际的最大物理内存,假设物理内存无限大的话,JVM内存的最大值跟操作系统有很大的关系。简单的说就32位处理器虽然可控内存空间有4GB,但是具体的操作系统会给一个限制,这个限制一般是2GB-3GB(一般来说Windows系统下为1.5G-2G,Linux系统下为2G-3G),而64bit以上的处理器就不会有限制。
8 1
|
1月前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
65 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
1月前
|
存储 缓存 算法
JVM核心知识点整理(内存模型),收藏再看!
JVM核心知识点整理(内存模型),收藏再看!
JVM核心知识点整理(内存模型),收藏再看!
|
28天前
|
存储 算法 Java
聊聊jvm的内存结构, 以及各种结构的作用
【10月更文挑战第27天】JVM(Java虚拟机)的内存结构主要包括程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区和运行时常量池。各部分协同工作,为Java程序提供高效稳定的内存管理和运行环境,确保程序的正常执行、数据存储和资源利用。
46 10