문제

Rococoa (Java to OSX Cocoa API 라이브러리)를 사용하여 간단한 스크린 샷 응용 프로그램을 코딩하려고했으며 실제로 스크린 샷을 찍는 것까지 얻은 다음 파일에 저장했습니다. 불행히도, 가끔 '위치에 대한 잘못된 메모리 액세스 ...'오류로 응용 프로그램이 실패합니다. 나는 이것이 참조를 유지하지 못하기 때문에 쓰레기를 수집 한 것이기 때문이라고 가정합니다. 충돌을 일으키는 라인은 다음과 같습니다. int [] data = pointer.getIntArray (0, bytesperplane / 4);

나는 실제로 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"));
    }
}
도움이 되었습니까?

해결책

문제를 발견했습니다.

'imageerep'의 마지막 사용은 "com.sun.jna.pointer pointer = imageerep.bitmapdata ();"라인에 있습니다. 그 후, Imagerep은 Java Garbage Collector의 공정한 게임입니다. 그리고 우리가 '포인터'를 사용하여 끝나기 전에 닿는 경우, 백킹 버퍼는 5 월을 가리키거나 해방 될 것이므로 나쁜 일이 발생하게됩니다. 이를 해결하기 위해 ImageRep에 대한 추가 보유/릴리스 세트를 추가하면 작업이 끝날 때까지 참조를 추가합니다.

다른 팁

아마도 관련이있을 수 있습니다. nsbitmapimagerep는 nsobject에서 직접가 아니라 nsimagerep에서 내려갑니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top