Open GoogleCodeExporter opened 9 years ago
I see no reason why cytoscape.visual.customgraphic.CustomGraphicsManager for
ex, is getting serialized or java.awt.EventDispatchThread. They are not
encapsulated or referred to by the code in the Runnable().
Original comment by nikhilsa...@gmail.com
on 19 Nov 2012 at 9:38
Is your code running on the Oracle/OpenJDK JVM, or a different JVM? The stack
trace looks unusual indeed.
It's an error serializing the object with the Kryo serializer. First of all we
can try to figure it out the issue here, and failing that, we can get in touch
with the Kryo devs.
It does look like it's trying to serialize a thread somehow.
If you're serializing a Callable or Runnable, one thing to be aware of is that
anonymous classes and inner classes retain a reference to their outer/enclosing
classes. If the outer class extends another class, furthermore they will
indirectly retain references to fields in the superclass. it might be the case
that the outer class or its superclass has a reference to a thread somehow.
Static nested classes do not retain references to their enclosing classes.
Could you try converting your Callable/Runnable to a nested static class
instead? You will need to add fields into that class for the variables/data you
actually want to send, and (say) pass them in via the constructor.
Original comment by ni...@npgall.com
on 19 Nov 2012 at 9:58
Here is a version of HelloWorld using a static instead of an anonymous Runnable:
public class HelloWorld {
// Assumes remote machine is called bob...
public static void main(String[] args) {
QuickTask.execute("bob", new HelloWorldCommand());
}
static class HelloWorldCommand implements Runnable {
@Override
public void run() {
System.out.println("Hello World");
}
}
}
Here is a version based on a static Callable instead:
public class HelloWorld2 {
// Assumes remote machine is called bob...
public static void main(String[] args) {
Long time = QuickTask.execute("bob", new HelloWorldCommand());
System.out.println(time);
}
static class HelloWorldCommand implements Callable<Long> {
@Override
public Long call() {
System.out.println("Hello World");
return System.currentTimeMillis();
}
}
}
Original comment by ni...@npgall.com
on 19 Nov 2012 at 10:03
[deleted comment]
The above works. It seems that Kryo was trying to serialize the thread
reference and hitting the 100mb limit. It is still unclear why the thread was
getting serialized only in the case of a Runnable and not a Callable.
Original comment by nikhilsa...@gmail.com
on 19 Nov 2012 at 10:09
Okay glad that sorted it.
My guess is that yes Kryo found a Thread object in the outer class or a
superclass, and once it started to serialize that, it found objects referenced
by that thread, which could include lots of ThreadLocal objects set by the
application. That might explain why you see unexpected objects from your
application mentioned in the stack trace.
I don't know why you got different behaviour when using a Callable vs a
Runnable. In theory they should not differ much in terms of serialization.
Perhaps some minor difference put it over the edge somehow.
To prevent this issue happening in future, I'd like to configure a "blacklist"
of classes banned from serialization (such as Thread objects). That way instead
of this buffer limit exceeded message, we could throw a more informative
message. I'll get in touch with Kryo devs to find out how best to do that.
Thanks for reporting this! I'll open a separate issue for the serialization
blacklisting.
Original comment by ni...@npgall.com
on 19 Nov 2012 at 10:33
Marking this as Done, as the investigation is complete. Also re-wording the
title to match the findings.
The most likely cause seems to be specific to the host application framework,
Cytoscape, due to the way the plugin framework in that application is
structured.
It seems (although not definite) that Cytoscape stores a reference to a Thread
object in a superclass which Cytoscape plugins extend. Because of this,
Cytoscape plugin implementation classes inherit a reference to the Thread
object, and so do anonymous Runnables/Callables declared inside those classes.
The end result being that anonymous Runnables/Callables declared directly
inside classes which extend the Cytoscape framework, cannot be serialized.
A workaround is to declare the Callable/Runnable as a static nested class
instead of an anonymous class (so that they do not inherit fields), or to move
the method which creates the anonymous Runnable/Callable to a different class
which doesn't inherit from a Cytoscape class.
Mobility-RPC threw an exception with quite a vague message in this instance.
The follow-on ticket issue 7 is to improve the error message when an attempt is
made to serialize a thread.
Original comment by ni...@npgall.com
on 20 Nov 2012 at 2:20
Original issue reported on code.google.com by
nikhilsa...@gmail.com
on 19 Nov 2012 at 9:36