atom feed13 messages in net.java.dev.rococoa.usersInvalid memory access of location...
FromSent OnAttachments
Sami NopanenNov 1, 2009 1:08 pm 
Paul LoyNov 1, 2009 2:06 pm 
Sami NopanenNov 1, 2009 2:18 pm 
Andrew ThompsonNov 1, 2009 3:25 pm 
Sami NopanenNov 1, 2009 4:12 pm 
Sami NopanenNov 6, 2009 8:43 am 
Paul LoyNov 6, 2009 9:00 am 
Sami NopanenNov 6, 2009 11:44 am 
Duncan McGregorNov 6, 2009 3:12 pm 
Andrew ThompsonNov 6, 2009 8:00 pm 
Sami NopanenNov 6, 2009 8:51 pm 
Andrew ThompsonNov 7, 2009 7:56 am 
Sami NopanenNov 7, 2009 9:07 am 
Subject:Invalid memory access of location...
From:Sami Nopanen (snop@gmail.com)
Date:Nov 1, 2009 1:08:19 pm
List:net.java.dev.rococoa.users

Hi all,

I've been trying to code a simple screenshot application using rococoa, and managed to get as far as actually taking the screenshot, and then saving it to a file. Unfortunately, once in a while, the application fails with an 'Invalid memory access of location...' error. I'm assuming this is due to something being garbage collected, because I'm failing to keep a reference alive. If the error occurs, it always seems to happen on the line 'int[] data = pointer.getIntArray(0, bytesPerPlane / 4);'.

Further, when trying to make the error easily reproducible, I changed the application to take 1000 sceenshots in a loop, which seems to usually cause it to crash after taking a few (3-10) of them. I tried a few things out, and what I noticed was, that if i add 'Runtime.getRuntime().gc();' between the calls to getScreenshot(), the application doens't seem to crash anymore. And further, it also seems that the application gets quite a bit slower after calling the method hundreds of times, so I'm guessing some resources might be leaking out, too.

I really haven't coded anything with Objective C, and just starting up with rococoa, so I'm finding myself just confused with this. I've copied the relevant code below, and would really appreciate any help with this!

Thanks, Sami, snop@gmail.com

---

public interface QuartzLibrary extends Library { QuartzLibrary INSTANCE = (QuartzLibrary) Native.loadLibrary("Quartz", QuartzLibrary.class);

class CGPoint extends Structure { public double x; public double y; }

class CGSize extends Structure { public double width; public double height; }

class CGRect extends Structure implements Structure.ByValue { public static class CGRectByValue extends CGRect { }

public CGPoint origin; public CGSize size; }

int kCGWindowListOptionIncludingWindow = (1 << 3); int kCGWindowImageBoundsIgnoreFraming = (1 << 0);

ID CGWindowListCreateImage(CGRect screenBounds, int windowOption, int windowId, int imageOption); }

public interface NSBitmapImageRep extends NSObject { public static final _Class CLASS = Rococoa.createClass("NSBitmapImageRep", _Class.class);

public interface _Class extends NSClass { NSBitmapImageRep alloc(); }

NSBitmapImageRep initWithCGImage(ID imageRef); com.sun.jna.Pointer bitmapData(); NSSize size(); }

public class Screenshot { public static void getScreenshot(int windowId) throws IOException { QuartzLibrary.CGRect bounds = new QuartzLibrary.CGRect.CGRectByValue(); bounds.origin = new QuartzLibrary.CGPoint(); bounds.origin.x = 0; bounds.origin.y = 0; bounds.size = new QuartzLibrary.CGSize(); bounds.size.width = 0; bounds.size.height = 0; ID imageRef = QuartzLibrary.INSTANCE.CGWindowListCreateImage(bounds, QuartzLibrary.kCGWindowListOptionIncludingWindow, windowId, QuartzLibrary.kCGWindowImageBoundsIgnoreFraming);

NSBitmapImageRep imageRep = NSBitmapImageRep.CLASS.alloc(); imageRep = imageRep.initWithCGImage(imageRef); NSSize size = imageRep.size(); com.sun.jna.Pointer pointer = imageRep.bitmapData();

int width = size.width.intValue(); int height = size.height.intValue();

BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); int[] data = pointer.getIntArray(0, bytesPerPlane / 4); int idx = 0; for(int y = 0; y < height; y++) for(int x = 0; x < width; x++) image.setRGB(x, y, data[idx++]);

ImageIO.write(image, "png", new File("foo.png")); }

public static void main(String[] args) throws Exception { NSAutoreleasePool pool = NSAutoreleasePool.new_(); try { for(int i = 0; i < 1000; i++) getScreenshot(12345); } finally { pool.drain(); } } }