Invalid memory access of location with Rococoa - java

I've been trying to code a simple screenshot application using rococoa (java to osx cocoa api library), 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. The line that is causing the crash is:
int[] data = pointer.getIntArray(0, bytesPerPlane / 4);
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!
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"));
}
}

Found the problem.
The last use of 'imageRep' is on the line
"com.sun.jna.Pointer pointer = imageRep.bitmapData();".
After this, imageRep is fair game for the Java garbage collector. And if it hits in
before we are done using 'pointer', the backing buffer it's pointing to may/will get
freed, causing bad things to happen.
To fix it, adding an extra set of retain/release for imageRep does the job, or alternatively
adding any reference to it to the end of the method.

Possibly related, possibly not: NSBitmapImageRep descends from NSImageRep, not directly from NSObject.

Related

About having various constructors and parameters for java

I have written the instructions below and till now, I've came up with having two parameters and letting the method to assign the value and retrieving it. However, one of the instruction I had to follow was to include one constructor with no parameters, so I'm wondering what statement should I make inside the constructor without any parameters. It would be wonderful if anyone gives be a instruction. This is the code I've came up so far.
public class Rectangle {
//first constructor no parameters
//public<class name> (<parameters>)<statements>}
//two parameters one for length, one for width
//member variables store the length and the width
//member methods assign and retrieve the length and width
//returning the area and perimeter
static int recPerimeter(int l, int w) {
return 2*(l+w);
}
static int recArea(int l, int w) {
return l*w;
}
public static void main(String[] args) {
int p = recPerimeter(5, 3);
System.out.println("Perimeter of the rectangle : " + p);
int a = recArea(5,3);
System.out.println("Area of the rectangle : " + a);
}
}
First off, I would take some time to read the java tutorials. At least the "Covering the Basics"
There is a ton wrong with your example. You should store the the attributes of a rectangle - width and length as data members of the class which will get initialized with values through the constructors. If a default constructor is called with no values, then set the attributes to whatever you want. I set them to zero in the example.
Also, you need to normally create an instance of your class and then access it. Big red flag if you are having to prepend "static" to everything.
public class Rectangle {
private int recLength;
private int recWidth;
public Rectangle() {
recLength = 0;
recWidth = 0;
}
public Rectangle( int l, int w ) {
recLength = l;
recWidth = w;
}
public int calcPerimeter() {
return 2*(recLength+recWidth);
}
public int calcArea() {
return recLength*recWidth;
}
public static void main (String [] args) {
Rectangle rec = new Rectangle(5,3);
System.out.println("Perimeter = "+ rec.calcPerimeter());
System.out.println("area = " + rec.calcArea());
}
}

Java class values getting overridden when calling constructor in a test case / different class

I have test case that does something like this
TestSquare.java
public void testEncaps() {
Shifting shift = new Shifting(150,260);
Square s = new Square(new Point(101,201),130,140,shift);
Point p = s.getMidPoint();
p.x = 215;
p.y = 315;
assertEquals(new Point(101,201),s.getMidPoint());
}
So on the last line, the s.getMidPoint() don't equal to the Point(101, 201) but instead gets overridden with 215,315. Here is my constructor code and get method.
Square.java
public Square(Point newP, int width, int height, Shift newS) {
this.newMidPoint = newP;
this.newWidth = width;
this.newHeight = height;
this.newShift= newS;
}
public Point getMidPoint() {
return newMidPoint;
}
So, s.getMidPoint() shouldn't be replaced with the Point object. What am I doing wrong?
This two codes are in different class. So there is no main method in Square.java
If you don't want another class to be able to edit Square's middle, return a new Point:
public Point getMidPoint() {
return new Point(newMidPoint);
}
Then your test will run green.

Array of queues not compiling - cannot find symbol error

I'm trying to get a radix sort going with an array of queues to avoid long rambling switch statements but I'm having some trouble getting the array properly initialized. The constructor and an example of an implementation are given below.
I'm just getting a cannot find symbol error when I try to compile though.
public static radixj(){
IntQueue[] buckets = new IntQueue[10];
for (int i = 0; i < 10; i++)
buckets[i] = new IntQueue();
}
public static void place(int temp, int marker)
{
int pos = temp % marker;
buckets[pos].put(temp);
}
I'm pretty sure it is a really simple mistake that I'm making but I can't find it. Any help would be greatly appreciated.
In your code
IntQueue[] buckets = new IntQueue[10];
is a local variable to the function
public static radixj()
which must have a return type
public static void radixj()
So then you can't use it in another function
buckets[pos].put(temp);
You should declare a static class variable
class Foo {
static IntQueue[] buckets = new IntQueue[10];
...
and access it using: Foo.buckets
class Foo {
public static IntQueue[] buckets = new IntQueue[10];
public static void radixj() {
for (int i = 0; i < 10; i++) {
Foo.buckets[i] = new IntQueue();
}
}
public static void place(int temp, int marker) {
int pos = temp % marker;
Foo.buckets[pos].put(temp);
}
}
the return type in radixj() is missing and buckets cannot be resolved to a variable

Calling a method from a class array gives NullPointerException

I've been searching a lot for this problem and I can't find a solution. I'm trying to build a mini-game and I have a method for creating platforms. I have a class with every platform parameters, and I made a class array so i can have multiple platforms at the same time.
Problem: When I try to call the method for constructing the platform by sending the parameters I want, it gives me a NullPointerException. The method was working before, but with everything static and so i couldnt have multiple instances of that class, and now I removed the static fields from the platform class and it gives me the NullPointerException every time I call the method.
I copied the part of the code that gives me the error, the error goes the following way:
public static void main(String[] args) {
Game ex = new Game();
new Thread(ex).start();
}
In Game class:
public Load_Stage load = new Load_Stage();
public Game() {
-other variables initializatin-
Initialize_Items();
load.Stage_1(); // <--- problem this way
In Load_Stage class:
public class Load_Stage {
public Platforms plat = new Platforms();
public void Stage_1(){
Stage_Builder.Build_Platform(200, 500, 300, plat.platform1);
Stage_Builder.Build_Platform(100, 200, 100, plat.platform1);
}
}
And inside the Stage_Builder class:
public class Stage_Builder {
public static final int max_platforms = 10;
public static Platform_1[] p1 = new Platform_1[max_platforms];
public static boolean[] platform_on = new boolean[max_platforms];
public Stage_Builder() {
for (int c = 0; c < platform_on.length; c++) {
platform_on[c] = false;
}
}
public static void Build_Platform(int x, int y, int width, ImageIcon[] type) { // BUILDS A PLATFORM
for (int b = 0; b < max_platforms; b++) {
if (platform_on[b] == false) {
p1[b].Construct(x, y, width, type); // <-- NullPointerException here
platform_on[b] = true;
break;
}
}
}
}
Thanks beforehand.
EDIT: Here's the Platform_1 class (sorry for forgetting about it):
public class Platform_1 {
private int platform_begin_width = 30;
private int platform_middle_width = 20;
public int blocks_number = 0;
public ImageIcon[] platform_floors = new ImageIcon[500];
private int current_width = 0;
public int [] platform_x = new int [500];
public int platform_y = 0;
public int platform_width = 0;
public void Construct(int x, int y, int width, ImageIcon [] type) {
platform_width = width;
platform_y = y;
for (int c = 0; current_width <= platform_width; c++) {
if (c == 0) {
platform_x[c] = x;
platform_floors[c] = type[0];
current_width += platform_begin_width;
} else if ((current_width + platform_middle_width) > platform_width) {
platform_floors[c] = type[2];
blocks_number = c + 1;
platform_x[c] = current_width + x;
current_width += platform_middle_width;
} else {
platform_floors[c] = type[1];
platform_x[c] = current_width + x;
current_width += platform_middle_width;
}
}
}
}
And the Platforms class:
public class Platforms {
public ImageIcon[] platform1 = {new ImageIcon("Resources/Sprites/Stage_Objects/Platform1/begin.png"),
new ImageIcon("Resources/Sprites/Stage_Objects/Platform1/middle.png"),
new ImageIcon("Resources/Sprites/Stage_Objects/Platform1/end.png")};
}
The problem and solution are both obvious.
public static Platform_1[] p1 = new Platform_1[max_platforms];
After this line of code executes, p1 is an array of references of type Platform_1 that are all null.
Executing this line of code tells you so right away:
p1[b].Construct(x, y, width, type); // <-- NullPointerException here
The solution is to intialize the p1 array to point to non-null instances of Platform_1.
Something like this would work:
for (int i = 0; < p1.length; ++i) {
p1[i] = new Platform1();
}
I'm not seeing where you put things in the p1 array in the Stage_Builder class.
Another possibility (unlikely, but possible if you haven't shown everything) is that something in the Platform class, which you didn't show, is not initialized, and is breaking when you call Construct.
Also, the following seems problematic
public static Platform_1[] p1 = new Platform_1[max_platforms];
public static boolean[] platform_on = new boolean[max_platforms];
public Stage_Builder() {
for (int c = 0; c < platform_on.length; c++) {
platform_on[c] = false;
}
}
it appears you declare static variables p1 and platform_on, but you only populate platform_on in a constructor. So the first time you create a Stage_Builder instance, you populate one static array with all false, and don't put anything in the other static array...
Populate those static variables in a static block
// static var declarations
static {
// populate static arrays here.
}
The array you are calling a message on was never filled.
You have
public static Platform_1[] p1 = new Platform_1[max_platforms];
so p1 is
p1[0] = null
p1[1] = null
.
.
.
p1[max_platforms] = null
You try to call
p1[b].Construct(x, y, width, type);
which is
null.Construct(...);
You need to initialize that index on the array first.
p1[b] = new Platform_1();
p1[b].Construct(...);
First of all, your problem is that p1[b] is most likely null, as duffymo pointed out.
Secondly, you are using arrays in a really weird way. What about
a) delete Stage_Builder
b) Instead, have an ArrayList somewhere
c) The equivalent of Build_Platform1() look like this, then:
p1.add(new Platform1(x, y, width, type);
d) no if on[i], no max_platforms, no for loop to add a platform (the latter is a bad performance problem if you actually have a few hundret platforms)

Returning an array from a Java method

I am trying to return two numbers from this method. I thought this was correct. Where am I going wrong?
public int[] getDimension() {
int shapeWidth = 0;
int shapeHeight = 0;
// .....
int[] result = new int[] {shapeWidth, shapeHeight};
return result;
}
And then at a calling site, is this correct?
public int getWidth() {
return getDimension()[0];
}
I am asking because I believe there's a bug but I don't see it.
That's fine. Short but complete program to demonstrate it working:
public class Test {
public static void main(String args[]) {
int width = getDimension()[0];
System.out.println(width);
}
public static int[] getDimension() {
int shapeWidth = 5;
int shapeHeight = 10;
int[] result = new int[] {shapeWidth, shapeHeight};
return result;
}
}
You can make the result declaration line slightly simpler, by the way:
int[] result = {shapeWidth, shapeHeight};
Rather than using an array, I would recommend using a class
class Dimensions {
private int width;
private int height;
public Dimensions(int width, int height) {
this.width = width;
this.height = height;
}
// add either setters and getters
// or better yet, functionality methods instead
}
This will give you compile time referential integrity, which is much better than inferring based on "we know index 0 is width and index 1 is height".
If you still want to use an array, Jon's answer is spot on.
Your code looks fine, but try not to use an array if you only need a pair.
Since Java doesn't have tuples/pairs you have to implement them, but it's pretty easy. Refer to this question for a possible implementation.
public class Test {
public static void main(String args[]) {
int width = getDimension().getLeft();
System.out.println(width);
}
public static Pair<Integer, Integer> getDimension() {
int shapeWidth = 5;
int shapeHeight = 10;
return new Pair<Integer, Integer>(shapeWidth, shapeHeight);
}
}
This is better than a Dimension class, because you can use it everywhere in your code.

Categories