下面一段截图程序在外部的一个方法中调用new ScreenCut().cutScreen(),截完图后使用Jprofilter测试有4M内存无法释放,占用对象是dialog,无法释放的方法是dialog.setVisible(),很是古怪,4M相当于一个screenImage的大小,也可能是grayImage,不知道这两个对象在程序的什么地方引用,导致无法回收.
说明:当截图程序调用,没用进行任何操作时,内存可以释放;当操作后并绘制了彩色选区,不管有没有复制到剪切板,内存都占4M,截图退出无法回收;
没怎么来逛,实在没分了...非常抱歉,重在学习,嘿嘿!
public class ScreenCut extends JPanel{
private BufferedImage screenImage;//-----全屏彩色图
private BufferedImage grayImage;//-------全屏灰度图
private BufferedImage cutImage;//--------截取图片
private JDialog dialog;//----------------弹出的截图窗口
...
public ScreenCut(){...}//-----构造
private void initScreenCut(Window window){....}//--------初始化dialog
public void cutScreen() throws AWTException{
if(!dialog.isVisible()){
updateImage();//-------更新屏幕视图
...
dialog.setVisible(true);
dialog.dispose();
dialog=null;
dispose();//---------------释放图片资源
}
}
//-----------------释放图片资源
private void dispose(){
...
if(cutImage!=null)cutImage=null;
if(screenImage!=null)screenImage=null;
if(grayImage!=null)grayImage=null;
}
//-----------------更新截图背景
private void updateImage() throws AWTException{
screenImage=new Robot().createScreenCapture(rect);//--------截取全屏
grayImage=new BufferedImage(SCREEN.width,SCREEN.height,BufferedImage.TYPE_3BYTE_BGR);//---灰度
ColorConvertOp convert= new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
convert.filter(screenImage, grayImage);//------------------灰度变换
}
//-----------------将选中图片复制到剪切板
private void choosedImage(){
cutImage=copyImage(cutImage);//----cutImage是引用screenImage中的数据,因此复制一份cutImage
ClipBoard.setClipboard(cutImage);//----添加到剪切板
dialog.dispose();//-----释放资源
}
//--------------------复制一个bufferedImage
public static BufferedImage copyImage(BufferedImage image){
BufferedImage buffer=new BufferedImage(image.getWidth(),image.getHeight(),image.getType());
image.copyData(buffer.getRaster());
return buffer;
}
//------------获取选区的彩色图片
private void cutBufferedImage(){
int x,y,width,height;//----------截图的区域
...
cutImage=screenImage.getSubimage(x, y, width, height);//---获取子图
}
//---------绘制图像
public void paint(Graphics g){
super.paint(g);
g.draw(grayImage,0,0,null);//-----------绘制灰度背景
...
cutBufferedImage();
g.drawImage(cutImage,x,y,null);//-----绘制彩色选区
...
}
//-----------------------选区的拖拽处理
private MouseMotionAdapter motion = new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
...
repaint();
}
};
//------------------------鼠标左键双击选区,复制图片
private MouseAdapter mouse = new MouseAdapter() {
...
choosedImage();
...
}
}
问题补充:
zhaomingzm_23 写道
Robot().createScreenCapture(xxx);做什么操作?
截取屏幕,rect是矩形Rectangle的一个实例引用!
问题补充:问题主要是出在调用repaint()方法之后,这4M内存就无法回收了....也就是在使用了g.drawImage(cutImage,x,y,null)之后,内存就一直被占着了...
问题补充:
白粥若水 写道
我看了一下别人的回复,大概就是这样的
不过,还是可能有这样的原因的:并不是在对象的引用为0时就会被立即回收的,一般的JVM会采取这样一种操作,当内存占用率达到一定的程度时才会进行GC计算,回收不可达的对象。
你显式的执行System.gc()看一下
我用测试工具强制回收都没有用了...
问题应该是某个对象一直被引用,而我实在找不出到底哪个还在被引用,JDialog
的引用都为null了,所有申明的引用都为null,可就是还有那4M内存被占用...