彻底解决Java处理图片时,BufferedImage内存溢出的解决方案

最近系统总数无原因出现内存溢出问题,我程序内会读取一张图片,先压缩图片大小,然后转成byte数组写入到数据库


但是经过大量测试调查,在压缩图片时使用了Java的java.awt.image.BufferedImage总会占用内存不释放,造成内存叠加,最终内存溢出。


在各种百度,谷歌下解决无果,还得亲自想办法。


中间看到有人使用imagemagick解决内存溢出问题,主要是使用dos命令运行exe,达到压缩图片的目的


有兴趣的可以研究下,我尝试了下不是很好用,


于是我想到使用dos加载运行外部jar包,运行自己的代码。


我自己新建了一个工程,然后将自己的工具类单独放到这个工程下,然后导出打成jar包使用。


下载地址:http://pan.baidu.com/s/1i5OT6Kl


将PictureUtil.jar放到工程下,然后通过路径找到PictureUtil.jar,


在dos命令下运行


Java -jar d:\PictureUtil.jar 2 "D:\1.jpg" 2000 2000 true "D:\22.jpg"


返回1是压缩成功。


jar包还有其他功能如下,替换第1个参数2即可:

1、裁切图片

2、压缩图片
3、添加水印
4、图片黑白化操作
5、图片透明化操作
6、格式转化


dos下运行查看参数说明

Java -jar d:\PictureUtil.jar 2 -h

java调用时如下:

package com.yunfeng.dj.common;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;

/**
 * 此类在2017.11.03版本调整 使用运行外部jar实现图片压缩,以处理内存溢出的问题 基本原则是在dos下使用 java -jar
 * CompressPic.jar "C:/saveImg/" "1.jpg" "C:/saveImg/" "1.jpg" 2000 2000
 * 以此不会影响本身的内存机制
 * 
 * @author dongqb
 */
public class CompressPic {

	/*******************************************************************************
	 * 缩略图类(通用) 本java类能将jpg、bmp、png、gif图片文件,进行等比或非等比的大小转换。 具体使用方法
	 * compressPic(大图片路径,生成小图片路径,大图片文件名,生成小图片文名,生成小图片宽度,生成小图片高度,是否等比缩放(默认为true))
	 */
	private File file = null; // 文件对象
	private String inputDir; // 输入图路径
	private String outputDir; // 输出图路径
	private String inputFileName; // 输入图文件名
	private String outputFileName; // 输出图文件名
	private int outputWidth = 2000; // 默认输出图片宽
	private int outputHeight = 2000; // 默认输出图片高

	private String jarpatch = "";

	public CompressPic() { // 初始化变量
		String className = DBMainConfig.class.getName();
		String classNamePath = className.replace(".", "/") + ".class";

		URL is = DBMainConfig.class.getClassLoader().getResource(classNamePath);
		String path = is.getFile();
		path = path.replace("%20", " ");
		path = path.substring(0, path.indexOf("WEB-INF") + 8);
		File f = new File(path);
		jarpatch = f.getParentFile().getAbsolutePath() + "\\CompressPic.jar";
	}

	public boolean compress(String inputDir, String outputDir,
			String inputFileName, String outputFileName, int width, int height) {
		// 输入图路径
		this.inputDir = inputDir;
		// 输出图路径
		this.outputDir = outputDir;
		// 输入图文件名
		this.inputFileName = inputFileName;
		// 输出图文件名
		this.outputFileName = outputFileName;
		// 设置图片长宽
		this.outputWidth = width;
		this.outputHeight = height;
		return execute();
	}

	// 图片处理
	private boolean execute() {
		StringBuffer cmd = new StringBuffer();
		cmd.append("java -jar \"" + jarpatch + "\" ");
		cmd.append(" \"" + inputDir + "\"");
		cmd.append(" \"" + inputFileName + "\"");
		cmd.append(" \"" + outputDir + "\"");
		cmd.append(" \"" + outputFileName + "\"");
		cmd.append(" \"" + outputWidth + "\"");
		cmd.append(" \"" + outputHeight + "\"");
		Runtime rn = Runtime.getRuntime();
		boolean flag = false;
		try {
			Process proc = rn.exec(cmd.toString());
			InputStream stderr = proc.getInputStream(); // 获取输入流
			InputStreamReader isr = new InputStreamReader(stderr);
			BufferedReader br = new BufferedReader(isr);
			String line = null;
			while ((line = br.readLine()) != null) { // 打印出命令执行的结果
				if ("1".equals(line)) {
					flag = true;
				}
			}
			stderr.close();
			br.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return flag;
	}

	public static void main(String[] args) {
		while (true) {
			CompressPic pic = new CompressPic();

			boolean flag = pic.compress("C://saveImg//", "C://saveImg//",
					"1.jpg", "3.jpg", 2000, 2000);
			System.out.println("压缩完成,结果为:" + flag);

			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}




你可能感兴趣的:(彻底解决Java处理图片时,BufferedImage内存溢出的解决方案)