java - StackOverflowError while saving and loading my object in android -
i'm writing android program , ran problem.
my program serves create graphs, run specific algorithms on them (dijsktra, belmanford, etc.), save graphs sd card , loading them back.
the problem: if save little bigger, more complex graph stackoverflow error..
serialization:
public void createexternalstoragepublicgraph(string filename) { file dir = environment.getexternalstoragepublicdirectory("grapher"); try { if (!dir.exists()) { dir.mkdirs(); } file file = new file(dir, filename); fileoutputstream fileoutputstream = new fileoutputstream(file); objectoutputstream objectoutputstream = new objectoutputstream(fileoutputstream); objectoutputstream.writeobject(graphdrawerview.getgraph()); objectoutputstream.close(); } catch (ioexception e) { log.w("externalstorage", "error writing" + filename, e); } }
deserialization:
public graph loadexternalstoragepublicgraph(string filename) { file file = new file(environment.getexternalstoragepublicdirectory("grapher"), filename); graph graph = null; try { fileinputstream fint = new fileinputstream(file); objectinputstream ois = new objectinputstream(fint); graph = (graph) ois.readobject(); ois.close(); } catch (exception e) { log.e("deserialization error:", e.getmessage()); e.printstacktrace(); } return graph; }
graph class:
package com.cslqaai.grapher; import android.util.log; import java.io.serializable; import java.util.linkedlist; public class graph implements serializable { private string name; private boolean directed = false; private boolean weighted = false; private linkedlist<vertex> vertexes = new linkedlist<vertex>(); private linkedlist<edge> edges = new linkedlist<edge>(); // -------------------------------------------------------------------------------------------------------------------------------------- public graph(boolean weighted, boolean directed) { this.directed = directed; this.weighted = weighted; } // -------------------------------------------------------------------------------------------------------------------------------------- public void add(abstractgraphobject ago) { if (ago instanceof vertex) { this.vertexes.add((vertex) ago); } else if (ago instanceof edge) { this.edges.add((edge) ago); } else { } } // -------------------------------------------------------------------------------------------------------------------------------------- public boolean isweighted() { return this.weighted; } // -------------------------------------------------------------------------------------------------------------------------------------- public boolean isdirected() { return this.directed; } // --------------------------------------------------------------------------------------------------------------------------------------\ public linkedlist<edge> getedges() { return this.edges; } // -------------------------------------------------------------------------------------------------------------------------------------- public linkedlist<vertex> getvertexes() { return this.vertexes; } // -------------------------------------------------------------------------------------------------------------------------------------- public void reset() { (int = 0; < this.edges.size(); i++) { this.edges.get(i).setcolortodefault(); } } // -------------------------------------------------------------------------------------------------------------------------------------- void remove(abstractgraphobject ago) { if (ago instanceof vertex) { log.d("graph", "remove vertex graph"); this.vertexes.remove((vertex) ago); } else if (ago instanceof edge) { log.d("graph", "remove edge graph"); this.edges.remove((edge) ago); } } // -------------------------------------------------------------------------------------------------------------------------------------- public void setweighted(boolean weighted) { this.weighted = weighted; } // -------------------------------------------------------------------------------------------------------------------------------------- public void setdirected(boolean directed) { this.directed = directed; } // -------------------------------------------------------------------------------------------------------------------------------------- public string getname() { return this.name; } // -------------------------------------------------------------------------------------------------------------------------------------- public void setname(string name) { this.name = name; } } // ----------------------------------------------------------------------------------------------------------------------------------------
vertex class:
package com.cslqaai.grapher; import android.graphics.canvas; import android.graphics.color; import android.graphics.paint; import android.graphics.typeface; import java.util.arraylist; import java.util.iterator; import java.util.linkedlist; public class vertex extends abstractgraphobject { public static final int radius_size = 20; public static final int surrounding_radius_size = 30; private static layer defaultvertexlayer = abstractgraphobject.defaultlayer; private static int no = 0; private static paint paint = new paint(paint.anti_alias_flag); private static paint paintcolored = new paint(paint.anti_alias_flag); private static paint textpaint = new paint(paint.anti_alias_flag); private static paint textbgpaint = new paint(paint.anti_alias_flag); private final int id; private string name = null; private coord coord; private coord cachedcoord; private arraylist<edge> edges = new arraylist<edge>(); private boolean colored = false; // -------------------------------------------------------------------------------------------------------------------------------------- static { vertex.paint.setcolor(0xff0ff5f5); vertex.paintcolored.setcolor(color.red); vertex.textpaint.setstyle(paint.style.fill); vertex.textpaint.setcolor(color.black); vertex.textpaint.settextalign(paint.align.center); vertex.textpaint.settextsize(20); vertex.textpaint.settypeface(typeface.create("helvetica", typeface.bold)); vertex.textbgpaint.setstyle(paint.style.fill); vertex.textbgpaint.setcolor(0xff0ff5f5); } // -------------------------------------------------------------------------------------------------------------------------------------- public vertex(coord coord) { super(vertex.defaultvertexlayer); this.id = vertex.no++; this.coord = coord; this.recalculate(); } // -------------------------------------------------------------------------------------------------------------------------------------- public vertex(int x, int y) { this(new coord(x, y)); } // -------------------------------------------------------------------------------------------------------------------------------------- @override public void recalculate() { this.cachedcoord = new coord(math.round((vertex.basex + this.coord.getx()) * vertex.scalefactor), math.round((vertex.basey + this.coord.gety()) * vertex.scalefactor)); this.onscreen = this.cachedcoord.getx() + vertex.radius_size > 0 && this.cachedcoord.gety() + vertex.radius_size > 0 && this.cachedcoord.getx() - vertex.radius_size < vertex.screenwidth && this.cachedcoord.gety() - vertex.radius_size < this.cachedcoord.gety(); } // -------------------------------------------------------------------------------------------------------------------------------------- public coord getcoord() { return this.coord; } // -------------------------------------------------------------------------------------------------------------------------------------- public coord getcachedcoord() { return this.cachedcoord; } // -------------------------------------------------------------------------------------------------------------------------------------- public int getradiussize() { return vertex.radius_size; } // -------------------------------------------------------------------------------------------------------------------------------------- @override public void draw(canvas canvas) { this.recalculate(); if (!this.onscreen) { return; } canvas.drawcircle(this.cachedcoord.getx(), this.cachedcoord.gety(), vertex.radius_size * vertex.scalefactor, vertex.paint); if (this.name != null) { float width = vertex.textpaint.measuretext(this.name) + 10; float height = vertex.textpaint.gettextsize() + 5; canvas.drawrect(this.cachedcoord.getx() - width / 2, this.cachedcoord.gety() - height / 2, this.cachedcoord.getx() + width / 2, this.cachedcoord.gety() + height / 2, vertex.textbgpaint); canvas.drawtext(this.name, this.cachedcoord.getx(), this.cachedcoord.gety() + height * 0.25f, vertex.textpaint); } } // -------------------------------------------------------------------------------------------------------------------------------------- private boolean searchingcoordon(float radius, float px, float py) { return this.onscreen && ((math.pow(px - this.cachedcoord.getx(), 2) + math.pow(py - this.cachedcoord.gety(), 2)) < (math.pow(radius * vertex.scalefactor, 2))); } // -------------------------------------------------------------------------------------------------------------------------------------- public boolean isoncoord(float px, float py) { return this.searchingcoordon(vertex.radius_size, px, py); } // -------------------------------------------------------------------------------------------------------------------------------------- public boolean isincoordsurroundings(float px, float py) { return this.searchingcoordon(vertex.surrounding_radius_size, px, py); } // -------------------------------------------------------------------------------------------------------------------------------------- public void addedge(edge edge) { if (!this.edges.contains(edge)) { this.edges.add(edge); } } // -------------------------------------------------------------------------------------------------------------------------------------- public arraylist<edge> getedges() { return this.edges; } // -------------------------------------------------------------------------------------------------------------------------------------- public void removeedge(edge edge) { if (this.edges.contains(edge)) { this.edges.remove(edge); } } // -------------------------------------------------------------------------------------------------------------------------------------- public boolean hasedge(edge edge) { return this.edges.contains(edge); } // -------------------------------------------------------------------------------------------------------------------------------------- public static void setdefaultlayer(layer layer) { vertex.defaultvertexlayer = layer; } // -------------------------------------------------------------------------------------------------------------------------------------- public static layer getdefaultlayer() { return vertex.defaultvertexlayer; } // -------------------------------------------------------------------------------------------------------------------------------------- public static void remove(vertex vertex) { iterator<edge> edges = vertex.getedges().iterator(); while (edges.hasnext()) { edge e = edges.next(); edges.remove(); edge.remove(e); } vertex.defaultvertexlayer.remove(vertex); if (vertex.graph != null) { vertex.graph.remove(vertex); } } // -------------------------------------------------------------------------------------------------------------------------------------- public boolean hasname() { return this.name != null; } // -------------------------------------------------------------------------------------------------------------------------------------- public void setname(string name) { this.name = name; } // -------------------------------------------------------------------------------------------------------------------------------------- public string getname() { return this.name; } // -------------------------------------------------------------------------------------------------------------------------------------- public int getid() { return this.id; } // -------------------------------------------------------------------------------------------------------------------------------------- }
edge class:
package com.cslqaai.grapher; import android.graphics.*; import java.util.arraylist; import java.util.linkedlist; public class edge extends abstractgraphobject { public static final float stroke_width = 5f; public static final float sensor_width = 50f; public static final float surrounding_sensor_width = 15f; public static final float triangle_size = 8f; private static paint paint = new paint(paint.anti_alias_flag); private static paint paintcolored = new paint(paint.anti_alias_flag); private static paint textpaint = new paint(paint.anti_alias_flag); private static paint textbgpaint = new paint(paint.anti_alias_flag); private static layer defaultedgelayer = abstractgraphobject.defaultlayer; private static int no = 0; private final int id; private int weight = 1; private coord cachedsourcecoord; private coord cachedtargetcoord; private vertex sourcevertex; private vertex targetvertex; private coord weightcoord; private boolean colored = false; // -------------------------------------------------------------------------------------------------------------------------------------- static { edge.paint.setcolor(0xffffffff); edge.paint.setstrokewidth(edge.stroke_width * edge.scalefactor); edge.paint.setstrokecap(paint.cap.round); edge.paint.setstyle(paint.style.fill_and_stroke); edge.paintcolored.setcolor(0xffff0000); edge.paintcolored.setstrokewidth(edge.stroke_width * edge.scalefactor); edge.paintcolored.setstrokecap(paint.cap.round); edge.paintcolored.setstyle(paint.style.fill_and_stroke); edge.textpaint.setstyle(paint.style.fill); edge.textpaint.setcolor(color.black); edge.textpaint.settextalign(paint.align.center); edge.textpaint.settextsize(20); edge.textpaint.settypeface(typeface.create("helvetica", typeface.bold)); edge.textbgpaint.setstyle(paint.style.fill); edge.textbgpaint.setcolor(color.white); } // -------------------------------------------------------------------------------------------------------------------------------------- public edge(vertex sourcevertex, vertex targetvertex) { super(edge.defaultedgelayer); this.id = edge.no++; this.sourcevertex = sourcevertex; this.targetvertex = targetvertex; this.sourcevertex.addedge(this); this.targetvertex.addedge(this); this.recalculate(); } // -------------------------------------------------------------------------------------------------------------------------------------- public void recalculate() { this.cachedsourcecoord = new coord(math.round((edge.basex + this.sourcevertex.getcoord().getx()) * edge.scalefactor), math.round((edge.basey + this.sourcevertex.getcoord().gety()) * edge.scalefactor)); this.cachedtargetcoord = new coord(math.round((edge.basex + this.targetvertex.getcoord().getx()) * edge.scalefactor), math.round((edge.basey + this.targetvertex.getcoord().gety()) * edge.scalefactor)); line line = new line(this.cachedsourcecoord, this.cachedtargetcoord); this.weightcoord = line.getmiddle(); this.onscreen = edge.screenbottomline.hasintersection(line) || edge.screenleftline.hasintersection(line) || edge.screenrightline.hasintersection(line) || edge.screentopline.hasintersection(line) || this.cachedsourcecoord.getx() > 0 && this.cachedsourcecoord.getx() < edge.screenwidth && this.cachedsourcecoord.gety() > 0 && this.cachedsourcecoord.gety() < edge.screenheight || this.cachedtargetcoord.getx() > 0 && this.cachedtargetcoord.getx() < edge.screenwidth && this.cachedtargetcoord.gety() > 0 && this.cachedtargetcoord.gety() < edge.screenheight; } // -------------------------------------------------------------------------------------------------------------------------------------- @override public void draw(canvas canvas) { this.recalculate(); if (!this.onscreen) { return; } canvas.drawline(this.cachedsourcecoord.getx(), this.cachedsourcecoord.gety(), this.cachedtargetcoord.getx(), this.cachedtargetcoord.gety(), this.colored ? edge.paintcolored : edge.paint); if (edge.graph != null && edge.graph.isdirected()) { line line = new line(this.cachedsourcecoord, this.cachedtargetcoord); coord v = line.getvector(); float t = (float) ((vertex.radius_size + 5) / math.sqrt(math.pow(v.getx(), 2) + math.pow(v.gety(), 2))); coord t1 = new coord((int) (this.cachedtargetcoord.getx() - t * v.getx()), (int) (this.cachedtargetcoord.gety() - t * v.gety())); if (!line.isonline(t1)) { t1 = new coord((int) (this.cachedtargetcoord.getx() + t * v.getx()), (int) (this.cachedtargetcoord.gety() + t * v.gety())); } t = (float) ((vertex.radius_size + 5 + edge.triangle_size) / math.sqrt(math.pow(v.getx(), 2) + math.pow(v.gety(), 2))); coord p = new coord((int) (this.cachedtargetcoord.getx() - t * v.getx()), (int) (this.cachedtargetcoord.gety() - t * v.gety())); if (!line.isonline(p)) { p = new coord((int) (this.cachedtargetcoord.getx() + t * v.getx()), (int) (this.cachedtargetcoord.gety() + t * v.gety())); } v = line.getnormalvector().getvector(); t = (float) ((edge.triangle_size) / math.sqrt(math.pow(v.getx(), 2) + math.pow(v.gety(), 2))); coord t2 = new coord((int) (p.getx() - t * v.getx()), (int) (p.gety() - t * v.gety())); coord t3 = new coord((int) (p.getx() + t * v.getx()), (int) (p.gety() + t * v.gety())); path path = new path(); path.setfilltype(path.filltype.even_odd); path.moveto(t1.getx(), t1.gety()); path.lineto(t2.getx(), t2.gety()); path.lineto(t3.getx(), t3.gety()); path.lineto(t1.getx(), t1.gety()); path.close(); canvas.drawpath(path, edge.paint); } if (edge.graph != null && edge.graph.isweighted()) { float width = edge.textpaint.measuretext(integer.tostring(this.weight)) + 10; float height = edge.textpaint.gettextsize() + 5; canvas.drawrect(this.weightcoord.getx() - width / 2, this.weightcoord.gety() - height / 2, this.weightcoord.getx() + width / 2, this.weightcoord.gety() + height / 2, edge.textbgpaint); canvas.drawtext(integer.tostring(this.weight), this.weightcoord.getx(), this.weightcoord.gety() + height * 0.25f, edge.textpaint); } } // -------------------------------------------------------------------------------------------------------------------------------------- private boolean searchingcoordon(float distance, float px, float py) { coord p = new coord((int) px, (int) py); coord v = (new line(this.cachedsourcecoord, this.cachedtargetcoord)).getnormalvector().getvector(); float t = (float) (distance / math.sqrt(math.pow(v.getx(), 2) + math.pow(v.gety(), 2))); coord c1 = new coord((int) (this.cachedsourcecoord.getx() - t * v.getx()), (int) (this.cachedsourcecoord.gety() - t * v.gety())); coord c2 = new coord((int) (this.cachedsourcecoord.getx() + t * v.getx()), (int) (this.cachedsourcecoord.gety() + t * v.gety())); coord c3 = new coord((int) (this.cachedtargetcoord.getx() - t * v.getx()), (int) (this.cachedtargetcoord.gety() - t * v.gety())); coord v1 = new coord(c2.getx() - c1.getx(), c2.gety() - c1.gety()); coord v2 = new coord(c3.getx() - c1.getx(), c3.gety() - c1.gety()); v = coord.minus(p, c1); return this.onscreen && 0 <= coord.dotproduct(v, v1) && coord.dotproduct(v, v1) <= coord.dotproduct(v1, v1) && 0 <= coord.dotproduct(v, v2) && coord.dotproduct(v, v2) <= coord.dotproduct(v2, v2); } // -------------------------------------------------------------------------------------------------------------------------------------- public boolean isoncoord(float px, float py) { return this.searchingcoordon(edge.sensor_width / 2, px, py); } // -------------------------------------------------------------------------------------------------------------------------------------- public boolean isincoordsurroundings(float px, float py) { return this.searchingcoordon(edge.surrounding_sensor_width / 2, px, py); } // -------------------------------------------------------------------------------------------------------------------------------------- public vertex getsourcevertex() { return this.sourcevertex; } // -------------------------------------------------------------------------------------------------------------------------------------- public vertex gettargetvertex() { return this.targetvertex; } // -------------------------------------------------------------------------------------------------------------------------------------- public static void setdefaultlayer(layer layer) { edge.defaultedgelayer = layer; } // -------------------------------------------------------------------------------------------------------------------------------------- public static layer getdefaultlayer() { return edge.defaultedgelayer; } // -------------------------------------------------------------------------------------------------------------------------------------- public static void remove(edge edge) { edge.getsourcevertex().removeedge(edge); edge.gettargetvertex().removeedge(edge); edge.defaultedgelayer.remove(edge); if (edge.graph != null) { edge.graph.remove(edge); } } // -------------------------------------------------------------------------------------------------------------------------------------- public void setweight(int weight) { this.weight = weight; } // -------------------------------------------------------------------------------------------------------------------------------------- public int getweight() { return this.weight; } // -------------------------------------------------------------------------------------------------------------------------------------- public int getid() { return this.id; } // -------------------------------------------------------------------------------------------------------------------------------------- public void setcolored() { this.colored = true; } // -------------------------------------------------------------------------------------------------------------------------------------- public void setcolortodefault() { this.colored = false; } // -------------------------------------------------------------------------------------------------------------------------------------- public static arraylist<edge> getedgesbetween(vertex v1, vertex v2) { arraylist<edge> edges = v1.getedges(); arraylist<edge> edgesret = new arraylist<edge>(); (edge edge : edges) { if (v2.hasedge(edge)) { edgesret.add(edge); } } return edges; } // -------------------------------------------------------------------------------------------------------------------------------------- }
the reason "normal" serialization each entry recursively invoke writeobject(e), , long lists give stackoverflowerror. iterative serialization avoids this.
i found on stackoverflow. think problem related long linkedlists..
any ideas, advices how serialize , deserialize graph object?
thank in advance!
as fast fix, try substuting linkedlist list implemetnations arraylists. didn't give enough details (the exact exception , implementations of vertexes , edges helpful), quoted might right: run out of memory because of recursive calls. didn't try, arraylist default java serialization avoid issue.
for solution, serialization methods of graph objects re-implemented, or tested , more memory efficient library used (eg. kryo).
this question helpful.
Comments
Post a Comment