首页 > 系统相关 >java脚本模拟服务器内存溢出实战&服务器部署java项目

java脚本模拟服务器内存溢出实战&服务器部署java项目

时间:2023-08-20 21:46:29浏览次数:90  
标签:java jar 线程 内存 服务器 jmap

一、背景:

使用java spring boot ,实现linux 服务器 内存溢出情况。

二、方案

1、打包成war包,可以直接将war包部署在tomcat容器里

2、spring boot,打包成jar包。打的jar包,内置了tomcat,所以在服务器上,直接启jar包就行,没有必要放在tomcat容器里部署,在启动jar包时,可以配置线程池等。

这里用 spring boot,打包成jar。

2.1 、新建 项目
java 选择8

 勾选spring web

 Spring boot 版本 <version>2.7.14</version>

 2.2 编写项目

OOMController.java
package com.example.testoom;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@RestController
public class OOMController {
    @GetMapping("/memoryLeak")
    public String memoryLeak() {
        // 是否调用remove方法
        boolean doRemove = false;
        // 加锁,让多个线程串行执行,避免多个线程同时占用内存导致的内存溢出问题
        final Object lockObj = new Object();
        // 开启20个线程
        ExecutorService executorService = Executors.newFixedThreadPool(20);
        // 为了不重复使用线程,用Map标记一下已经已使用过的线程,
        Map<Long, Integer> threadIdMap = new ConcurrentHashMap<>();
        // 循环向线程变量中设置数据 1024 * 1024 = 1M
        for (int i = 0; i < 20; i++) {
            executorService.execute(() -> {
                synchronized (lockObj) {
                    Integer num = threadIdMap.putIfAbsent(Thread.currentThread().getId(), 1);
                    if (num == null) {
                        ThreadLocal<Byte[]> threadLocal = new ThreadLocal<>();
                        threadLocal.set(new Byte[1024 * 1024]);
                        // 手工回收
                        System.gc();
                        try {
                            // 调用GC后不一定会马上回收
                            Thread.sleep(500);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }

                    System.out.println(Thread.currentThread().getName());

                }

            }

            );
        }
        // 线程池中的任务全部执行完毕
        executorService.shutdown();
        return "ok";

    }

}

 配置端口号,8083

application.properties

spring.mvc.view.prefix=classpath:/templates/  
spring.mvc.view.suffix=.html  
server.port=8083  

 2.3 打jar包

 (如果之前,大过,要先cleam清理一下)

jar包在target目录下

2.4 部署服务在服务器启动该jar包
1、先将jar包上传到服务器。

2、启动jar包

参数解释

nohup 表示不挂断的运行, 注意并没有后台运行的功能,用 nohup 命令可以使命令永久的执行, 和客户端没有任何关系

& 表示是后台运行

-Xms20M -Xmx20M -Xmn10M

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./heapdump.hprof 表示为了发生OOM的时候会自动导出Dump文件

java -jar -Xms300M -Xmx300M -Xmn100M testOOM-0.0.1-SNAPSHOT.jar -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./heapdump.hprof &

3 请求接口

部署之后请求一下接口:  http://192.168.1.3:8083/memoryLeak

 三、使用jmeter压这个接口

加大线程对接口进行压测,通过jmap或Arthas监控项目运行过程中(cpu、内存、磁盘)等关键信息

四、案例分析

分析思路1:

1、jmap 常用参数:

jmap命令进行堆转储(heap dump)时,如果 Java 进程遇到内存溢出(OutOfMemoryError),jmap命令会自动停止并输出堆转储文件。

jmap -histo:pid:打印指定 Java 进程(pid)的内存使用情况摘要。
jmap heap pid:打印指定 Java 进程(pid)的堆(heap)信息。
jmap -dump:format=b,file=output.dump:生成堆转储快照(dump 文件),并指定文件格式(b 表示二进制输出)。
jmap -finalize:查看 finalize 执行队列,即等待垃圾回收的线程。 

 获取当前进程id

存储dump堆文件:

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

 从项目运行日志关键字:java.lang.OutOfMemoryError: Java heap space,当前项目出现了内存泄露的情况

 2、使用 jstat -gcutil 线程ID 9557 查看

结果排查, FGC比较频繁,多半是有问题

分析思路2:

Arthas定位分析

java -jar arthas-boot.jar 9557

 1、输入  dashboard  查看线程整体的运行情况,heap的消耗情况,以及运行时环境

 

2、 输入 heapdump命令 将 hprof 文件下载下来,通过mat工具进行分析

 mat工具直接加载hprof文件

 点击Histogram,列出内存中的对象,对象的个数及大小

发现出问题的对象为 class java.lang.Byte[]

1)Byte[] 占用了空间的 90%以上,基本可以断定为是 Byte[] 没有被回收导致的内存泄漏

2)点击【overview】页签下方的leaksuspects,打开leaksuspects页签,自动分析内存内存泄漏的原因,可以直接定位到Class和行数;

 

参考笔记:

https://www.cnblogs.com/wzl0916/p/12928704.html

https://blog.csdn.net/bookssea/article/details/124073742

https://blog.csdn.net/huangliangbao2009/article/details/129785174

  

 

标签:java,jar,线程,内存,服务器,jmap
From: https://www.cnblogs.com/xfbk/p/17639215.html

相关文章

  • Cause: java.sql.SQLException: Field 'id' doesn't have a default value Field 'id&
    报错内容: 是因为实体类文件中设置主键自增的类型不对导致的,建议再温习一下逐渐自增的类型以及使用方式我自己的实体类里面设置的IdType为auto,但是主键id是char类型的,还不是int数值类型,所以无法设置为自增 这里需要换成IdType.ID_WORKER_STR@ApiModelProperty(......
  • 探索Java中的并发编程:多线程同步与性能优化
    在后端开发领域,Java作为一门强大的编程语言,广泛应用于构建高性能和并发性能强大的应用程序。本文将深入探讨Java中的并发编程,重点关注多线程同步机制与性能优化策略。通过结合实际代码示例,为读者提供关于并发编程的深奥知识和实用方法。1.并发编程概述与原理并发编程是指多个线程......
  • java.lang.NoSuchMethodError: com.baomidou.mybatisplus.core.toolkit.StringUtils.i
    在运行springboot项目的时候爆java.lang.NoSuchMethodError:com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotBlank(Ljava/lang/CharSequence;)Z错误错误如下11:49:08.390[restartedMain]DEBUGorg.springframework.boot.context.logging.ClasspathLoggingApplica......
  • Linux服务器的性能监控与分析
    通过vmstat分析性能 如上图所示,我们在命令vmstat后面添加了两个参数,1表示间隔一秒获取一次,10表示总共获取10次我们一列一列数据来看:r:代表目前实际运行的指令队列,很高表示CPU很繁忙通常会CPU使用率过高这个数据如果高于服务器CPU核数就可能出现瓶颈(需要结合后五列CPU使用百......
  • JVM内存模型深度剖析与优化
    JDK体系结构Java语言的跨平台特性JVM整体结构及内存模型 二、JVM内存参数设置 SpringBoot程序的JVM参数设置格式(Tomcat启动直接加在bin目录下catalina.sh文件里):java‐Xms2048M‐Xmx2048M‐Xmn1024M‐Xss512K‐XX:MetaspaceSize=256M‐XX:MaxMetaspaceSize=25......
  • Java踩坑3.org.gradle.api.tasks.sourceset.getcompiloconfigurationname
    idea2018自带gradle版本4.1我改properties文件为7.5启动项目,sync时报错,如标题。解决步骤:1.我尝试更改jdk9和11都一样报错。2.我尝试改properties文件为6.4不报错。3.我仍然使用properties文件为7.5,不理会build窗口的这个错误。在右侧的gradle插件build,clean这些正常使用。......
  • 《Java编程思想第四版》学习笔记17
    崩溃JavaJava标准集合里包含了toString()方法,所以它们能生成自己的String表达方式,包括它们容纳的对象。例如在Vector中,toString()会在Vector的各个元素中步进和遍历,并为每个元素调用toString()。假定我们现在想打印出自己类的地址。看起来似乎简单地引用this即可(特别......
  • Prim算法是一种用于解决最小生成树问题的贪心算法。它通过逐步选择边来构建最小生成树
    importjava.util.*;classPrimAlgorithm{privatestaticfinalintINF=Integer.MAX_VALUE;publicvoidprimMST(int[][]graph){intvertices=graph.length;int[]parent=newint[vertices];//用于存储最小生成树的父节点int......
  • mysql 8 - linux 安装后 java 调用报错 SQLException: Temporary file write failure
    完整报错Cause:java.sql.SQLException:Temporaryfilewritefailure.;uncategorizedSQLException;SQLstate[HY000];errorcode[1878];Temporaryfilewritefailure.;nestedexceptionisjava.sql.SQLException:Temporaryfilewritefailure.解决不要作用在......
  • 使用Java来开发物联网应用
    这是Hello,LithosphereTutorials系列教程中的其中一篇。感觉介绍用C/C++,用Python来开发物联网应用的文章比较多,用Java来做物联网的文章比较少。这篇文章,介绍如何使用Java技术来开发一个物联网的简单例子。我们从手机App上,遥控硬件板上的LED灯亮灯、熄灯、闪灯。我们学习如何......