وصول ذاكرة غير صالحة من الموقع باستخدام Rococoa

StackOverflow https://stackoverflow.com/questions/1655145

  •  11-09-2019
  •  | 
  •  

سؤال

لقد كنت أحاول رمز تطبيق لقطة شاشة بسيطة باستخدام Rococoa (Java To Library ASX Cocoa API)، وتمكنت من الحصول على بقدر ما تأخذ في الواقع لقطة الشاشة، ثم حفظه إلى ملف. لسوء الحظ، مرة واحدة في حين، فشل التطبيق باستخدام خطأ "وصول ذاكرة غير صالح للموقع ...". أفترض أن هذا يرجع إلى شيء يجمع القمامة، لأنني فشل في الاحتفاظ بالمرجع الحي. الخط الذي يسبب التعطل هو: int [] البيانات = pointer.getintray (0، bytesperplane / 4)؛

أنا حقا لم أرمز أي شيء بهدف ج، وبدأ فقط مع روكوكو، لذلك أجد نفسي في حيرة مع هذا. لقد قمت بنسخ التعليمات البرمجية ذات الصلة أدناه، وسوف نقدر حقا أي مساعدة في هذا!


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"));
    }
}
هل كانت مفيدة؟

المحلول

وجدت المشكلة.

الاستخدام الأخير من "ImageReP" موجود على الخط "com.sun.jna.pointer = imagerep.bitmapdata ()؛". بعد هذا، Imagerep هو لعبة عادلة لمعجم القمامة Java. وإذا كان يضربه قبل أن ننتهي باستخدام "المؤشر"، فإن المخزن المؤقت للدعم يشير إلى مايو / سيحصل على إطلاق سراحه، مما تسبب في حدوث أشياء سيئة. لإصلاحه، قم بإضافة مجموعة إضافية من الاحتفاظ / الإصدار عن ImageREP هل الوظيفة، أو بدلا من ذلك إضافة أي إشارة إليها إلى نهاية الطريقة.

نصائح أخرى

ربما ترتبط، ربما لا: nsbitmapimagerep ينحدر من nsimagerep، وليس مباشرة من nsobject.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top