Reputation: 115
I am getting OutOfMemory errors on my saveScreenShot thread even though the BlockingQueue is empty
in my Main there is the following variables storing the images
public static BlockingQueue<ImageSaveData> imageQueue1 = new LinkedBlockingQueue<ImageSaveData>();
public static BlockingQueue<ImageSaveData> imageQueue2 = new LinkedBlockingQueue<ImageSaveData>();
public static BlockingQueue<ImageSaveData> imageQueue3 = new LinkedBlockingQueue<ImageSaveData>();
public static BlockingQueue<ImageSaveData> imageQueue4 = new LinkedBlockingQueue<ImageSaveData>();
here is my ImageSaveData class
import java.awt.image.BufferedImage;
public class ImageSaveData
{
private String fileNumber;
private BufferedImage image;
public ImageSaveData(String fileNumber, BufferedImage image)
{
this.fileNumber = fileNumber;
this.image = image;
}
public String getFileNumber()
{
return fileNumber;
}
public BufferedImage getImage()
{
return image;
}
}
Here is my thread that takes a screenshot and saves it to imageQueueX
// long start = System.currentTimeMillis();
synchronized (runner)
{
int imageCount = 0;
int maxCount = 0;
boolean hasMessage = false;
String[] countFormat =
{
"00000000", "0000000", "000000", "00000", "0000", "000", "00", "0"
};
// 10
while (true)
{
if (maxCount++ < 1000000010)
{
try
{
BufferedImage image = new Robot().createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
String imageOutNumb = "";
if (imageCount < 10) imageOutNumb = countFormat[0] + imageCount++;
else if (imageCount < 100) imageOutNumb = countFormat[1] + imageCount++;
else if (imageCount < 1000) imageOutNumb = countFormat[2] + imageCount++;
else if (imageCount < 10000) imageOutNumb = countFormat[3] + imageCount++;
else if (imageCount < 100000) imageOutNumb = countFormat[4] + imageCount++;
else if (imageCount < 1000000) imageOutNumb = countFormat[5] + imageCount++;
else if (imageCount < 10000000) imageOutNumb = countFormat[6] + imageCount++;
else if (imageCount < 100000000) imageOutNumb = countFormat[7] + imageCount++;
else imageOutNumb = "" + imageCount++;
ImageSaveData imageSaveData = new ImageSaveData(imageOutNumb, image);
while (true)
{
if (Main.imageQueue1.offer(imageSaveData, 1, TimeUnit.NANOSECONDS)) break;
if (Main.imageQueue2.offer(imageSaveData, 1, TimeUnit.NANOSECONDS)) break;
if (Main.imageQueue3.offer(imageSaveData, 1, TimeUnit.NANOSECONDS)) break;
if (Main.imageQueue4.offer(imageSaveData, 1, TimeUnit.NANOSECONDS)) break;
}
}
catch (HeadlessException | AWTException e)
{
e.printStackTrace();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
catch(OutOfMemoryError e)
{
try
{
runner.sleep(1);
}
catch (InterruptedException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
try
{
runner.sleep(34);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else
{
if (hasMessage)
{
try
{
System.out.println(Main.imageQueue1.isEmpty());
System.out.println(Main.imageQueue2.isEmpty());
System.out.println(Main.imageQueue3.isEmpty());
System.out.println(Main.imageQueue4.isEmpty());
}
catch (Exception e)
{
}
}
else
{
System.out.println("We Have Finished saving images to memory");
hasMessage = true;
}
}
}
}
I have 3 consumer threads the only diffrence is that the filePath is diffrent
// long start = System.currentTimeMillis();
synchronized (runner)
{
String PathName = "\\\\DELL\\Maxtor\\aJordan\\";
while (true)
{
try
{
ImageSaveData imageData1 = Main.imageQueue1.poll(1, TimeUnit.NANOSECONDS);
ImageSaveData imageData2 = Main.imageQueue1.poll(1, TimeUnit.NANOSECONDS);
ImageSaveData imageData3 = Main.imageQueue1.poll(1, TimeUnit.NANOSECONDS);
ImageSaveData imageData4 = Main.imageQueue1.poll(1, TimeUnit.NANOSECONDS);
if (imageData1 != null) ImageIO.write(imageData1.getImage(), "png", new File(PathName + imageData1.getFileNumber() + ".png"));
if (imageData2 != null) ImageIO.write(imageData2.getImage(), "png", new File(PathName + imageData2.getFileNumber() + ".png"));
if (imageData3 != null) ImageIO.write(imageData3.getImage(), "png", new File(PathName + imageData3.getFileNumber() + ".png"));
if (imageData4 != null) ImageIO.write(imageData4.getImage(), "png", new File(PathName + imageData4.getFileNumber() + ".png"));
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
error
java.lang.OutOfMemoryError: Java heap space
at sun.awt.windows.WRobotPeer.getRGBPixels(Unknown Source)
at java.awt.Robot.createScreenCapture(Unknown Source)
at TakeShothandler1.run(TakeShothandler1.java:48)
at java.lang.Thread.run(Unknown Source)
line 48 is
BufferedImage image = new Robot().createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
Upvotes: 1
Views: 404
Reputation: 116
What is the capacity of your queues and what is your current heap size?
Each screenshot is going to be in the ballpark of 3-10 MB depending on your resolution (example for 1024x768x32 resolution: 1024x768x4bytes/pixel=3.14MB), and you will likely be able to take them faster than you can write them to disk.
Depending on your heap size and queue capacities, it may not take very long at all to mow through your available heap.
Also, I am not sure (you may have other code elsewhere), but it looks like you may only be polling from one queue in your consumer threads:
ImageSaveData imageData1 = Main.imageQueue1.poll(1, TimeUnit.NANOSECONDS);
ImageSaveData imageData2 = Main.imageQueue1.poll(1, TimeUnit.NANOSECONDS);
ImageSaveData imageData3 = Main.imageQueue1.poll(1, TimeUnit.NANOSECONDS);
ImageSaveData imageData4 = Main.imageQueue1.poll(1, TimeUnit.NANOSECONDS);
Edit: Wow, didn't realize this thread was two years old.
Upvotes: 1