2009-10-31 3 views
1

Я пытался создать простую программу для скриншотов, используя rococoa (java to osx cocoa api library), и ей удалось получить практически весь снимок экрана, а затем сохранить его на файл. К сожалению, время от времени приложение выходит из строя с ошибкой «Недопустимый доступ к памяти местоположения ...». Я предполагаю, что это связано с тем, что собирался сбор мусора, потому что я не могу сохранить ссылку в живых. Строка, вызывающая сбой: int [] data = pointer.getIntArray (0, bytesPerPlane/4);Недопустимый доступ к памяти для местоположения с помощью Rococoa

Я действительно ничего не кодировал с Objective C и просто начал с rococoa, так что я нахожу себя в замешательстве с этим. Я скопировал соответствующий код ниже и был бы очень признателен за любую помощь в этом!


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); 
     // The crash always happens when calling 'getIntArray' in the next line. 
     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")); 
    } 
} 

ответ

2

Обнаружена проблема.

Последнее использование 'imageRep' находится на линии "com.sun.jna.Pointer pointer = imageRep.bitmapData();". После этого imageRep - это честная игра для сборщика мусора Java. И если он попадает в , прежде чем мы закончим с помощью «указателя», буфер резервной копии, указывающий на возможность/может получить , освобождается, что приводит к возникновению плохих вещей. Чтобы исправить это, добавление дополнительного набора удержания/освобождения для imageRep выполняет задание или, альтернативно, , добавляя любую ссылку на него до конца метода.

0

Возможно связаны, возможно, не так: NSBitmapImageRep спускается с NSImageRep, а не непосредственно из NSObject.

Смежные вопросы