jvm调优工具

jvm常用参数与命令

  • 常用jvm参数
-Xms20M       设置初始 Java 堆大小
-Xmx20M       设置最大 Java 堆大小
-XX:MaxDirectMemorySize=20M  设置堆外内存大小
-XX:MetaspaceSize=20m        设置初始元空间大小
-XX:MaxMetaspaceSize=20m     设置最大元空间大小
  • jps命令
jps     查看所有jvm进程 (进程id 主类名)
jps -l  显示全类名
jps -v  显示jvm启动参数
jps -m  显示传递给main函数的参数
  • jinfo id 实时查看虚拟机各项参数
  • jmap命令 用于内存分析
jmap -dump:format=b,file=filename  进程id      将内存使用情况dump到文件中
jmap -heap 进程id  查看进程中堆内存的详细使用情况
  • jstack命令 用户线程分析
jstack 进程id          输出当前jvm进程中每一个线程的执行方法的堆栈集合。

使用jmap查看堆内存信息

  • jmap -heap 进程id 就会将当前Java进程中堆内存信息打印出来
  • 堆内存配置信息如下,包含了堆内存空间大小,新生代,年老代内存大小等信息。
Heap Configuration:
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 8388608 (8.0MB)
   NewSize                  = 2621440 (2.5MB)
   MaxNewSize               = 2621440 (2.5MB)
   OldSize                  = 5767168 (5.5MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)
  • 堆内存使用信息如下,包含每个区域使用情况,剩余空间,使用率等。
Heap Usage:
PS Young Generation
Eden Space:
   capacity = 1572864 (1.5MB) //eden区大小
   used     = 1339624 (1.2775650024414062MB) //eden区使用内存
   free     = 233240 (0.22243499755859375MB) //eden区剩余内存
   85.17100016276042% used //eden区使用率
From Space: //两个survivor区使用情况
   capacity = 524288 (0.5MB)
   used     = 520240 (0.4961395263671875MB)
   free     = 4048 (0.0038604736328125MB)
   99.2279052734375% used
To Space:
   capacity = 524288 (0.5MB)
   used     = 0 (0.0MB)
   free     = 524288 (0.5MB)
   0.0% used
PS Old Generation //年老代使用情况
   capacity = 5767168 (5.5MB)
   used     = 3761512 (3.5872573852539062MB)
   free     = 2005656 (1.9127426147460938MB)
   65.22286155007102% used
4790 interned Strings occupying 378432 bytes.

使用jmap检测堆内存溢出问题

  • 如下代码会产生堆内存溢出问题
//设置堆内存大小为8m  -Xmx8m
public class Test {
    public static Logger log = LoggerFactory.getLogger(Test.class);
    public static void main(String[] args) throws InterruptedException {
        LinkedList<String> list = new LinkedList<>();
        String str = "hello";
        int i = 0;
        while(true){
            System.out.println(i);
            str = str + str;
            i++;
            list.add(str);
            Thread.sleep(2000);
        }
    }
}
  • 首先使用jps查看当前程序进程id
  • 然后使用jmap id 就可以查看进程当前时刻的堆内存使用情况。如下可以发现新生代 老年代内存占有率都很高,已经达到濒临溢出。
Heap Configuration:
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 8388608 (8.0MB)
   NewSize                  = 2621440 (2.5MB)
   MaxNewSize               = 2621440 (2.5MB)
   OldSize                  = 5767168 (5.5MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
PS Young Generation
Eden Space:
   capacity = 1572864 (1.5MB)
   used     = 1339624 (1.2775650024414062MB)
   free     = 233240 (0.22243499755859375MB)
   85.17100016276042% used
From Space:
   capacity = 524288 (0.5MB)
   used     = 520240 (0.4961395263671875MB)
   free     = 4048 (0.0038604736328125MB)
   99.2279052734375% used
To Space:
   capacity = 524288 (0.5MB)
   used     = 0 (0.0MB)
   free     = 524288 (0.5MB)
   0.0% used
PS Old Generation
   capacity = 5767168 (5.5MB)
   used     = 3761512 (3.5872573852539062MB)
   free     = 2005656 (1.9127426147460938MB)
   65.22286155007102% used
4790 interned Strings occupying 378432 bytes.

jstack

  • 使用jstack检测线程死锁问题。
  • 运行如下代码
public class Test {
    static Object a = new Object();
    static Object b = new Object();
    public static Logger log = LoggerFactory.getLogger(Test.class);
    public static void main(String[] args) throws InterruptedException {
        new Thread(()->{
            synchronized (a){
                sleep(1000);
                synchronized (b){
                }
            }
        },"t1").start();
        new Thread(()->{
            synchronized (b){
                sleep(1000);
                synchronized (a){
                }
            }
        },"t2").start();
    }
    public static void sleep(int n)  {
        try {
            Thread.sleep(n);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
  • 使用jps查看当前运行程序的进程id
  • 然后使用 jstack 进程id 就可以打印当前jvm进程中的线程信息
  • 通过如下信息就可以判断出是t1线程和t2线程出现死锁。
Found one Java-level deadlock:
=============================
"t2":
  waiting to lock monitor 0x000000001c940ee8 (object 0x000000076ba1d9c0, a java.lang.Object),
  which is held by "t1"
"t1":
  waiting to lock monitor 0x000000001c9431f8 (object 0x000000076ba1d9d0, a java.lang.Object),
  which is held by "t2"

Java stack information for the threads listed above:
===================================================
"t2":
        at Test.lambda$main$1(Test.java:31)
        - waiting to lock <0x000000076ba1d9c0> (a java.lang.Object)
        - locked <0x000000076ba1d9d0> (a java.lang.Object)
        at Test$$Lambda$2/2094777811.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:748)
"t1":
        at Test.lambda$main$0(Test.java:21)
        - waiting to lock <0x000000076ba1d9d0> (a java.lang.Object)
        - locked <0x000000076ba1d9c0> (a java.lang.Object)
        at Test$$Lambda$1/1879492184.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:748)

Found 1 deadlock.

jconsole工具

  • jconsole工具可以实时查看一个jvm进程的内存 cpu 类加载 线程等信息。

  • 使用jconsole检测内存溢出问题

  • 在电脑左下角输入jconsole找到相关程序运行,然后连接到本地指定jvm进程,点击内存界面,然后就可以实时查看到该进程内存使用情况,如下可以发现内存使用不断攀升最终溢出。
    在这里插入图片描述

  • jconsole工具来检测线程死锁问题。

  • 在电脑左下角输入jconsole找到相关程序运行,然后连接到本地指定jvm进程,点击线程界面就可以对线程信息进行调试。
    在这里插入图片描述

  • 点击检测死锁就可以查看到当前程序是否发生死锁。
    在这里插入图片描述

jvisualVM工具

  • 相比于jconsole工具,jvisualVM工具除了实时查看jvm进程中内存 线程 cpu等信息外,还可以对当前内存 线程使用情况进行快照,然后进行详细分析。

  • 输入jvisualvm命令 回车,然后连接指定进程。

  • 在监视界面点击堆dump就可以对当前堆内存进行快照。
    在这里插入图片描述

  • 可以查看每个类的实例数和占用内存情况
    在这里插入图片描述

  • 然后可以点击查找前20最大对象,对占用内存最大的几个对象中字段进行详细分析。
    在这里插入图片描述

  • 还可以点击线程 dump 分析线程快照信息
    在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值