热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

JVM参数设置与命令行工具详解

JVM参数配置与命令行工具的深入解析旨在优化系统性能,通过合理设置JVM参数,确保在高吞吐量的前提下,有效减少垃圾回收(GC)的频率,进而降低系统停顿时间,提升服务的稳定性和响应速度。此外,本文还将详细介绍常用的JVM命令行工具,帮助开发者更好地监控和调优JVM运行状态。

JVM参数配置

大致方向:JVM调优的目的是保证在一定吞吐量的情况下尽可能的减少GC次数,从而减少系统停顿时间,提高服务质量和效率。


其中减少GC次数的原则:

  • 将新生代转换成老年代的数量降至最少(及时进行Minor GC回收新生代)
  • 减少Full GC 次数


常用参数

  • -XX:+PrintGCDetails:打印GC的详细信息(冒号之后的+表示打印,-表示不打印)

  • -XX:+UseSerialGC : 使用串行回收器

  • -Xmx4000m :指定堆最大值为4000M( 等价于-XX:MaxHeapSize)。默认物理内存的1/4

  • -Xms4000m :指定堆初始化值为4000M( 等价于-XX:initialHeapSize)。默认物理内存的1/64

  • -Xmn2000m :设置新生代大小为2000M。

  • -Xss512k:设置栈大小为512k


设置堆内存大小

  • -Xmx :指定堆最大值。默认物理内存的1/4
  • -Xms :指定堆初始化值。默认物理内存的1/64


推荐:通常会将 -Xmx 与 -Xms两个参数配置成相同的值


public class Main {

    /**
     *堆内存大小配置
     * -Xmx4000m  设置最大堆内存为4000m
     * -Xms4000m  设置初始化堆内存为4000m
     * @param args
     */
    public static void main(String[] args) {


        System.out.println("堆最大内存:"+Runtime.getRuntime().maxMemory()/1024/1024);

        System.out.println("可用内存:"+Runtime.getRuntime().freeMemory()/1024/1024);
        System.out.println("内存总量:"+Runtime.getRuntime().totalMemory()/1024/1024);
        }
}


设置栈大小

-Xss

  • 设置单个线程栈的大小,一般默认为 512-1024k
  • 等价于 -XX:ThreadStackSize

设置新生代大小

-Xmn :设置年轻代大小。

整个JVM内存大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。

  • 此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。


设置元空间大小

元空间的本质和永久代类似,都是对 JVM 规范中的方法区的实现。

不过元空间于永久代之间最大区别在于,元空间并不在虚拟中,而是使用本地内存,因此默认情况下,元空间的大小仅受本地内存限制。

  • 元空间的默认大小在20m左右,通常会调大一点。

-XX:MetaspaceDetails=1024m


新生代比例大小配置

-XX:SurvivorRatio=8 eden:from:to = 8:1:1 (default)

-XX:SurvivorRatio=2 eden:from:to = 2:1:1

public class Main {

    /**
     * 新生代比例大小配置
     * -Xms20m -Xmx20m -Xmn1m -XX:SurvivorRatio=2 -XX:+PrintGCDetails -XX:+UseSerialGC
     * -Xmn1m  新生代最大可用值
     * 
     *
     *
     * @param args
     */
    public static void main(String[] args) {


        byte[] b = null;
        for (int i = 0; i <10; i++) {
            b = new byte[1 * 1024 * 1024];
        }
        }
}


新生代和老年代比例配置

-XX:NewRatio=2 新生代和老年代的占比为1:2 (default)

public class Main {

    /**
     * 新生代与老年代比例大小配置
     *
     * -XX:NewRatio=2  新生代和老年代的占比为1:2
     *
     * @param args
     */
    public static void main(String[] args) {


        byte[] b = null;
        for (int i = 0; i <10; i++) {
            b = new byte[1 * 1024 * 1024];
        }
        }
}

设置垃圾的最大年龄

-XX:MaxTenuringThreshold=15(default)

新生代对象经过15次的回收就会进入老年代


小结

-Xmx4000m 
-Xms4000m 
-Xss1024k 
-XX:MetaspaceSize=1024m 
-XX:+PrintCommandLineFlags 
-XX:+PrintGCDetails
//使用默认
-Xmn
-XX:SurvivorRatio
-XX:NewRatio
-XX:MaxTenuringThreshold

堆内存溢出问题

当程序需要申请内存的时候,由于没有足够的内存,此时就会抛出OutOfMemoryError,这就是内存溢出


堆是存放对象的地方,那么只要在堆中疯狂的创建对象,那么堆就会发生内存溢出。

public class Main {

    /**
     *-Xms1m -Xmx1m   -XX:+PrintGCDetails 
     */
    public static void main(String[] args) {

        for (int i=0;i<100;i++)
        {
            Byte[] bytes = new Byte[1 * 1024 * 1024];  ///1M = 1024K = 1024*1024 字节
        }
    }
}


  • 增大堆内存

    -Xms100m -Xmx100m


栈溢出

通常产生于递归调用

public class Main {

    /**
     *   -Xss10m
     */
    private static int count;

    public static void count()
    {

//          count++;
//          count();

        try
        {
            count++;
            count();
        }
        catch (Throwable throwable)
        {
            System.out.println("最大深度:"+count);
        }

    }
    public static void main(String[] args) {
        count();



    }
}


内存溢出和内存泄漏


内存溢出发生在申请堆内存空间时,内存不够用了。

比如你需要100M的空间,系统只剩90M了,这就叫内存溢出


内存泄漏是指创建一些对象,比如说IO流,数据库连接未关闭导致内存的持续占用,致使本该回收的内存空间依然被占用。而内存泄漏多了之后,就会导致内存溢出。


JVM命令工具

JVM常用命令


jps:JVM Process Status Tool 虚拟机进程状况工具

jps -l   输出主类全名,如果是Jar包,输出Jar包路径
-l : 输出主类全名或jar路径
-q : 只输出LVMID
-m : 输出JVM启动时传递给main()的参数
-v : 输出JVM启动时显示指定的JVM参数

技术图片

jinfo:查看虚拟机各项参数

jps -l   //获取LVMID

//查看打印GC日志的参数

jinfo -flag PrintGCDetails 12368

-XX:-PrintGCDetails

// 冒号后面的-表示未开启GC日志打印,+代表打印

技术图片

查看MetaspaceSize初始值

技术图片

  • -flag : 输出指定args参数的值
  • -flags : 不需要args参数,输出所有JVM参数的值
  • -sysprops : 输出系统属性,等同于System.getProperties()

jstat:监视虚拟机运行时状态信息的命令

? 可以显示出虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据


? 命令格式

jstat [option] LVMID [interval] [count]
  • [option] : 操作参数
  • LVMID : 本地虚拟机进程ID
  • [interval] : 连续输出的时间间隔
  • [count] : 连续输出的次数
参数 含义
-class 监视类装载、卸载数量、总空间以及类装载所耗费的时间
-gc 监视Java堆状况,包括Eden区、两个Survivor区、老年代、永久代等的容量、已用空间、GC时间合计等信息
-gccapacity 监视内容与-gc基本相同,但输出主要关注Java堆各个区域使用到的最大、最小空间
-gcutil 监视内容与-gc基本相同,但输出主要关注已使用空间占总空间的百分比
-gccause 与-gcutil功能一样,但是会额外输出导致上一次GC产生的原因
-gcnew 监视新生代GC状况
-gcnewcapacity 监视内容与-gcnew基本相同,输出主要关注使用到的最大、最小空间
-gcold 监视老年代GC状况
-gcoldcapacity 监视内容与-gcold基本相同,输出主要关注使用到的最大、最小空间
-gcpermcapacity 输出永久代使用到的最大、最小空间
-compiler 输出JIT编译器编译过的方法、耗时信息
-printcompilation 输出已经被JIT编译的方法


-class

监视类装载、卸载数量、总空间以及耗费的时间

jstat -class 10524   

Loaded  Bytes  Unloaded  Bytes     Time
   610  1231.7        0     0.0       0.42
   
   
Loaded : 加载class的数量
Bytes : class字节大小
Unloaded : 未加载class的数量
Bytes : 未加载class的字节大小
Time : 加载时间
-----------------------------------------------------------------------------------

jstat -class 12036 1000 5  表示每1000毫秒查询一次,一共查询5次


C:\Users\Administrator>jstat -class 12036 1000 5
Loaded  Bytes  Unloaded  Bytes     Time
  3252  3765.3        0     0.0       2.60
  3252  3765.3        0     0.0       2.60
  3252  3765.3        0     0.0       2.60
  3252  3765.3        0     0.0       2.60
  3252  3765.3        0     0.0       2.60


  • -gc

垃圾回收堆的行为统计

jstat -gc 12036

技术图片

C即Capacity 总容量,U即Used 已使用的容量

  • S0C : survivor0区的总容量
  • S1C : survivor1区的总容量
  • S0U : survivor0区已使用的容量
  • S1U : survivor1区已使用的容量
  • EC : Eden区的总容量
  • EU : Eden区已使用的容量
  • OC : Old区的总容量
  • OU : Old区已使用的容量
  • PC 当前perm的容量 (KB)
  • PU perm的使用 (KB)
  • YGC : 新生代垃圾回收次数
  • YGCT : 新生代垃圾回收时间
  • FGC : 老年代垃圾回收次数
  • FGCT : 老年代垃圾回收时间
  • GCT : 垃圾回收总消耗时间


  • -gccapacity

同-gc,不过还会输出Java堆各区域使用到的最大、最小空间

jstat  -gccapacity 12036

技术图片

  • NGCMN : 新生代占用的最小空间
  • NGCMX : 新生代占用的最大空间
  • OGCMN : 老年代占用的最小空间
  • OGCMX : 老年代占用的最大空间
  • OGC:当前年老代的容量 (KB)
  • OC:当前年老代的空间 (KB)
  • PGCMN : perm占用的最小空间
  • PGCMX : perm占用的最大空间


  • -gcutil

同-gc,不过输出的是已使用空间占总空间的百分比

jstat -gcutil 12036

  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
 55.54   0.00   4.79  52.70      -      -     50    0.823     6    0.068    0.891


  • -gccause

垃圾收集统计概述(同-gcutil),附加最近两次垃圾回收事件的原因

jstat  -gccause 12036

S0 S1 E O M CCS YGC YGCT FGC FGCT GCT LGCC GCC
55.54 0.00 7.99 52.70 - - 50 0.823 6 0.068 0.891 Allocation Failure No GC

  • LGCC:最近垃圾回收的原因
  • GCC:当前垃圾回收的原因


  • -gcnew

统计新生代的行为

C:\Users\Administrator>jstat -gcnew 12036

 S0C    S1C    S0U    S1U   TT MTT  DSS      EC       EU     YGC     YGCT
13056.0 13056.0 7251.9    0.0  1   6 6528.0 104960.0  19574.8     50    0.823
  • TT:Tenuring threshold(提升阈值)
  • MTT:最大的tenuring threshold
  • DSS:survivor区域大小 (KB)


  • -gcnewcapacity

新生代与其相应的内存空间的统计

C:\Users\Administrator>jstat -gcnewcapacity 12036

NGCMN NGCMX NGC S0CMX S0C S1CMX S1C ECMX EC YGC FGC
131072.0 131072.0 131072.0 13056.0 13056.0 13056.0 13056.0 104960.0 104960.0 50 6

  • NGC:当前年轻代的容量 (KB)
  • S0CMX:最大的S0空间 (KB)
  • S0C:当前S0空间 (KB)
  • ECMX:最大eden空间 (KB)
  • EC:当前eden空间 (KB)


  • -gcold

监视老年代的GC状况

C:\Users\Administrator>jstat -gcold 12036

MC MU CCSC CCSU OC OU YGC FGC FGCT GCT

   -        -        -        -    131072.0     69073.6     50     6    0.068    0.891


  • -gcoldcapacity

统计老年代的大小和空间

C:\Users\Administrator>jstat -gcoldcapacity 12036
   OGCMN       OGCMX        OGC         OC       YGC   FGC    FGCT     GCT
   131072.0    655360.0    131072.0    131072.0    50     6    0.068    0.891


  • -printcompilation

输出已经被JIT编译的方法

C:\Users\Administrator>jstat -printcompilation 12036
Compiled  Size  Type Method
    2537     30    1 java/io/ExpiringCache$1 removeEldestEntry
  • Compiled:被执行的编译任务的数量
  • Size:方法字节码的字节数
  • Type:编译类型
  • Method:编译方法的类名和方法名。类名使用”/” 代替 “.” 作为空间分隔符. 方法名是给出类的方法名. 格式是一致于HotSpot - XX:+PrintComplation 选项



jmap:生成堆转储快照

jmap -dump:live,format=b,file=dump.hprof 12233

format指定输出格式,live指明是活着的对象,file指定文件名


-heap

打印heap的概要信息,GC使用的算法,heap的配置及wise heap的使用情况,可以用此来判断内存目前的使用情况以及垃圾回收情况

jmap -heap 28920


jhat: 分析jmap生成的dump

jhat内置了一个微型的HTTP/HTML服务器,生成dump的分析结果后,可以在浏览器中查看。在此要注意,一般不会直接在服务器上进行分析,因为jhat是一个耗时并且耗费硬件资源的过程,一般把服务器生成的dump文件复制到本地或其他机器上进行分析。


jstack: 用于生成java虚拟机当前时刻的线程快照

线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。

线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做什么事情,或者等待什么资源。

如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题。

另外,jstack工具还可以附属到正在运行的java程序中,看到当时运行的java程序的java stack和native stack的信息, 如果现在运行的java程序呈现hung的状态,jstack是非常有用的。

  • -F : 当正常输出请求不被响应时,强制输出线程堆栈
  • -l : 除堆栈外,显示关于锁的附加信息
  • -m : 如果调用到本地方法的话,可以显示C/C++的堆栈
jstack -F 12233


JVM可视化工具

位于JDK的bin目录下

JConsole

jconsole

技术图片

VisualVM

jvisualvm

技术图片

技术图片

JVM参数配置&&命令工具


推荐阅读
  • 本文介绍了实现链表数据结构的方法与技巧,通过定义一个 `MyLinkedList` 类来管理链表节点。该类包含三个主要属性:`first` 用于指向链表的第一个节点,`last` 用于指向链表的最后一个节点,以及 `size` 用于记录链表中节点的数量。此外,还详细探讨了如何通过这些属性高效地进行链表的操作,如插入、删除和查找等。 ... [详细]
  • 在 Linux 系统中,`/proc` 目录实现了一种特殊的文件系统,称为 proc 文件系统。与传统的文件系统不同,proc 文件系统主要用于提供内核和进程信息的动态视图,通过文件和目录的形式呈现。这些信息包括系统状态、进程细节以及各种内核参数,为系统管理员和开发者提供了强大的诊断和调试工具。此外,proc 文件系统还支持实时读取和修改某些内核参数,增强了系统的灵活性和可配置性。 ... [详细]
  • 在Spring框架中,基于Schema的异常通知与环绕通知的实现方法具有重要的实践价值。首先,对于异常通知,需要创建一个实现ThrowsAdvice接口的通知类。尽管ThrowsAdvice接口本身不包含任何方法,但开发者需自定义方法来处理异常情况。此外,环绕通知则通过实现MethodInterceptor接口来实现,允许在方法调用前后执行特定逻辑,从而增强功能或进行必要的控制。这两种通知机制的结合使用,能够有效提升应用程序的健壮性和灵活性。 ... [详细]
  • POJ 1696: 空间蚂蚁算法优化与分析
    针对 POJ 1696 的空间蚂蚁算法进行了深入的优化与分析。本研究通过改进算法的时间复杂度和空间复杂度,显著提升了算法的效率。实验结果表明,优化后的算法在处理大规模数据时表现优异,能够有效减少计算时间和内存消耗。此外,我们还对算法的收敛性和稳定性进行了详细探讨,为实际应用提供了可靠的理论支持。 ... [详细]
  • 深入解析 iOS Objective-C 中的对象内存对齐规则及其优化策略
    深入解析 iOS Objective-C 中的对象内存对齐规则及其优化策略 ... [详细]
  • 高效排序算法是提升数据处理速度的重要技术。通过优化排序算法,可以显著提高数据处理的效率和性能。本文介绍了几种常见的高效排序算法,如快速排序、归并排序和堆排序,并通过实例代码展示了它们的具体实现。实验结果表明,这些算法在大规模数据集上的表现尤为突出,能够有效减少数据处理时间,提升系统整体性能。 ... [详细]
  • 在 Codeforces Global Round 3 的 B 题 "Inherent Talent" 中,主人公潇洒哥需要从 A 地前往 C 地,但两地之间没有直飞航班。他可以选择在 A 地和 B 地之间的中转航班,以便尽快抵达目的地 C。该问题的核心在于如何合理安排中转,以实现最短的旅行时间。 ... [详细]
  • 题目描述:小K不幸被LL邪教洗脑,洗脑程度之深使他决定彻底脱离这个邪教。在最终离开前,他计划再进行一次亚瑟王游戏。作为最后一战,他希望这次游戏能够尽善尽美。众所周知,亚瑟王游戏的结果很大程度上取决于运气,但通过合理的策略和算法优化,可以提高获胜的概率。本文将详细解析洛谷P3239 [HNOI2015] 亚瑟王问题,并提供具体的算法实现方法,帮助读者更好地理解和应用相关技术。 ... [详细]
  • 本文详细介绍了 MiniGUI 中静态控件(CTRL_STATIC)的使用方法及其不同风格的应用。具体而言,采用 SS_SIMPLE 风格的静态控件仅支持单行文本显示,不具备自动换行功能,且文本始终为左对齐。而 SS_LEFT、SS_CENTER 和 SS_RIGHT 风格则分别实现了文本的左对齐、居中和右对齐布局,提供了更多的排版灵活性。此外,文章还探讨了这些控件在实际开发中的应用场景和最佳实践。 ... [详细]
  • Go语言中的高效排序与搜索算法解析
    在探讨Go语言中高效的排序与搜索算法时,本文深入分析了Go语言提供的内置排序功能及其优化策略。通过实例代码,详细讲解了如何利用Go语言的标准库实现快速、高效的排序和搜索操作,为开发者提供了实用的编程指导。 ... [详细]
  • 题目旨在解决树上的路径最优化问题,具体为在给定的树中寻找一条长度介于L到R之间的路径,使该路径上的边权平均值最大化。通过点分治策略,可以有效地处理此类问题。若无长度限制,可采用01分数规划模型,将所有边权减去一个常数m,从而简化计算过程。此外,利用单调队列优化动态规划过程,进一步提高算法效率。 ... [详细]
  • 深入解析 Spring MVC 的核心原理与应用实践
    本文将详细探讨Spring MVC的核心原理及其实际应用,首先从配置web.xml文件入手,解析其在初始化过程中的关键作用,接着深入分析请求处理流程,包括控制器、视图解析器等组件的工作机制,并结合具体案例,展示如何高效利用Spring MVC进行开发,为读者提供全面的技术指导。 ... [详细]
  • 在C#和ASP.NET开发中,TypeParse 是一个非常实用的类型解析扩展方法库,提供了简便的类型转换功能。例如,通过 `var int1 = "12".TryToInt();` 可以将字符串安全地转换为整数,如果转换失败则返回0。此外,还支持更多复杂的类型转换场景,如 `var int2 = "22x".TryToInt();` 和 `var int3 = "3.14".TryToInt();`,确保了代码的健壮性和易用性。 ... [详细]
  • 在C#编程中,管理和操作Windows事件日志是一项重要技能。本文详细探讨了如何注册新的事件源,并通过示例代码展示了如何在应用程序中实现这一功能。具体而言,文章介绍了通过检查事件源是否存在,若不存在则进行注册的步骤,以及如何利用`EventLog`类来记录日志消息。此外,还提供了关于事件日志配置和最佳实践的深入分析,帮助开发者更好地理解和应用这一技术。 ... [详细]
  • Django框架下的对象关系映射(ORM)详解
    在Django框架中,对象关系映射(ORM)技术是解决面向对象编程与关系型数据库之间不兼容问题的关键工具。通过将数据库表结构映射到Python类,ORM使得开发者能够以面向对象的方式操作数据库,从而简化了数据访问和管理的复杂性。这种技术不仅提高了代码的可读性和可维护性,还增强了应用程序的灵活性和扩展性。 ... [详细]
author-avatar
干杯13ds_198
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有