JPPF, java, parallel computing, distributed computing, grid computing, parallel, distributed, cluster, grid, cloud, open source, android, .net
JPPF

The open source
grid computing
solution

 Home   About   Features   Download   Documentation   On Github   Forums 
August 10, 2022, 02:19:26 PM *
Welcome,
Please login or register.

Login with username, password and session length
Advanced search  
News: New users, please read this message. Thank you!
  Home Help Search Login Register  
Pages: [1]   Go Down

Author Topic: KryoSerialization sample doesn't work with JPPF 4.0  (Read 4079 times)

Emin Mamedov

  • JPPF Grand Master
  • ****
  • Posts: 69
KryoSerialization sample doesn't work with JPPF 4.0
« on: January 21, 2014, 12:21:47 PM »

Hi JPPF Team,

Decided to play with KryoSerialization sample but looks like it doesn't work.

OS: Win 8 x64
JPPF: 4.0
Java: Java(TM) SE Runtime Environment (build 1.7.0-b147), Java HotSpot(TM) Client VM (build 21.0-b17, mixed mode, sharing)
Topology: 1 driver + 1 node with disabled auto discovery (direct connection)
Kryo Libs: Took from sample and tried also the latest versions (Kryo 2.22, objenesis 2.1 and etc).

Node can't connect to the driver and tries to reconnect every second. In driver's log I found next exeception

Code: [Select]
2014-01-21 13:49:54,201 [NodeClassServer-8] DEBUG org.jppf.nio.StateTransitionTask {} - error on channel SelectionKeyWrapper[id=16, readyOps=1, interestOps=0, context=channel=SelectionKeyWrapper[id=16], state=WAITING_INITIAL_NODE_REQUEST, resource=null, pendingResponses=0, type=node, peer=false, uuid=null, secure=false, ssl=false] : com.esotericsoftware.kryo.KryoException: java.lang.ClassCastException: class org.jppf.classloader.ResourceIdentifier != null
Serialization trace:
dataMap (org.jppf.classloader.JPPFResourceWrapper)
  at com.esotericsoftware.kryo.serializers.FieldSerializer$ObjectField.read(FieldSerializer.java:626)
  at com.esotericsoftware.kryo.serializers.FieldSerializer.read(FieldSerializer.java:221)
  at com.esotericsoftware.kryo.Kryo.readClassAndObject(Kryo.java:729)
  at test.KryoSerialization.deserialize(KryoSerialization.java:84)
  at org.jppf.utils.ObjectSerializerImpl.deserialize(ObjectSerializerImpl.java:154)
  at org.jppf.utils.ObjectSerializerImpl.deserialize(ObjectSerializerImpl.java:140)
  at org.jppf.io.IOHelper.unwrappedData(IOHelper.java:215)
  at org.jppf.io.IOHelper.unwrappedData(IOHelper.java:187)
  at org.jppf.server.nio.classloader.ClassContext.deserializeResource(ClassContext.java:120)
  at org.jppf.server.nio.classloader.node.WaitingInitialNodeRequestState.performTransition(WaitingInitialNodeRequestState.java:72)
  at org.jppf.server.nio.classloader.node.WaitingInitialNodeRequestState.performTransition(WaitingInitialNodeRequestState.java:33)
  at org.jppf.nio.StateTransitionTask.run(StateTransitionTask.java:82)
  at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
  at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
  at java.util.concurrent.FutureTask.run(FutureTask.java:166)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
  at java.lang.Thread.run(Thread.java:722)

Code: [Select]
2014-01-21 13:49:26,075 [main] INFO  org.jppf.utils.VersionUtils {} - --------------------------------------------------------------------------------
2014-01-21 13:49:26,075 [main] INFO  org.jppf.utils.VersionUtils {} - JPPF Version: 4.0, Build number: 1301, Build date: 2014-01-14 07:48 CET
2014-01-21 13:49:26,075 [main] INFO  org.jppf.utils.VersionUtils {} - starting driver with PID=9540, UUID=44E96A5D-F4C2-1F60-CAFF-D48B64D3B503
2014-01-21 13:49:26,075 [main] INFO  org.jppf.utils.VersionUtils {} - --------------------------------------------------------------------------------

Could you please look on it?

Many thanks in advance,

Emin
« Last Edit: January 21, 2014, 12:25:12 PM by Emin Mamedov »
Logged

Emin Mamedov

  • JPPF Grand Master
  • ****
  • Posts: 69
Re: KryoSerialization sample doesn't work with JPPF 4.0
« Reply #1 on: January 21, 2014, 01:17:08 PM »

Please ignore. Looks like Kryo issue

https://code.google.com/p/kryo/issues/detail?id=134

Thanks and sorry :)
Logged

lolo

  • Administrator
  • JPPF Council Member
  • *****
  • Posts: 2272
    • JPPF Web site
Re: KryoSerialization sample doesn't work with JPPF 4.0
« Reply #2 on: January 21, 2014, 03:11:05 PM »

Hello Emin,

In fact, I believe this is an issue in the Kryo serializer sample code. This can be resolved easily by adding the following in the createKryo() method of KryoSerializer.java, before the return statement:
Code: [Select]
kryo.register(EnumMap.class, new EnumMapSerializer());
Sorry for the inconvenience this caused.

In any case, I will update the samples pack distribution with this fix shortly.

Sincerely,
-Laurent
Logged

Emin Mamedov

  • JPPF Grand Master
  • ****
  • Posts: 69
Re: KryoSerialization sample doesn't work with JPPF 4.0
« Reply #3 on: March 03, 2014, 09:41:59 AM »

Hi Laurent,

Thanks for the reply. Actually I did the same to resolve the issue and can confirm that it works.

Another question: is it possible to get Serializer implementation class name from driver (by clients and nodes) to not duplicate this config in client's, node's and driver's config files?

Thanks,
Emin
Logged

lolo

  • Administrator
  • JPPF Council Member
  • *****
  • Posts: 2272
    • JPPF Web site
Re: KryoSerialization sample doesn't work with JPPF 4.0
« Reply #4 on: March 03, 2014, 07:17:27 PM »

Hi Emin,

It is not possible to obtain the serialization class from the driver, because the nodes and clients need the serialization to communicate with the driver. It's a little bit of a chicken and egg problem :)

One possiblity, however, is to have the serialization class defined in a configuration source that is common to drivers, clients and nodes by using a configuration include, and specifying a configuration source that is reachable by everyone, for instance on a shared file system or a web server.

Let's take an example. Let's imagine that you have a web server on the host 192.168.1.10, with a properties file placed at /jppf/config/serialization-class.properties which contains the following:
Code: [Select]
# Kryo serialization
jppf.object.serialization.class = org.jppf.serialization.kryo.KryoSerialization

Now, in your driver, node and client configuration, instead of specifying "jppf.object.serialization.class", you can use an #!include statement to load the properties file on the web server:
Code: [Select]
...
#!include url http://192.168.1.10/jppf/config/serialization-class.properties
...

I believe this achieves what you were trying to do.

Sincerely,
-Laurent
Logged

Emin Mamedov

  • JPPF Grand Master
  • ****
  • Posts: 69
Re: KryoSerialization sample doesn't work with JPPF 4.0
« Reply #5 on: March 04, 2014, 07:12:59 AM »

Hi Laurent,

Thanks a lot for detailed explanation. I will try your approach.

Thanks,
Emin
Logged

Konstantin Eroshenko

  • Guest
Re: KryoSerialization sample doesn't work with JPPF 4.0
« Reply #6 on: November 19, 2016, 12:02:36 PM »

Hi, Laurent.

I still have a strong suspicion that sample is a bit broken. 
The quote from documentation

"In effect, each node in the grid will have a map of each client identifier with a unique class loader, creating the class loader when needed. The implication is that, if a new client identifier is specified, the classes used in any job / task submiotted by this client will be dynamically reloaded."

doesn't hold true, when KryoSerialization is used. Is it a known issue?
If not, then I'll describe a test I've used to spot the issue and the reasons why is that working so.
Logged

lolo

  • Administrator
  • JPPF Council Member
  • *****
  • Posts: 2272
    • JPPF Web site
Re: KryoSerialization sample doesn't work with JPPF 4.0
« Reply #7 on: December 28, 2016, 09:26:02 AM »

Hello,

Sorry for the latse answer.

Quote
The quote from documentation "[...]" doesn't hold true, when KryoSerialization is used. Is it a known issue?

This is not an issue that I'm aware of. I'd be happy if you could provide details on how to reproduce it. Also, just to be sure, can you confirm with which JPPF version you observe this problem?

Thanks,
-Laurent
Logged

Konstantin Eroshenko

  • Guest
Re: KryoSerialization sample doesn't work with JPPF 4.0
« Reply #8 on: December 28, 2016, 02:28:38 PM »

I've spot the issue with JPPF 4.2, but it seems there is no JPPF fault in it.

I wrote very simple test:

Code: [Select]
public void jppfClientTest2() throws Exception {
TypedProperties props = JPPFConfiguration.getProperties();
props.setString("jppf.object.serialization.class", "org.jppf.serialization.kryo.KryoSerialization");
...

try (JPPFClient client = new JPPFClient()) {
JPPFJob job = new JPPFJob();
job.add(new TestJPPFTask());
List<Task<?>> jobResult = client.submitJob(job);
Task<?> taskResult = jobResult.get(0);
Assert.assertEquals(TestJPPFTask.result, taskResult.getResult());
}

where for the first run TestJPPFTask is

Code: [Select]
private class TestJPPFTask extends JPPFTask {
public static final int result = 1;

@Override
public void run() {
setResult(result);
}
}

and for the second run
Code: [Select]
private class TestJPPFTask extends JPPFTask {
public static final int result = 2;

@Override
public void run() {
setResult(result);
}
}

The difference is in private static final result field.
Then I ran it against "1-server 1-node" jppf topology, and the second run failed with:

Code: [Select]
java.lang.AssertionError: expected:<2> but was:<1>
The reason is in how kryo works. I've debug it a bit and revealed that the following method is called when data gets deserialized on the node:

Code: [Select]
Thread [main] (Suspended (breakpoint at line 152 in DefaultClassResolver))
owns: Class<T> (org.jppf.classloader.JPPFClassLoader) (id=59)
DefaultClassResolver.getTypeByName(String) line: 152
DefaultClassResolver.readName(Input) line: 133
DefaultClassResolver.readClass(Input) line: 115
Kryo.readClass(Input) line: 641
EnumMapSerializer.create(Kryo, Input, Class<EnumMap<Enum<?>,?>>) line: 62
EnumMapSerializer.read(Kryo, Input, Class<EnumMap<Enum<?>,?>>) line: 71
EnumMapSerializer.read(Kryo, Input, Class) line: 36
Kryo.readObject(Input, Class<T>, Serializer) line: 679
UnsafeCacheFields$UnsafeObjectField(ObjectField).read(Input, Object) line: 106
FieldSerializer<T>.read(Kryo, Input, Class<T>) line: 528
Kryo.readClassAndObject(Input) line: 761
KryoSerialization.deserialize(InputStream) line: 78
BootstrapObjectSerializer.deserialize(InputStream) line: 148
IOHelper.unwrappedData(DataLocation, ObjectSerializer) line: 237
IOHelper.unwrappedData(SocketWrapper, ObjectSerializer) line: 197
RemoteResourceRequest.run() line: 77
RemoteClassLoaderConnection(AbstractClassLoaderConnection<C>).performCommonHandshake(ResourceRequestRunner) line: 66
RemoteClassLoaderConnection.performHandshake() line: 122
RemoteClassLoaderConnection.init() line: 86
JPPFClassLoader(AbstractJPPFClassLoaderLifeCycle).init() line: 123
JPPFClassLoader.<init>(ClassLoaderConnection, ClassLoader) line: 47
NodeRunner$2.run() line: 244
NodeRunner$2.run() line: 241
AccessController.doPrivileged(PrivilegedAction<T>) line: not available [native method]
NodeRunner.getJPPFClassLoader() line: 247
NodeRunner.createNode(ConnectionContext) line: 179
NodeRunner.main(String...) line: 130

which basically tries to get class for given name from internal kryo cache (or map to be precise)

Code: [Select]
protected Class<?> getTypeByName(final String className) {
return nameToClass != null ? nameToClass.get(className) : null;
}

For me kryo kind of wrong here. It would be better if kryo compares classes' classloaders along with classes' names to get proper one cached class.
Please, confirm my suspicions.





Logged

lolo

  • Administrator
  • JPPF Council Member
  • *****
  • Posts: 2272
    • JPPF Web site
Re: KryoSerialization sample doesn't work with JPPF 4.0
« Reply #9 on: December 28, 2016, 11:41:40 PM »

Hello,

Thank you for your detailed analysis. I could reproduce in JPPF 5.2.2 and I completely agree with your conclusions. Seeing this, I was hoping that setting setAutoReset(true) on the Kryo instance would get this class cache cleared, but looking at the  Kryo code, I could see that the cache is in fact never cleared.

To try and overcome this problem, I created a subclass of DefaultClassResolver and overrode its reset() method:
Code: [Select]
public static class CustomClassResolver extends DefaultClassResolver {
  @Override
  public void reset() {
    super.reset();
    if (nameToClass != null) nameToClass.clear();
  }
}

Then, in the createKryo() method I changed the creation of the Kryo instance from this:
Code: [Select]
Kryo kryo = new Kryo();
into this:
Code: [Select]
Kryo kryo = new Kryo(new CustomClassResolver(), new MapReferenceResolver());
kryo.setAutoReset(true);

and this worked!

Sincerely,
-Laurent
Logged
Pages: [1]   Go Up
 
JPPF Powered by SMF 2.0 RC5 | SMF © 2006–2011, Simple Machines LLC Get JPPF at SourceForge.net. Fast, secure and Free Open Source software downloads