Java 我应该(可以?)重写Robot类以通过重复屏幕捕获来节省内存,还是GC足够好?

Java 我应该(可以?)重写Robot类以通过重复屏幕捕获来节省内存,还是GC足够好?,java,memory-management,garbage-collection,screen-capture,awtrobot,Java,Memory Management,Garbage Collection,Screen Capture,Awtrobot,编辑#2-我认为这可能是过度优化,并将尝试按原样使用Robot类,直到遇到问题,但FWIW: 我正在设计一个应用程序(严格针对OSX Lion),它与一些非常CPU和内存密集型的软件一起运行,包括音频软件,这些软件不应该因为短CPU峰值/过载而停止运行。与大多数音频软件一样,内存也在不断地读/写 这是一个非常轻量级的应用程序-其主要目的是使用Robot类的createScreenCapture方法,在长达数小时的过程中,每分钟拍摄几次屏幕捕获 在每个后续屏幕捕获时,不需要上一个屏幕捕获。查看Ro

编辑#2-我认为这可能是过度优化,并将尝试按原样使用Robot类,直到遇到问题,但FWIW:

我正在设计一个应用程序(严格针对OSX Lion),它与一些非常CPU和内存密集型的软件一起运行,包括音频软件,这些软件不应该因为短CPU峰值/过载而停止运行。与大多数音频软件一样,内存也在不断地读/写

这是一个非常轻量级的应用程序-其主要目的是使用Robot类的
createScreenCapture
方法,在长达数小时的过程中,每分钟拍摄几次屏幕捕获

在每个后续屏幕捕获时,不需要上一个屏幕捕获。查看Robot源代码后,似乎每次调用
createScreenCapture()
时都会创建一个新的
BuffereImage
,这意味着前一个将留给垃圾收集,对吗

我不熟悉Java和垃圾收集器。我担心GC管理/删除这些旧捕获的必要性会导致CPU峰值。理想情况下,图像可以直接从屏幕转到每次都覆盖内存中的相同区域,并且应用程序的内存占用将保持相当恒定,而GC不会工作太多

是否建议/可能尝试扩展Robot类并重写
createScreenCapture()
,以便它使用相同的静态BuffereImage?如果这真的起作用,我看不出任何人有任何优势,因为目前机器人为每次捕获分配新内存的方式

谢谢

编辑#1-相关机器人源代码摘自,如下所示。似乎不仅每次都会创建一个新的BuffereImage,而且还会创建同样大的int[]、DataBufferInt和WritableRaster。加上peer.getRGBPixels()所产生的任何开销,它似乎连接到了图形驱动程序,但我找不到任何关于这个的源或信息。我认为不重复使用相同的内存是浪费,这是错误的吗?很明显,使用静态指针解决不了任何问题。需要使用BuffereImage自己的set方法覆盖它。我添加了自己对该方法的评论,标记为$$。理论上,它可以为我的应用程序节省大量GC操作,但这是否值得担心呢?如果我对java和评测有更多的了解,我会马上尝试一下

public synchronized BufferedImage createScreenCapture(Rectangle screenRect) {
    checkScreenCaptureAllowed();

    // according to the spec, screenRect is relative to robot's GD
    Rectangle translatedRect = new Rectangle(screenRect);
    translatedRect.translate(gdLoc.x, gdLoc.y);
    checkValidRect(translatedRect);

BufferedImage image;
DataBufferInt buffer;
WritableRaster raster;

if (screenCapCM == null) {
    /*
     * Fix for 4285201 
     * Create a DirectColorModel equivalent to the default RGB ColorModel,
     * except with no Alpha component.
     */

    screenCapCM = new DirectColorModel(24,
                     /* red mask */    0x00FF0000,
                     /* green mask */  0x0000FF00,
                     /* blue mask */   0x000000FF);
}

    // need to sync the toolkit prior to grabbing the pixels since in some
    // cases rendering to the screen may be delayed
    Toolkit.getDefaultToolkit().sync();

int pixels[]; //$$$ do away with this array altogether?
int[] bandmasks = new int[3];

pixels = peer.getRGBPixels(translatedRect); //$$$ not needed
buffer = new DataBufferInt(pixels, pixels.length); //$$$ not needed

bandmasks[0] = screenCapCM.getRedMask();
bandmasks[1] = screenCapCM.getGreenMask();
bandmasks[2] = screenCapCM.getBlueMask();

raster = Raster.createPackedRaster(buffer, translatedRect.width, translatedRect.height, translatedRect.width, bandmasks, null);
//$$$ not needed
//$$$ i don't know what bandmasks are, but maybe the full-size raster could be initialized once with the bandmasks array, then...
//$$$ ...use raster.setPixels(0, 0, translatedRect.width, translatedRect.height, peer.getRGBPixels(translatedRect));

image = new BufferedImage(screenCapCM, raster, false, null);
//$$$ instead use image.setData(raster);

CachingSurfaceManager.restoreLocalAcceleration(image);

return image;
}

不要害怕分配和GC,它们做得非常好,所以您不必担心它们。我可以告诉你,你的解决方案会奏效,因为我已经用AWT机器人实现了实时屏幕捕获,一个每秒捕获20次全屏的机器人!它可以使用默认的JVM参数
-Xmx64
运行数小时,而且没有任何问题。

不要害怕分配和GC,它们做得非常好,所以您不必担心它们。我可以告诉你,你的解决方案会奏效,因为我已经用AWT机器人实现了实时屏幕捕获,一个每秒捕获20次全屏的机器人!它可以使用默认的JVM参数
-Xmx64
运行数小时,而且没有任何问题。

可能不是您等待的答案,但我确实建议您尝试一下。我的意思是,使用默认实现编写应用程序,然后对其进行性能测试。只有当CPU出现问题时,才考虑如何解决。过早的优化可能是许多弊病的根源……编辑完我的问题后,我意识到你说得太对了。我将按原样使用它,看看会发生什么。加上我在一台全新的MacBook上。。。虽然我知道从理论上讲,对于涉及重复屏幕捕获的应用程序来说,这是一种浪费。在学习了更多关于扩展和重写的知识之后,不可能完成我想要的操作,因为所需的方法peer.getRGBPixels()是私有的。尽管如此,我还是很惊讶没有人考虑编写一个更高效的屏幕捕获操作,直接重用相同的内存分配。这可能不是您等待的答案,但我真的建议您尝试一下。我的意思是,使用默认实现编写应用程序,然后对其进行性能测试。只有当CPU出现问题时,才考虑如何解决。过早的优化可能是许多弊病的根源……编辑完我的问题后,我意识到你说得太对了。我将按原样使用它,看看会发生什么。加上我在一台全新的MacBook上。。。虽然我知道从理论上讲,对于涉及重复屏幕捕获的应用程序来说,这是一种浪费。在学习了更多关于扩展和重写的知识之后,不可能完成我想要的操作,因为所需的方法peer.getRGBPixels()是私有的。尽管如此,我还是很惊讶没有人考虑编写一个更高效的屏幕捕获操作,直接重用相同的内存分配。+1我认为调整VM参数比重写核心类更好。通常这对我来说是一件小事,我毫不怀疑,在正常情况下,这种事情可以持续几天。我担心的唯一原因是,我将同时运行的其他音频/视频应用程序有时会使处理器过载,甚至超读4核。基本上,我会时不时地挤出每一滴水。所以我不知道我是否会因为GC进程而不得不缩减工作量,理论上我应该能够消除它。最有可能的是,默认情况下一切都会很顺利,我会报告结果。+1我认为调整VM参数比重写核心类更好。通常这对我来说是一件小事,我毫不怀疑这种事情在正常情况下可以运行数天。我担心的唯一原因是,我将同时运行的其他音频/视频应用程序有时会使处理器过载,甚至