为什么这个Java程序占用了这么多内存?

我有一小段代码每隔五分钟拍摄一次我的桌面截图 – 这是一段时间的工作,可以轻松思考并计算出多少截图,比如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; } } 

其他答案是正确的,Java将使用尽可能多的内存,此时它将垃圾收集。 要解决此问题,可以在JVM设置中指定较小的最大堆大小。 您可以使用-Xmx设置执行此操作。 例如,如果您认为只需要32MB,请将其运行为:

 java -Xmx32M [your main class or jar here] 

您的程序堆(非堆栈内存)永远不会超过32MB,但如果它需要多于一次(并且您需要配置文件),它将崩溃。 我没有看到你的程序有任何明显的泄漏(假设ImageIO不需要任何清理),所以我认为你会没事的。

对于现代计算机,200MB并不是过多的内存。 如果您正在创建和丢弃大量对象,JVM将让堆增长一段时间,这样您的程序就不会陷入垃圾回收的困境。 让你的程序运行几个小时,然后检查你是否认为有问题。

JVM垃圾收集器最终会清除你的内存堆。 用于手动清除该堆调用Runtime.getRuntime().gc(); ,但我不建议每5分钟这样做。