[code="java"]
Robot ro = new Robot();
Rectangle rec = ScreenPanel.select;
BufferedImage img = ro.createScreenCapture(rec);
Image image = img.getScaledInstance(w, h, Image.SCALE_DEFAULT);
BufferedImage bufImg = new BufferedImage(w,h,Image.SCALE_DEFAULT);
bufImg.getGraphics().drawImage(image, 0, 0, null);
q.push(bufImg);
[/code]
上面的代码在定时器里面50毫秒执行一次,执行几次之后就会报错:
Exception in thread "Timer-2" java.lang.OutOfMemoryError: Java heap space
at java.awt.image.DataBufferInt.(DataBufferInt.java:75)
at java.awt.image.Raster.createPackedRaster(Raster.java:470)
at java.awt.image.DirectColorModel.createCompatibleWritableRaster(DirectColorModel.java:1032)
at sun.awt.image.ImageRepresentation.createBufferedImage(ImageRepresentation.java:253)
at sun.awt.image.ImageRepresentation.setPixels(ImageRepresentation.java:554)
at java.awt.image.ReplicateScaleFilter.setPixels(ReplicateScaleFilter.java:250)
at sun.awt.image.OffScreenImageSource.sendPixels(OffScreenImageSource.java:137)
at sun.awt.image.OffScreenImageSource.produce(OffScreenImageSource.java:187)
at sun.awt.image.OffScreenImageSource.addConsumer(OffScreenImageSource.java:66)
at sun.awt.image.OffScreenImageSource.startProduction(OffScreenImageSource.java:80)
at java.awt.image.FilteredImageSource.startProduction(FilteredImageSource.java:183)
at sun.awt.image.ImageRepresentation.startProduction(ImageRepresentation.java:727)
at sun.awt.image.ImageRepresentation.drawToBufImage(ImageRepresentation.java:802)
at sun.java2d.pipe.DrawImage.copyImage(DrawImage.java:1018)
at sun.java2d.pipe.ValidatePipe.copyImage(ValidatePipe.java:186)
at sun.java2d.SunGraphics2D.drawImage(SunGraphics2D.java:3084)
at sun.java2d.SunGraphics2D.drawImage(SunGraphics2D.java:3069)
at ideamoment.Recorde.queue.CutScreen.run(CutScreen.java:31)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
我是想不停的截图,然后缩放,然后放进一个list中,这个list是队列,我会1毫秒检查一次读取第一个然后remove第一个,理论上应该没问题啊......
溢出后 建议打印堆栈检查(jmap)
bufImg.getGraphics() 用完后考虑dispose
JDK描述
[quote]dispose()释放此图形的上下文以及它使用的所有系统资源。调用 dispose 之后,就不能再使用 Graphics 对象。
Java 程序运行时,可以在一个短时间帧内创建大量的 Graphics 对象。尽管垃圾回收器的终止进程也能够进行相同的系统资源释放,但是最好通过调用此方法来手工释放相关资源,而不是依靠终止进程,因为终止进程需要很长时间才能结束运行。 [/quote]
读取完第一个以后虽然remove掉了,但是你读取的结果应该还保留着吧?remove只是从队列中把对象的的引用给删掉了,如果你之前从队列里读取出来的第一个对象的引用还保留着的话,那个对象是不会被垃圾回收掉的,所以内存堆的剩余空间会越来越少。只有没有任何对该对象的引用的时候,才会被垃圾回收掉。
比如:
public static void main(String[] args){
String s = "hello";
List<String> al = new ArrayList<String>();
al.add(s);
for(String str:al)
System.out.println(str);
al.remove(0);
System.out.println(s);
}
执行结果:
hello
hello
您可以尝试使用在使用后释放掉资源,使用后使其变为弱引用或虚引用对象,这样可以减少内存泄露问题