JVM之堆学习

发布时间:2023年12月19日

目录

一、Java虚拟机内存结构图

二、堆的介绍

三、一些示例

3.1 堆内存溢出

3.2 堆内存诊断工具

jps命令

jmap命令

jconsole命令

jvisualvm命令


一、Java虚拟机内存结构图

二、堆的介绍

1.?前面学习的程序计数器,虚拟机栈和本地方法栈都是线程私有的,堆是线程共享的;

2.?通过 new 关键字,创建的对象都会使用堆内存,其特点是:

  • 它是线程共享的,堆中对象都需要考虑线程安全的问题(虚拟机栈中的局部变量只要不逃离方法的作用范围就是线程安全的
  • 有垃圾回收机制

三、一些示例

3.1 堆内存溢出

1. 代码示例

package cn.itcast.jvm.t1.heap;

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

/**
 * 演示堆内存溢出 java.lang.OutOfMemoryError: Java heap space
 * -Xmx8m
 */
public class Demo1_5 {

    public static void main(String[] args) {
        int i = 0;
        try {
            List<String> list = new ArrayList<>();
            String a = "hahaha";
            while (true) {
                list.add(a); // hahaha, hahahahahaha, hahahahahahahahaha...
                a = a + a;
                i++;
            }
        } catch (Throwable e) {
            e.printStackTrace();
            System.out.println(i);
        }
    }
}

2. 报错信息?

3. 修改堆内存大小

?修改了堆内存大小后再次运行程序:

3.2 堆内存诊断工具

jps命令

?首先通过jps工具查看当前系统中有哪些Java进程,简单使用如下:

jps是 Java Virtual Machine Process Status Tool (Java虚拟机进程状态工具)的缩写,它是JDK提供的一个命令行工具,用于列出当前运行的Java进程信息。jps命令可以显示正在运行的Java进程的进程ID (PID)和主类名称等信息,对于查找和监控Java进程非常有用,特别是在需要与正在运行的Java应用程序进行交互或诊断时,常见的jsp命令选项如下:

(1)jps: 显示系统中的Java进程号和主类名称(不包括主类的包名),如下:

(2)jps -q : 只输出进程ID,而不显示主类名称,如下:

(3)jps -l : 显示完整的主类名称或jar文件名称(如果是通过java -jar 命令进行启动一个项目),如下:

? ? ? ? (3.1)直接启动的java程序或项目(不是通过java -jar 的形式启动的),显示如下:

? ? ? ? (3.2)通过java -jar的方式启动的java服务,如下图显示的是jar包的文件名称:

(4)jps -v?: 可以显示虚拟机启动时的JVM参数,如下:

? ? ? ? (4.1)启动一个通过SpringBoot项目打包的jar,如下:

? ? ? ? (4.2)通过 jps -v 命令查看虚拟机启动参数:如下:

(5)jps -m:?显示虚拟机进程启动时传递给主类 main() 函数的参数,示例如下

? ? ? ? (5.1)一个简单的java程序如下:

package jvm_jps;

public class Test_1 {

    public static void main(String[] args) throws InterruptedException {
        for (String arg : args) {
            System.out.println(arg);
        }
        Thread.sleep(10000000L);
    }
}

? ? ? ? ?(5.2)通过命令行启动这个java程序,如下图所示:

? ? ? ? ?(5.3)然后使用 jps -l -m 查看,如下图:

? ? ? ? (5.4)也可以在启动上述java程序时,指定虚拟机参数,如设置堆内存大小,如下图:

? ? ? ?(5.5) 然后使用 jps -l -v 命令查看启动虚拟机时,传递给虚拟机的参数,如下图:

? ? ? ? ?(5.6)也可以 jsp -l -m -v 一起使用,同时查看传递给main函数的参数和传递给虚拟机的参数,如下图:

jmap命令

????????通过上述的jps命令得到Java进程号后(PID),可以通过jmap工具查看某个java进程的堆内存的使用情况。【jmap -heap pid就可查看某一个java进程的堆内存使用情况】

????????注意:jmap只能查询某个时刻堆内存的占用情况,如果想对堆内存做一个连续的监测,需要使用jconsole或jvirsualvm工具。

jconsole命令

控制台输入 jconsole命令,双击你要连接的Java进程,选择不安全的连接,进入界面,如下:

jvisualvm命令

控制台输入jvisualvm命令,如下图所示:

目前只是针对这些工具进行了简要的介绍和使用

3.3 案例:垃圾回收后,内存依然占用很高

场景:

运行一个程序后,通过jps命令查看有哪些java进程,如下图:

使用jmap -heap java进程id 查看当前java进程的堆内存使用情况,如下图:

使用 jconsole工具调出图形化工具进行查看,如下图:

再次使用 jmap -heap 查看此java进程对应的堆内存占用情况,发现老年代占用的堆内存并没有下降,如下图:

此时,就需要另一个工具进行排查,jvisualvm工具,此工具打开的图形化界面可以继续针对上述问题进行排查,如下图:

?分析上面dump出来的堆内存信息,如下图:

?

查看源代码,如下图:
?

文章来源:https://blog.csdn.net/qq_23388169/article/details/135006415
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。