imageio.write 惹的祸,占用cpu过高,堆溢出问题

本文详细介绍了在遇到Java进程CPU占用率过高和堆溢出问题时的诊断与解决步骤,包括使用jstack、jmap、jstat和jinfo等工具进行深入分析的方法。
部署运行你感兴趣的模型镜像

两次与imageio接触:

1.在一个队列中消费消息的时候一个线程抛出堆溢出

2.一次在线上cpu占用率过高

 

 

线上出现cpu过高解决办法:

1.启动一个shell命令窗口,top命令查看java进程

2.在启动一个shell命令窗口,top -H -p 12233,查看这个进程的线程号

3. 在启动一个shell命令窗口,当看到某个想成请求cpu过高的时候,输入jstack  12233 >>/data/test.txt,dump

线程的日志文件

4.将进程号转换为16进制,方法是在shell中输入printf %x 12233 转成比如3b82

5. grep  -C 10 3b82或者jstat pid |grep -C 10 pid(16进制转换之后)

 

 

 

其他方案:

jstat -gcutil 15178 1s  观察一段时间GC状况

 

jmap -histo 15178 | less 查看一下对象实例数量和空间占用

 

jstack 5511 | wc -l 查看当前系统的线程总数
加载当前的堆信息:jmap -dump:live,format=b,file=dump.hprof 5511
统计总共线程数

 

 

 

知识点:

 

原文:https://blog.csdn.net/u010827436/article/details/46564641

0.分类
功能
    
命令
线程     jstack
内存     jmap
性能     jstat
1.查找到Jvm的进程id,以后所有命令基本都需要
jps
# 附带jvm参数信息
jps -v
# 只显示id
jps -q
#输出main method的参数
jps -m
#输出完全的包名,应用主类名,jar的完全路径
jps -l
# 向下个命令输出pid
jps | grep 'Bootstrap' | awk '{print $1}' |
2.jstat命令使用
jps  -opt  pid -h n (每隔多少行出现行头)interval(间隔多久)  count(多少次)
# 查询gc百分比
jstat -gcutil pid 1000
# 显示三代的使用量
jstat -gccapacity pid 1000
# 显示加载class的数量,及所占空间等信息
jstat -class pid
# 显示VM实时编译的数量等信息
jstat -compiler pid
# 可以显示gc的信息,查看gc的次数,及时间。其中最后五项,分别是young gc的次数,young gc的时间,full gc的次数,full gc的时间,gc的总时间。
jstat -gc pid
# 当前VM执行的信息
jstat -printcompilation pid
# 用于查看垃圾收集的统计情况(这个和-gcutil选项一样),如果有发生垃圾收集,它还会显示最后一次及当前正在发生垃圾收集的原因
jstat -gccause pid
 
3.jinfo可以输出并修改运行时的java 进程的参数
jinfo -opt  pid
# 打印所有pid相关的vm配置
jinfo pid
# 只显示某个配置 例如永久代:MaxPermSize
jinfo -flag MaxPermSize pid
# -flag [+|-]< name >:设置或取消指定java虚拟机参数的布尔值
jinfo -flag +PrintGCDetails 2000
# jinfo虽然可以在java程序运行时动态地修改虚拟机参数,但并不是所有的参数都支持动态修改
4.jmap打印出某个java进程内存内的,所有‘对象’的情况
jmap  -opt  pid
# 使用hprof二进制形式,输出jvm的heap内容到文件=. live子选项是可选的,假如指定live选项,那么只输出活的对象到文件
jmap -dump:format=b,file=test.bin pid
# 打印正等候回收的对象的信息
jmap -finalizerinfo pid
# 打印heap的概要信息,GC使用的算法,heap的配置及wise heap的使用情况
jmap -heap pid
# 打印每个class的实例数目,内存占用,类全名信息. VM的内部类名字开头会加上前缀”*”. 如果live子参数加上后,只统计活的对象数量.
# 统计大对象的时候很实用 但是会触发一次full gc
jmap histo:live pid | head -n 23
# 打印classload和jvm heap长久层的信息. 包含每个classloader的名字,活泼性,地址,父classloader和加载的class数量. 另外,内部String的数量和占用内存数也会打印出来
jmap -permstat pid
 
5.jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息
jstack -opt  pid
# 一般使用是将jstack的结果输出到文件中来查看
jstat pid > jstat01.log
# 或者直接使用grep查找
jstat pid |grep -C 10 pid(16进制转换之后)
# 或者直接搜索关键字 Deadlock 之类的

转换工具 http://tool.oschina.net/hexconvert

dump 文件里,值得关注的线程状态有:
     死锁,Deadlock(重点关注)
     执行中,Runnable  
     等待资源,Waiting on condition(重点关注)
     等待获取监视器,Waiting on monitor entry(重点关注)
     暂停,Suspended
     对象等待中,Object.wait() 或 TIMED_WAITING
     阻塞,Blocked(重点关注)
     停止,Parked

 

转载于:https://www.cnblogs.com/QAZLIU/p/10151879.html

您可能感兴趣的与本文相关的镜像

GPT-SoVITS

GPT-SoVITS

AI应用

GPT-SoVITS 是一个开源的文本到语音(TTS)和语音转换模型,它结合了 GPT 的生成能力和 SoVITS 的语音转换技术。该项目以其强大的声音克隆能力而闻名,仅需少量语音样本(如5秒)即可实现高质量的即时语音合成,也可通过更长的音频(如1分钟)进行微调以获得更逼真的效果

package com.huawei.assessment.util; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFRelation; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.awt.*; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import javax.imageio.ImageIO; @Component public class ExcelWatermark { @Value("${watermark.height:1500}") private int height; @Value("${watermark.width:1500}") private int width; @Value("${watermark.excelFontSize:30}") private int excelFontSize; /** * 将文本二进制数据增加水印 * * @param watermarkText watermarkText * @param bytes bytes * @return byte[] * @throws IOException IOException */ // 将水印图片添加到工作簿 public byte[] addWatermarkToWorkbook(String watermarkText, byte[] bytes) throws IOException { try (InputStream inputStream = new ByteArrayInputStream(bytes); XSSFWorkbook workbook = new XSSFWorkbook(inputStream)) { // 创建水印图片(规范关闭流) BufferedImage image = createWatermarkImage(watermarkText); byte[] imageBytes; try (ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream()) { ImageIO.write(image, "png", byteArrayOut); imageBytes = byteArrayOut.toByteArray(); } // 添加水印 int pictureIdx = workbook.addPicture(imageBytes, Workbook.PICTURE_TYPE_PNG); for (int i = 0; i < workbook.getNumberOfSheets(); i++) { addWatermarkToSheet(workbook.getSheetAt(i), pictureIdx); } return convertWorkbookToByteArray(workbook); } } // 创建水印图片 private BufferedImage createWatermarkImage(String text) { Font font = new Font("宋体", Font.PLAIN, excelFontSize); return drawText(text, font, Color.LIGHT_GRAY, Color.WHITE, height, width); } // 将 XSSFWorkbook 转换为 byte[] public byte[] convertWorkbookToByteArray(XSSFWorkbook workbook) throws IOException { try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) { // 将工作簿写入字节输出流 workbook.write(byteArrayOutputStream); // 返回字节数组 return byteArrayOutputStream.toByteArray(); } } // 将水印添加到指定的工作表 private void addWatermarkToSheet(XSSFSheet sheet, int pictureIdx) { String rID = sheet.addRelation(null, XSSFRelation.IMAGE_PNG, sheet.getWorkbook().getAllPictures().get(pictureIdx)) .getRelationship().getId(); sheet.getCTWorksheet().addNewPicture().setId(rID); } // 绘制文本水印图像 private BufferedImage drawText(String text, Font font, Color textColor, Color backColor, double height, double width) { BufferedImage img = new BufferedImage((int) width, (int) height, BufferedImage.TYPE_INT_ARGB); Graphics2D loGraphic = img.createGraphics(); FontMetrics loFontMetrics = loGraphic.getFontMetrics(font); int liStrWidth = loFontMetrics.stringWidth(text); int liStrHeight = loFontMetrics.getHeight(); loGraphic.setColor(backColor); loGraphic.fillRect(0, 0, (int) width, (int) height); loGraphic.translate(((int) width - liStrWidth) / 2, ((int) height - liStrHeight) / 2); loGraphic.rotate(Math.toRadians(-45)); loGraphic.translate(-((int) width - liStrWidth) / 4, -((int) height - liStrHeight) / 4); loGraphic.setFont(font); loGraphic.setColor(textColor); loGraphic.drawString(text, ((int) width - liStrWidth) / 4, ((int) height - liStrHeight) / 2); loGraphic.drawString(text, ((int) width - liStrWidth) / 2, ((int) height - liStrHeight) / 4); loGraphic.drawString(text, ((int) width - liStrWidth) / 6, ((int) height - liStrHeight) / 20); loGraphic.dispose(); return img; } } 上面代码请求次数过多,会出现oom问题,优化上面代码,输出代码样例
09-06
public List<String> llmReadFile(MultipartFile file) { List<String> results = new ArrayList<>(); //获取文件类型 String fileName = file.getOriginalFilename().toLowerCase(); //判断文件是否存在 if (fileName == null) { results.add("文件对象为空或无效"); return results; } try (InputStream is = file.getInputStream()) { //LLM识别PDF文件 if (fileName.endsWith(".pdf")) { try (PDDocument pdfDoc = PDDocument.load(is)) { PDFRenderer pdfRenderer = new PDFRenderer(pdfDoc); int totalPages = pdfDoc.getNumberOfPages(); for (int i = 0; i < totalPages; i++) { BufferedImage pdfImage = pdfRenderer.renderImageWithDPI(i, 200F); processImage(results, pdfImage); } } //LLM识别图片 } else if (fileName.endsWith(".png") || fileName.endsWith(".jpg")) { BufferedImage image = ImageIO.read(is); BufferedImage resized = resizeImage(image, 40); processImage(results, resized); } else { results.add("不支持的文件格式: " + fileName); } } catch (IOException e) { results.add("读取文件失败: " + e.getMessage()); } System.out.println("识别内容:" + results); return results; } /** * LLM大模型请求 输出内容 * * @param results * @param image * @throws IOException */ private void processImage(List<String> results, BufferedImage image) throws IOException { BufferedImage processedImage = sharpenImage(image); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ImageIO.write(processedImage, "png", baos); String base64Image = Base64.getEncoder().encodeToString(baos.toByteArray()); String dataUrl = "data:image/png;base64," + base64Image; String promptText = " 请精准识别图片中的内容,不要思考和推理,只需要输出图中的内容。"; Media media = Media.builder() .mimeType(MimeTypeUtils.IMAGE_PNG) .mimeType(MimeTypeUtils.IMAGE_JPEG) .data(dataUrl) .build(); UserMessage userMessage = new UserMessage(promptText, media); String content = chatModel.call(new Prompt(userMessage)).toString(); results.add(content); } //锐化 private BufferedImage sharpenImage(BufferedImage original) { float[] sharpenMatrix = { 0, -1, 0, -1, 5, -1, 0, -1, 0 }; BufferedImageOp sharpenOp = new ConvolveOp(new Kernel(3, 3, sharpenMatrix), ConvolveOp.EDGE_NO_OP, null); return sharpenOp.filter(original, null); } //强化图片 private BufferedImage resizeImage(BufferedImage originalImage, int targetDPI) { int width = originalImage.getWidth(); int height = originalImage.getHeight(); double scale = (double) targetDPI / 96; int newWidth = (int) (width * scale); int newHeight = (int) (height * scale); BufferedImage resizedImage = new BufferedImage(newWidth, newHeight, originalImage.getType()); java.awt.Graphics2D g2d = resizedImage.createGraphics(); g2d.drawImage(originalImage, 0, 0, newWidth, newHeight, null); g2d.dispose(); return resizedImage; } 这个是我的代码 我如何去使用线程池去优化这种
最新发布
10-24
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值