赞
踩
通过oshi这个三方库来获取,目前这个最准确。
引入依赖
<dependency>
<groupId>com.github.oshi</groupId>
<artifactId>oshi-core</artifactId>
<version>3.5.0</version>
</dependency>
Demo代码
import oshi.SystemInfo; import oshi.software.os.OSProcess; import oshi.software.os.OperatingSystem; import oshi.util.FormatUtil; import java.lang.management.ManagementFactory; import java.lang.management.RuntimeMXBean; public class Test { public static void main(String[] args) { ExecutorService service = Executors.newSingleThreadScheduledExecutor(); final long[] bytesWritten = {0}; final long[] bytesRead = {0}; service.execute(new Runnable() { @SneakyThrows @Override public void run() { while(true) { SystemInfo systemInfo = new SystemInfo(); OperatingSystem os = systemInfo.getOperatingSystem(); int processId = os.getProcessId(); OSProcess process = os.getProcess(processId); long curBytesWritten = process.getBytesWritten(); long curBytesRead = process.getBytesRead(); if (bytesWritten[0] == 0 ){ bytesWritten[0] = curBytesWritten; } if (bytesRead[0] == 0 ){ bytesRead[0] = curBytesRead; } log.info("pid %d 当前进程:占用内存 %s | 占用CPU(%%) %.2f | 写入(bytes) %d | 读取(bytes) %d".formatted(processId, FormatUtil.formatBytes(process.getResidentSetSize()), getProcessCpuLoad(), curBytesWritten - bytesWritten[0], curBytesRead - bytesRead[0])); bytesWritten[0] = curBytesWritten; bytesRead[0] = curBytesRead; try { Thread.sleep(1000); } catch (InterruptedException e) { log.error("性能监控时出现异常:{}",e); } } } }); } /** * 获取当前进程的CPU利用率 * @return * @throws Exception */ public static double getProcessCpuLoad() throws Exception { MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); ObjectName name = ObjectName.getInstance("java.lang:type=OperatingSystem"); AttributeList list = mbs.getAttributes(name, new String[]{ "ProcessCpuLoad" }); if (list.isEmpty()) { return Double.NaN; } Attribute att = (Attribute)list.get(0); Double value = (Double)att.getValue(); // usually takes a couple of seconds before we get real values if (value == -1.0) { return Double.NaN; } // returns a percentage value with 1 decimal point precision return ((int)(value * 1000) / 10.0); } }
效果图


如果还想对这些数据进行统计的话,我这里也写了个小DEMO,用于解析日志文件,然后计算出下面这些指标:
平均RAM使用(MB)548.36 | 总CPU利用率(%) 12.70 | 平均写入速率(kb/s) 713 | 平均读取速率(kb/s) 346
最大RAM使用(MB)838.40 | 最大CPU利用率(%) 25.20 | 最大写入速率(kb/s) 8161 | 最大读取速率(kb/s) 65582
需要注意,执行代码前要修改日志所在路径folderPath ,以及日志持续时间durationSeconds
DEMO代码
import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Test { public static void main(String[] args) { // 定义指定文件夹路径 String folderPath = "D:\\xx\\logs\\Info\\日志"; File folder = new File(folderPath); // 遍历文件夹下所有文件 int countFile = 1; //持续时间 double durationSeconds = 2271; double totalRAMUseage = 0d; double maxRAMUseage = 0d; double totalCPUUseage = 0d; double maxCPUUseage = 0d; long maxReadBytes = 0; long totalReadBytes = 0; long maxWrittenBytes = 0; long totalWrittenBytes = 0; File[] files = folder.listFiles((d, name) -> name.endsWith(".info")); // 使用自定义的Comparator按照创建时间从早到晚排序 Arrays.sort(files, Comparator.comparingLong(File::lastModified)); for (File file: files) { if (file.isFile() && file.getName().endsWith(".info")) { // 打开文件并按行读取 try (BufferedReader br = new BufferedReader(new FileReader(file))) { System.out.println("正在解析日志%s(%d/%d)".formatted(file.getName(),countFile++,folder.listFiles().length)); String line; while ((line = br.readLine()) != null) { if (line.contains("占用内存")) { double ramUsage = getRAMUsageAfterSpecifiedString(line); double cpuUsage = getCPUUsageAfterSpecifiedString(line); long readBytes = getReadBytesAfterSpecifiedString(line); long writtenBytes = getWrittenBytesAfterSpecifiedString(line); if (ramUsage > maxRAMUseage){ System.out.println("max ram "+line); } if (cpuUsage > maxCPUUseage){ System.out.println("max cpu "+line); } if (readBytes > maxReadBytes){ System.out.println("max read "+line); } if (writtenBytes > maxWrittenBytes){ System.out.println("max write "+line); } maxRAMUseage = (ramUsage > maxRAMUseage ? ramUsage : maxRAMUseage); maxCPUUseage = (cpuUsage > maxCPUUseage ? cpuUsage : maxCPUUseage); maxReadBytes = (readBytes > maxReadBytes ? readBytes : maxReadBytes); maxWrittenBytes = (writtenBytes > maxWrittenBytes ? writtenBytes : maxWrittenBytes); totalRAMUseage += ramUsage; totalCPUUseage += cpuUsage; totalReadBytes += readBytes; totalWrittenBytes += writtenBytes; } } } catch (IOException e) { e.printStackTrace(); } } } System.out.println("平均RAM使用(MB)%.2f | 总CPU利用率(%%) %.2f | 平均写入速率(kb/s) %d | 平均读取速率(kb/s) %d ".formatted( totalRAMUseage / durationSeconds, totalCPUUseage/ durationSeconds, totalWrittenBytes / (long)durationSeconds/1024, totalReadBytes/(long)durationSeconds/1024) ); System.out.println("最大RAM使用(MB)%.2f | 最大CPU利用率(%%) %.2f | 最大写入速率(kb/s) %d | 最大读取速率(kb/s) %d ".formatted( maxRAMUseage, maxCPUUseage, maxWrittenBytes/1024, maxReadBytes/1024 )); } public static double getRAMUsageAfterSpecifiedString(String specifiedString){ // 定义待匹配的字符串 // 定义正则表达式 String patternString = ".*占用内存 (\\d+\\.\\d+) GiB.*"; Pattern pattern = Pattern.compile(patternString); // 进行匹配 Matcher matcher = pattern.matcher(specifiedString); if (matcher.matches()) { // 获取第一组匹配到的数字 String numberStr = matcher.group(1); return Double.parseDouble(numberStr)*1024; }else { patternString = ".*占用内存 (\\d+\\.\\d+) MiB.*"; pattern = Pattern.compile(patternString); // 进行匹配 matcher = pattern.matcher(specifiedString); if (matcher.matches()) { // 获取第一组匹配到的数字 String numberStr = matcher.group(1); return Double.parseDouble(numberStr); } } return 0d; } public static double getCPUUsageAfterSpecifiedString(String specifiedString){ // 定义待匹配的字符串 // 定义正则表达式 String patternString = ".*占用CPU\\(%\\) (\\d+\\.\\d+).*"; Pattern pattern = Pattern.compile(patternString); // 进行匹配 Matcher matcher = pattern.matcher(specifiedString); if (matcher.matches()) { // 获取第一组匹配到的数字 String numberStr = matcher.group(1); return Double.parseDouble(numberStr); } return 0d; } public static long getReadBytesAfterSpecifiedString(String specifiedString){ // 定义待匹配的字符串 // 定义正则表达式 String patternString = ".*读取\\(bytes\\) (\\d+).*"; Pattern pattern = Pattern.compile(patternString); // 进行匹配 Matcher matcher = pattern.matcher(specifiedString); if (matcher.matches()) { // 获取第一组匹配到的数字 String numberStr = matcher.group(1); return Long.parseLong(numberStr); } return 0; } public static long getWrittenBytesAfterSpecifiedString(String specifiedString){ // 定义待匹配的字符串 // 定义正则表达式 String patternString = ".*写入\\(bytes\\) (\\d+).*"; Pattern pattern = Pattern.compile(patternString); // 进行匹配 Matcher matcher = pattern.matcher(specifiedString); if (matcher.matches()) { // 获取第一组匹配到的数字 String numberStr = matcher.group(1); return Long.parseLong(numberStr); } return 0; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。