From abca82ac7ca373db8b6eff7f63cf68d5ae8bbfeb Mon Sep 17 00:00:00 2001 From: huoyo <1729913829@qq.com> Date: Thu, 3 Oct 2024 19:07:30 +0800 Subject: [PATCH] add:export heapdump --- .../kotime/controller/KoTimeController.java | 39 ++++++++++++++-- .../kotime/service/HeapDumpService.java | 45 +++++++++++++++++++ 2 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 src/main/java/cn/langpy/kotime/service/HeapDumpService.java diff --git a/src/main/java/cn/langpy/kotime/controller/KoTimeController.java b/src/main/java/cn/langpy/kotime/controller/KoTimeController.java index 41a9038..cf6f84a 100644 --- a/src/main/java/cn/langpy/kotime/controller/KoTimeController.java +++ b/src/main/java/cn/langpy/kotime/controller/KoTimeController.java @@ -3,11 +3,10 @@ package cn.langpy.kotime.controller; import cn.langpy.kotime.annotation.Auth; import cn.langpy.kotime.config.DefaultConfig; import cn.langpy.kotime.model.*; -import cn.langpy.kotime.service.ClassService; -import cn.langpy.kotime.service.GraphService; -import cn.langpy.kotime.service.SysUsageService; -import cn.langpy.kotime.service.ThreadUsageService; +import cn.langpy.kotime.service.*; import cn.langpy.kotime.util.Context; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; @@ -99,6 +98,7 @@ public class KoTimeController { } } + @GetMapping("/getParamGraph") @ResponseBody @Auth @@ -259,6 +259,37 @@ public class KoTimeController { return heapMemoryInfo; } + + @GetMapping("/dumpHeap") + @ResponseBody +// @Auth + public void dumpHeap(Boolean live, HttpServletResponse response) { + live = live==null?false:live; + HeapDumpService heapDumpService = HeapDumpService.newInstance(); + String heapDumpFile = heapDumpService.getHeapDumpFile(live); + if (heapDumpFile == null) { + throw new RuntimeException("Can not dumpheap file!"); + } + log.info(heapDumpFile); + response.setCharacterEncoding("utf-8"); + response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); + response.addHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename="+heapDumpService.getHeapDumpFileName(live)); + try( OutputStream out = response.getOutputStream(); + BufferedOutputStream bufferedOut = new BufferedOutputStream(out); + FileInputStream fileInputStream = new FileInputStream(heapDumpFile); + BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream)){ + byte[] buffer = new byte[1024]; + int bytesRead; + while ((bytesRead = bufferedInputStream.read(buffer)) != -1) { + bufferedOut.write(buffer,0,bytesRead); + } + bufferedOut.flush(); + + }catch (Exception e){ + e.printStackTrace(); + } + } + @GetMapping("/getPhysicalMemoryInfo") @ResponseBody @Auth diff --git a/src/main/java/cn/langpy/kotime/service/HeapDumpService.java b/src/main/java/cn/langpy/kotime/service/HeapDumpService.java new file mode 100644 index 0000000..c7115df --- /dev/null +++ b/src/main/java/cn/langpy/kotime/service/HeapDumpService.java @@ -0,0 +1,45 @@ +package cn.langpy.kotime.service; + +import com.sun.management.HotSpotDiagnosticMXBean; + +import javax.management.MBeanServer; +import java.io.File; +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.logging.Logger; + +public class HeapDumpService { + private static final String STANDARD_DUMP_NAME = "kotime-heapdump-%s.hprof"; + private static Logger log = Logger.getLogger(HeapDumpService.class.toString()); + private static final String HotSpotDiagnosticName = "com.sun.management:type=HotSpotDiagnostic"; + + public static HeapDumpService newInstance() { + return new HeapDumpService(); + } + + public String getHeapDumpFile(boolean live) { + String targetFile = System.getProperty("java.io.tmpdir")+File.separator+getHeapDumpFileName(live); + try { + MBeanServer server = ManagementFactory.getPlatformMBeanServer(); + HotSpotDiagnosticMXBean hotSpotDiagnostic = ManagementFactory.newPlatformMXBeanProxy(server, HotSpotDiagnosticName, HotSpotDiagnosticMXBean.class); + if (Files.exists(Paths.get(targetFile))) { + new File(targetFile).delete(); + } + hotSpotDiagnostic.dumpHeap(targetFile, live); + } catch (IOException e) { + e.printStackTrace(); + log.severe("Can not dump heap file!"); + } + return targetFile; + } + + public String getHeapDumpFileName(boolean live) { + if (live) { + return String.format(STANDARD_DUMP_NAME, "live"); + } + return String.format(STANDARD_DUMP_NAME, "all"); + } + +}