我有一小段代码,每隔五分钟就会截取一次我的桌面屏幕截图 - 这是一个轻松思考的工作,并计算出多少截图,比如facebook ...
然而,我对它占用的内存量感到有点困惑 - 通常它会爬升到200mb的RAM,我确信这是多余的......有人可以告诉我一个合理的方法来减少内存占用或b)为什么它在所有上升?
/**
* Code modified from code given in http://whileonefork.blogspot.co.uk/2011/02/java-multi-monitor-screenshots.html following a SE question at
* http://stackoverflow.com/questions/10042086/screen-capture-in-java-not-capturing-whole-screen and then modified by a code review at http://codereview.stackexchange.com/questions/10783/java-screengrab
*/
package com.tmc.personal;
import java.awt.AWTException;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import javax.imageio.ImageIO;
class ScreenCapture {
static int minsBetweenScreenshots = 5;
public static void main(String args[]) {
int indexOfPicture = 1000;// should be only used for naming file...
while (true) {
takeScreenshot("ScreenCapture" + indexOfPicture++);
try {
TimeUnit.MINUTES.sleep(minsBetweenScreenshots);
} catch (Exception e) {
e.printStackTrace();
}
}
}
//from http://www.coderanch.com/t/409980/java/java/append-file-timestamp
private final static String getDateTime()
{
DateFormat df = new SimpleDateFormat("yyyy-MM-dd_hh:mm:ss");
df.setTimeZone(TimeZone.getTimeZone("PST"));
return df.format(new Date());
}
public static void takeScreenshot(String filename) {
Rectangle allScreenBounds = getAllScreenBounds();
Robot robot;
try {
robot = new Robot();
BufferedImage screenShot = robot.createScreenCapture(allScreenBounds);
ImageIO.write(screenShot, "jpg", new File(filename + getDateTime()+ ".jpg"));
} catch (AWTException e) {
System.err.println("Something went wrong starting the robot");
e.printStackTrace();
} catch (IOException e) {
System.err.println("Something went wrong writing files");
e.printStackTrace();
}
}
/**
* Okay so all we have to do here is find the screen with the lowest x, the
* screen with the lowest y, the screen with the higtest value of X+ width
* and the screen with the highest value of Y+height
*
* @return A rectangle that covers the all screens that might be nearby...
*/
private static Rectangle getAllScreenBounds() {
Rectangle allScreenBounds = new Rectangle();
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] screens = ge.getScreenDevices();
int farx = 0;
int fary = 0;
for (GraphicsDevice screen : screens) {
Rectangle screenBounds = screen.getDefaultConfiguration().getBounds();
// finding the one corner
if (allScreenBounds.x > screenBounds.x) {
allScreenBounds.x = screenBounds.x;
}
if (allScreenBounds.y > screenBounds.y) {
allScreenBounds.y = screenBounds.y;
}
// finding the other corner
if (farx < (screenBounds.x + screenBounds.width)) {
farx = screenBounds.x + screenBounds.width;
}
if (fary < (screenBounds.y + screenBounds.height)) {
fary = screenBounds.y + screenBounds.height;
}
allScreenBounds.width = farx - allScreenBounds.x;
allScreenBounds.height = fary - allScreenBounds.y;
}
return allScreenBounds;
}
}
答案 0 :(得分:13)
其他答案是正确的,Java将使用尽可能多的内存,此时它将进行垃圾收集。要解决此问题,可以在JVM设置中指定较小的最大堆大小。您可以使用-Xmx设置执行此操作。例如,如果您认为只需要32MB,请将其运行为:
java -Xmx32M [your main class or jar here]
您的程序堆(非堆栈内存)永远不会超过32MB,但如果它需要多于一次(并且您需要配置文件),它将崩溃。我没有看到你的程序有任何明显的泄漏(假设ImageIO不需要任何清理),所以我认为你会没事的。
答案 1 :(得分:3)
对于现代计算机,200MB并不是过多的内存。如果您正在创建和丢弃大量对象,JVM将让堆增长一段时间,这样您的程序就不会陷入垃圾回收的困境。让你的程序运行几个小时,然后检查你是否认为有问题。
答案 2 :(得分:1)
JVM垃圾收集器最终会清除你的内存堆。要手动清除堆调用Runtime.getRuntime().gc();
,但我不建议每5分钟执行一次。