Getting NullPointerException when running drawing commands after reading Objects

I've written a program to visualize graphs, and I can serialize and save the graph, but when I load the graph, I get a NullPointerException the first time a drawing command is run. I've adjusted the code, and the problem does not involve any of the values that were read during the call to java.io.ObjectInputStream.readObject()

Here's the call that reads the graph object:

public void load(String filename) {
  println("Loading from " + filename);
  ObjectInputStream in = null;
  FileInputStream fis = null;
  try {
    fis = new FileInputStream(filename + ".graph");
    in = new ObjectInputStream(fis);
    g = (Graph)in.readObject();
    in.close();
  } catch (IOException e) {
    e.printStackTrace();
  } catch(ClassNotFoundException e) {
    e.printStackTrace();
  }
  g.printEdges();

}

Here are the serialization/deserialization routines in Graph:

private void writeObject(java.io.ObjectOutputStream out) throws IOException {
    out.writeObject(v);
    out.writeObject(e);
    out.writeBoolean(weighted);
    out.writeFloat(defaultVertexRadius);
    out.writeObject(colors);
    out.writeInt(defaultVertexColor);
    out.writeInt(defaultEdgeColor);
    out.writeFloat(closeToEdgeThreshold);
    out.writeFloat(edgeWeight);
    out.writeObject(mtx);
}  

 private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
    v = (Vertex[]) in.readObject();
    e = (Edge[]) in.readObject();
    weighted = in.readBoolean();
    defaultVertexRadius = in.readFloat();
    colors = (int[]) in.readObject();
    defaultVertexColor = in.readInt();
    defaultEdgeColor = in.readInt();
    closeToEdgeThreshold = in.readFloat();
    edgeWeight = in.readFloat();
    println("Read edgeWeight: " + edgeWeight);
    mtx = (byte[][])in.readObject();
  }

 private void readObjectNoData()  throws ObjectStreamException{
     println("Whoops, no data!");
 }

Here are the routines in Vertex

private void writeObject(java.io.ObjectOutputStream out) throws IOException {
    out.writeObject(label);
    out.writeFloat(labelx);
    out.writeFloat(labely);
    out.writeFloat(x);
    out.writeFloat(y);
    out.writeFloat(radius);
    out.writeInt(c);
}

private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
    label = (String)in.readObject();
    labelx = in.readFloat();
    labely = in.readFloat();
    x = in.readFloat();
    y = in.readFloat();
    radius = in.readFloat();
    c= in.readInt();
}

 private void readObjectNoData()  throws ObjectStreamException{
     println("Whoops, no data!");
 }

And here are the corresponding routines in Edge:

 private void writeObject(java.io.ObjectOutputStream out) throws IOException {
     out.writeInt(c);
     out.writeInt(s);
     out.writeInt(t);
     out.writeObject(weight);
     out.writeFloat(weightX);
     out.writeFloat(weightY);
     out.writeFloat(autoX);
     out.writeFloat(autoY);
 }

 private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
     c = in.readInt();
     s = in.readInt();
     t = in.readInt();
     weight = (String)in.readObject();
     weightX = in.readFloat();
     weightY = in.readFloat();
     autoX = in.readFloat();
     autoY = in.readFloat();
 }

 private void readObjectNoData() throws ObjectStreamException {
     println("Whoops, no data!");
 }

Here is the code that generates the NullPointerException:

public void drawEdge(int i) {
  println("edgeWeight: " + edgeWeight);
  println("v[e[i].s].x: " + v[e[i].s].x);
  println("e[i].c: " + e[i].c);
  float ew = edgeWeight;
  try {
    strokeWeight(ew);
  } catch(NullPointerException e) {
    e.printStackTrace();
  }
  stroke(color(0,0,255));

And here's the stack trace:

Loading from ab
Read edgeWeight: 3.0
0, 1
edgeWeight: 3.0
v[e[i].s].x: 100.0
e[i].c: 0
java.lang.NullPointerException
at graphMaker2$Graph.drawEdge(graphMaker2.java:634)
at graphMaker2$Graph.draw(graphMaker2.java:620)
at graphMaker2.draw(graphMaker2.java:71)
at processing.core.PApplet.handleDraw(PApplet.java:2386)
at processing.core.PGraphicsJava2D.requestDraw(PGraphicsJava2D.java:240)
at processing.core.PApplet.run(PApplet.java:2256)
at java.lang.Thread.run(Thread.java:745)

This last bit of code tells a short story. I initially thought that calling strokeWeight(edgeWeight) was the problem, since I'd just read edgeWeight as part of the graph. However I confirmed it had a value with a println(). Then I assigned that value to another variable, ew, and ran strokeWeight with that argument that certainly wasn't null, and that threw an NPE. I've now found that any drawing-related command, such as strokeWeight(), stroke(), and line() generates an NPE, even when given a constant argument.

Did ObjectInputStream.readObject() possibly overwrite some important Processing graphics-rendering object with null?

Answers

  • We can't possibly tell with such a tiny piece of code, no idea of the arrays involved and none of the data.

    println is your friend here - print everything before you use it. I'm guessing you are initialising the arrays but not the elements inside the array.

  • edited August 2015

    I should've been more clear. The println statements are my evidence that all of the data is present. What's happening is that stroke(), with a constant argument, throws a NPE. Same thing happens when I surround the stroke() command in a try block and the program runs line() later on. I'll add some more code, though.

  • edited August 2015

    what is this Graph / graphmaker2 code you're using?

    edit: ah, ok, that's your sketch. and you've pasted drawEdge().

    the only thing that looks suspicious is that the reference seems to expect strokeWeight() to be an integer.

    also, choose a better name than g for your variable, see if that helps. (istr that there's an object called g which is part of processing)

  • void setup() {
      size(100, 100, JAVA2D);
      g = new Object();
    }
    
    void draw() {
      line(0, 0, 100, 100);
    }
    

    for instance, here i don't define g but the error i get when i run it says 'cannot convert from Object to PGraphics' rather than 'g not defined' (i'm using 1.5.1 so the error might be different BUT it does suggest that g already exists)

  • edited August 2015

    That's interesting but still hasn't solved the problem. I replaced every instance of g with theGraph, and still get the same error. I did at one point accidentally miss one of the g's in the command writeObject(g) and it complained that PGraphics objects weren't serializable, but I've since changed the reference and the problem persists.

    I've had issues when writing Java code with Eclipse in which old versions of code are saved in some sort of cache, so that new code isn't always updated. Can that happen with the Processing IDE?

  • edited August 2015 Answer ✓

    I solved the problem by changing the way I serialized the my Object arrays. Here's the crux of it, for posterity:

    private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
    
        int vl = in.readInt();
            v = (Vertex[])expand(v, vl);
            for(int i = 0; i < vl; i++) {
             v[i] = new Vertex();
              v[i].readObject(in);
        }
    
    int el = in.readInt();
        e = (Edge[])expand(e, el);
        for(int i = 0; i < el; i++) {
          e[i] = new Edge();
          e[i].readObject(in);
    }
    

    In retrospect, maybe I could have left more of it the way it was if I'd just created default constructors.

Sign In or Register to comment.