phhoangbao / mobility-rpc

Automatically exported from code.google.com/p/mobility-rpc
0 stars 0 forks source link

"Buffer limit exceeded" in proprietary/Cytoscape application #6

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. Running the hello world code in the context of a proprietary application 
results in a series of exceptions. 

What is the expected output? What do you see instead?
I should see hello world in the console, instead I get a massive stacktrace 
like so:

[java] threads (java.lang.ThreadGroup)
     [java] group (java.util.concurrent.Executors$DefaultThreadFactory)
     [java] threadFactory (java.util.concurrent.ThreadPoolExecutor)
     [java] imageLoaderService
(cytoscape.visual.customgraphic.CustomGraphicsManager)
     [java] manager (cytoscape.visual.VisualMappingManager)
     [java] vmm (cytoscape.visual.ui.VizMapperMainPanel)
     [java] a (cytoscape.data.attr.util.MultiHashMapModel$AttrDefLisChain)
     [java] a (cytoscape.data.attr.util.MultiHashMapModel$AttrDefLisChain)
     [java] m_dataDefListener (cytoscape.data.attr.util.MultiHashMapModel)
     [java] mmap (cytoscape.data.CyAttributesImpl)
     [java] data (browser.DataTableModel)
     [java] dataModel (browser.ui.CyAttributeBrowserTable)
     [java]     at
com.esotericsoftware.kryo.Kryo.writeClassAndObject(Kryo.java:492)
     [java]     at
com.esotericsoftware.kryo.serialize.ArraySerializer.writeArray(ArraySerializer.j
ava:123)
     [java]     at
com.esotericsoftware.kryo.serialize.ArraySerializer.writeObjectData(ArraySeriali
zer.java:88)
     [java]     at
com.esotericsoftware.kryo.serialize.FieldSerializer.writeObjectData(FieldSeriali
zer.java:175)
     [java]     at
com.esotericsoftware.kryo.serialize.ReferenceFieldSerializer.writeObjectData(Ref
erenceFieldSerializer.java:52)
     [java]     at
com.esotericsoftware.kryo.serialize.FieldSerializer.writeObjectData(FieldSeriali
zer.java:175)
     [java]     at
com.esotericsoftware.kryo.serialize.ReferenceFieldSerializer.writeObjectData(Ref
erenceFieldSerializer.java:52)
     [java]     at
com.esotericsoftware.kryo.serialize.FieldSerializer.writeObjectData(FieldSeriali
zer.java:175)
     [java]     at
com.esotericsoftware.kryo.serialize.ReferenceFieldSerializer.writeObjectData(Ref
erenceFieldSerializer.java:52)
     [java]     at
com.esotericsoftware.kryo.serialize.FieldSerializer.writeObjectData(FieldSeriali
zer.java:175)
     [java]     at
com.esotericsoftware.kryo.serialize.ReferenceFieldSerializer.writeObjectData(Ref
erenceFieldSerializer.java:52)
     [java]     at
com.esotericsoftware.kryo.serialize.FieldSerializer.writeObjectData(FieldSeriali
zer.java:175)
     [java]     at
com.esotericsoftware.kryo.serialize.ReferenceFieldSerializer.writeObjectData(Ref
erenceFieldSerializer.java:52)
     [java]     at
com.esotericsoftware.kryo.serialize.FieldSerializer.writeObjectData(FieldSeriali
zer.java:175)
     [java]     at
com.esotericsoftware.kryo.serialize.ReferenceFieldSerializer.writeObjectData(Ref
erenceFieldSerializer.java:52)
     [java]     at
com.esotericsoftware.kryo.serialize.FieldSerializer.writeObjectData(FieldSeriali
zer.java:175)
     [java]     at
com.esotericsoftware.kryo.serialize.ReferenceFieldSerializer.writeObjectData(Ref
erenceFieldSerializer.java:52)
     [java]     at
com.esotericsoftware.kryo.serialize.FieldSerializer.writeObjectData(FieldSeriali
zer.java:175)
     [java]     at
com.esotericsoftware.kryo.serialize.ReferenceFieldSerializer.writeObjectData(Ref
erenceFieldSerializer.java:52)
     [java]     at
com.esotericsoftware.kryo.serialize.FieldSerializer.writeObjectData(FieldSeriali
zer.java:175)
     [java]     at
com.esotericsoftware.kryo.serialize.ReferenceFieldSerializer.writeObjectData(Ref
erenceFieldSerializer.java:52)
     [java]     at
com.esotericsoftware.kryo.serialize.FieldSerializer.writeObjectData(FieldSeriali
zer.java:175)
     [java]     at
com.esotericsoftware.kryo.serialize.ReferenceFieldSerializer.writeObjectData(Ref
erenceFieldSerializer.java:52)
     [java]     at
com.esotericsoftware.kryo.serialize.FieldSerializer.writeObjectData(FieldSeriali
zer.java:175)
     [java]     at
com.esotericsoftware.kryo.serialize.ReferenceFieldSerializer.writeObjectData(Ref
erenceFieldSerializer.java:52)
     [java]     at
com.esotericsoftware.kryo.serialize.FieldSerializer.writeObjectData(FieldSeriali
zer.java:175)
     [java]     at
com.esotericsoftware.kryo.serialize.ReferenceFieldSerializer.writeObjectData(Ref
erenceFieldSerializer.java:52)
     [java]     at
com.esotericsoftware.kryo.Kryo.writeClassAndObject(Kryo.java:489)
     [java]     ... 140 more
     [java] Caused by:
com.esotericsoftware.kryo.SerializationException: Buffer limit
exceeded writing object of type: java.awt.EventDispatchThread
     [java] Serialization trace:
     [java] busyThreadSet (sun.awt.AWTAutoShutdown)
     [java] target (java.lang.Thread)
     [java]     at
com.esotericsoftware.kryo.Kryo.writeClassAndObject(Kryo.java:492)
     [java]     at
com.esotericsoftware.kryo.serialize.CollectionSerializer.writeObjectData(Collect
ionSerializer.java:86)
     [java]     at
com.esotericsoftware.kryo.serialize.FieldSerializer.writeObjectData(FieldSeriali
zer.java:175)
     [java]     at
com.esotericsoftware.kryo.serialize.ReferenceFieldSerializer.writeObjectData(Ref
erenceFieldSerializer.java:52)
     [java]     at
com.esotericsoftware.kryo.serialize.FieldSerializer.writeObjectData(FieldSeriali
zer.java:175)
     [java]     at
com.esotericsoftware.kryo.serialize.ReferenceFieldSerializer.writeObjectData(Ref
erenceFieldSerializer.java:52)
     [java]     at
com.esotericsoftware.kryo.Kryo.writeClassAndObject(Kryo.java:489)
     [java]     ... 167 more
     [java] Caused by:
com.esotericsoftware.kryo.SerializationException: Buffer limit
exceeded writing object of type:
java.lang.ThreadLocal$ThreadLocalMap$Entry
     [java] Serialization trace:
     [java] table (java.lang.ThreadLocal$ThreadLocalMap)
     [java] threadLocals (java.awt.EventDispatchThread)
     [java]     at
com.esotericsoftware.kryo.Kryo.writeClassAndObject(Kryo.java:492)
     [java]     at
com.esotericsoftware.kryo.serialize.ArraySerializer.writeArray(ArraySerializer.j
ava:123)
     [java]     at
com.esotericsoftware.kryo.serialize.ArraySerializer.writeObjectData(ArraySeriali
zer.java:88)
     [java]     at
com.esotericsoftware.kryo.serialize.FieldSerializer.writeObjectData(FieldSeriali
zer.java:175)
     [java]     at
com.esotericsoftware.kryo.serialize.ReferenceFieldSerializer.writeObjectData(Ref
erenceFieldSerializer.java:52)
     [java]     at
com.esotericsoftware.kryo.serialize.FieldSerializer.writeObjectData(FieldSeriali
zer.java:175)
     [java]     at
com.esotericsoftware.kryo.serialize.ReferenceFieldSerializer.writeObjectData(Ref
erenceFieldSerializer.java:52)
     [java]     at
com.esotericsoftware.kryo.Kryo.writeClassAndObject(Kryo.java:489)
     [java]     ... 173 more

Original issue reported on code.google.com by nikhilsa...@gmail.com on 19 Nov 2012 at 9:36

GoogleCodeExporter commented 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

GoogleCodeExporter commented 9 years ago
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

GoogleCodeExporter commented 9 years ago
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

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
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

GoogleCodeExporter commented 9 years ago
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

GoogleCodeExporter commented 9 years ago
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