0

I have looked at these post How to resize an image without loading into memory? and JMACKIG https://github.com/justinedelson/jmagick only runs on linux and im on a windows currently or has not been tested on onther operating systems besided linux is notes in the README.md Also have looked at this post Java image scaling without loading the whole image into memory But in this case he get the image from a File in mine case I get the image from a Image object.

The use case in mine case is that mine program is in a while loop and then takes screenshots. Then the program looks at the image to detect color and determain where ever it has to do some action based on the color it finds. But the problem right now is that after about 60 iterations of the loop I get a memory leak with this error java get out of memory heap space

So I also tried to clear up mine java cache after every iterations with this bat file: Clear Java Cache but thats seems to do about nothing

So is there anyway that its possible to clear the cache after every iteration of the loop or in the resize function clear the cache of make that the image doesnt go into the cache? Also have seen post where you can increase the max cache size of the program but that doesnt really fix the problem in this case cause The program runs doubtly longer but the error will still occurr and I want to find a way to make it possible that I dont get that memory leak at all.

the code for the image resizing

public Image SCapture(int w, int h) throws Exception
{
    Robot robot = new Robot();
    BufferedImage screenCapture = robot.createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
    Image image = getScaledImage(screenCapture, w, h);
    return image;
}

//Gets screen width and height from main
private static Image getScaledImage(Image srcImg, int w, int h){

    BufferedImage resizedImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2 = resizedImg.createGraphics();

    g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
    g2.drawImage(srcImg, 0, 0, w, h, null);
    g2.dispose();

    return resizedImg;
}

Also I dont really care about image quality it just has to be done fast and clean

Update: After looking in the code more it was something with mine ArrayList checking all the color of the pixels. But this little trick at the end of mine while loop solved the problem

How to force garbage collection in Java?

 public static void gc() {
   Object obj = new Object();
   WeakReference ref = new WeakReference<Object>(obj);
   obj = null;
   while(ref.get() != null) {
      System.gc();
   }

}

HashtagForgotName
  • 651
  • 1
  • 7
  • 23
  • It has to be done in Java? – Tarik Nov 13 '20 at 09:53
  • Well if an external program can do it but how do i hook it up to the java code then in this case? – HashtagForgotName Nov 13 '20 at 09:54
  • That "Java Cache" question has nothing to do with you running out of memory. Use VisualVM or other profiler to see which objects are filling up the heap. – Kayaman Nov 13 '20 at 09:59
  • Imagemagick can do it. You can launch any script or program from Java. That said, having a Java solution would be better. – Tarik Nov 13 '20 at 10:00
  • The GC might not be kicking-in soon enough. – Tarik Nov 13 '20 at 10:01
  • You can use java command line parameters to increase the heap memory. – Tarik Nov 13 '20 at 10:03
  • Use -Xms to specify the initial Java heap size. Use -Xss to set the Java thread stack size. – Tarik Nov 13 '20 at 10:04
  • How do you know for certain that you have a memory leak? How big are your images? – Tarik Nov 13 '20 at 10:04
  • Its not that mine images are big its just that The program takes about 40 per seconds or so Also increase the heap like I said is not a real solution to the memory leak. @Tarik but I geuss I will look more into ImageMagick – HashtagForgotName Nov 13 '20 at 10:07
  • @Kayaman if i remove mine resize image function and use a test image for the whole script I dont get the memory leak so its clearly the image resizing that is causing the issue – HashtagForgotName Nov 13 '20 at 10:08
  • A quick calculation assuming a resolution ~= 1500 x 2000 at 4 bytes per pixel gives 720MB. If your heap settings are too tight and the GC does not kick in fast enough your application might get out of memory. However, assuming you allocate, say 2GB, and it still gets out of memory, then yeah, you might have a memory leak. Give the Xmx parameter a shot and advise. – Tarik Nov 13 '20 at 10:10
  • You might want to use a profiler to find out the exact cause. Obviously the problem is in your code, that's not the mystery here. The GC is called before an `OOME` is thrown, so unless you're getting a GC Overhead limit exceeded, the GC is not "too slow". – Kayaman Nov 13 '20 at 10:12
  • @Tarik after setting the heap to 6g its only lets the program run for longer so It still gets a memory leak error – HashtagForgotName Nov 13 '20 at 10:15
  • @HashtagForgotName Ok, you got me :-) – Tarik Nov 13 '20 at 10:17
  • Ill will start looking more into ImageMagick again see if I can fidn the solution in there to the problem – HashtagForgotName Nov 13 '20 at 10:19
  • What about the rest of the program? You get scaled down images by calling SCapture, then what? Maybe you are keeping them in memory or something. – Tarik Nov 13 '20 at 10:21
  • What about reusing the Graphics2D instead of creating it repeatedly. This is assuming you write the scaled down image to file and do not need it anymore. – Tarik Nov 13 '20 at 10:28
  • Ill try that first when I get home before I look onto imagemagick or one of the java libaries build on imagemagick – HashtagForgotName Nov 13 '20 at 10:45
  • @Kayaman after some more looking into the code its something else indeed – HashtagForgotName Nov 13 '20 at 12:01

0 Answers0