JPPF Issue Tracker
star_faded.png
Please log in to bookmark issues
bug_report_small.png
CLOSED  Bug report JPPF-451  -  Android demo: exception in the client upon receiving results from the server
Posted May 28, 2016 - updated Jun 03, 2016
icon_info.png This issue has been closed with status "Closed" and resolution "RESOLVED".
Issue details
  • Type of issue
    Bug report
  • Status
     
    Closed
  • Assigned to
     lolo4j
  • Progress
       
  • Type of bug
    Not triaged
  • Likelihood
    Not triaged
  • Effect
    Not triaged
  • Posted by
     lolo4j
  • Owned by
    Not owned by anyone
  • Category
    Android
  • Resolution
    RESOLVED
  • Priority
    Normal
  • Reproducability
    Always
  • Severity
    Normal
  • Targetted for
    icon_milestones.png JPPF 5.1.4
Issue description
When running the Android Demo in the samples pack, I can see that the demo shows looping connection attempts to the server. Looking in the client log, I see the following repeated exception:
2016-05-28 08:37:55,162 [DEBUG][org.jppf.client.BaseJPPFClientConnection.receiveBundleAndResults(276)]: java.lang.ReflectiveOperationException; local class incompatible: stream classdesc serialVersionUID = 2505831918131413020, local class serialVersionUID = 123456789
java.io.InvalidClassException: java.lang.ReflectiveOperationException; local class incompatible: stream classdesc serialVersionUID = 2505831918131413020, local class serialVersionUID = 123456789
  at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:617)
  at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1622)
  at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1517)
  at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1622)
  at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1517)
  at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
  at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
  at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1990)
  at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1915)
  at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1798)
  at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
  at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
  at org.jppf.serialization.DefaultJavaSerialization.deserialize(DefaultJavaSerialization.java:45)
  at org.jppf.utils.ObjectSerializerImpl.deserialize(ObjectSerializerImpl.java:137)
  at org.jppf.utils.ObjectSerializerImpl.deserialize(ObjectSerializerImpl.java:125)
  at org.jppf.io.IOHelper.unwrappedData(IOHelper.java:230)
  at org.jppf.io.IOHelper.unwrappedData(IOHelper.java:190)
  at org.jppf.client.BaseJPPFClientConnection.receiveBundleAndResults(BaseJPPFClientConnection.java:254)
  at org.jppf.client.BaseJPPFClientConnection.receiveResults(BaseJPPFClientConnection.java:293)
  at org.jppf.client.JPPFClientConnectionImpl.receiveResults(JPPFClientConnectionImpl.java:35)
  at org.jppf.client.balancer.ChannelWrapperRemote$RemoteRunnable.run(ChannelWrapperRemote.java:226)
  at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
  at java.util.concurrent.FutureTask.run(FutureTask.java:262)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
  at java.lang.Thread.run(Thread.java:745)
Steps to reproduce this issue
  • run the Android demo as indicated here
  • you will see the repeating connection attempts messages
  • looking in the log, you will see the exception mentioned in the description

#4
Comment posted by
 lolo4j
May 29, 10:09
The main problem is that there is an error in the build.xml of the Android demo, which causes it to generate an empty jar when running the target "ant dex.jar". I have fixed it and attached it to this post. Basically I changed the "jar" target from this:
<target name="jar" depends="compile">
  <jar jarfile="demo.jar" includes="${classes}/**/*.*" excludes="${classes}/**/Runner.*"/>
</target>
to this:
<target name="jar" depends="compile">
  <jar jarfile="demo.jar">
    <fileset dir="${classes}" excludes="${classes}/**/Runner.*"/>
  </jar>
</target>
With this change, the demo works without problem.

What happens if the dex jar is empty? When the tasks are received in the node their deserialization will fail because the necessary classes are not found. This triggers a ReflectiveOperationException which the JPPF node catches and reports back by substituting the task with an instance of JPPFExceptionResult (subclass of AbtsractTask), whose sole purpose is to describe the error in a way that can be propagated back to the client.

Therefore, the problem reported in the description reveals two things:
  • there is a serialization incomptability between the Android and JDK versions of ReflectiveOperationException: the JDK version of ReflectiveOperationException sets an explicit serialVersionUID (123456789L), whereas the Android version does not and uses a value that is computed during serialization.
  • there is an exception handling issue in the JPPF node: the fact that we use setThrowable(Throwabme) to propagate the ReflectiveOperationException is what causes the InvalidClassException in the client. Currently the only way to avoid this is to not send the ReflectiveOperationException, so what should we send instead?
A possibility would be to to use a set of textual fields to discribe the throwable, instead of the throwable itself, for instance: throwableMessage, throwableStackTrace, throwableClassName.
#5
Comment posted by
 lolo4j
May 29, 10:15
For information: I just realized that ReflectiveOperationException is the common superclass for a number of other exceptions, such as ClassNotFoundException, which is the one that must be actually occurring in the node.
#6
Comment posted by
 lolo4j
May 29, 22:22
Created Android defect 211596: Serialization incompatibility between Android and JDK versions of java.lang.ReflectiveOperationException
#7
Comment posted by
 lolo4j
May 29, 22:23
Fixed in:
#9
Comment posted by
 lolo4j
Jun 02, 08:06
Reopening due to missing scenario where the issue is not fixed: if a task reports a Throwable which extends ReflectiveOperationException during its execution on an Android node, then the client will also be unable to deserialize it.

The issue was updated with the following change(s):
  • The status has been updated, from Closed to New.
  • This issue has been reopened
  • The resolution has been updated, from RESOLVED to Not determined.
#10
Comment posted by
 lolo4j
Jun 03, 08:52
Fixed in: