Details
-
Bug
-
Status: Resolved
-
Critical
-
Resolution: Fixed
-
2.9, 2.10, 2.12, 2.13, 2.14, 2.15
-
Thin Java Client: fixed orphaned handles after binary object detach operation.
-
Release Notes Required
Description
I have encountered an issue in deserializing cache values which are of Collection type.
The issue occurs if a field in different objects within the collection points to the same reference.
Versions:
org.apache.ignite:ignite-core:2.9.0 to org.apache.ignite:ignite-core:2.15.0
Person.java public class Person implements Serializable { private String id; private String firstName; private String lastName; private double salary; private String country; private String deleted; private Set<String> accounts; } Client ClientCacheConfiguration cacheCfg = new ClientCacheConfiguration().setName(cacheName). setCacheMode(CacheMode.REPLICATED). setWriteSynchronizationMode(CacheWriteSynchronizationMode.FULL_SYNC); cache = client.getOrCreateCache(cacheCfg); Set<String> set = new HashSet<>(); set.add("1"); List<Person> persons = new ArrayList<>(); persons.add(new Person("105286a4","Jack","Smith",10000f, "USA","false", set)); persons.add(new Person("98545b0fd3af","John", "Doe", 500000f, "Australia","false", null)); persons.add(new Person("98545b0fd3afd","Hari","M",400000f, "India", null, null)); persons.add(new Person("985488b0fd3ae","Bugs","Bunny",300000f,"Wabbit Land ", null, set)); cache.put("group1", value) // Write collection to cache List<Person> persons = (List<Person>) cache.get("group1"); // Get from cache, Exception here
Exception:
class org.apache.ignite.binary.BinaryObjectException: Failed to deserialize object [typeName=com.ignite.example.model.Person] at org.apache.ignite.internal.binary.BinaryClassDescriptor.read(BinaryClassDescriptor.java:927) at org.apache.ignite.internal.binary.BinaryReaderExImpl.deserialize0(BinaryReaderExImpl.java:1764) at org.apache.ignite.internal.binary.BinaryReaderExImpl.deserialize(BinaryReaderExImpl.java:1716) at org.apache.ignite.internal.binary.GridBinaryMarshaller.deserialize(GridBinaryMarshaller.java:316) at org.apache.ignite.internal.client.thin.ClientBinaryMarshaller.deserialize(ClientBinaryMarshaller.java:74) at org.apache.ignite.internal.client.thin.ClientUtils.unwrapBinary(ClientUtils.java:557) at org.apache.ignite.internal.client.thin.ClientUtils.unwrapCollection(ClientUtils.java:578) at org.apache.ignite.internal.client.thin.ClientUtils.unwrapBinary(ClientUtils.java:562) at org.apache.ignite.internal.client.thin.ClientUtils.readObject(ClientUtils.java:546) at org.apache.ignite.internal.client.thin.TcpClientCache.readObject(TcpClientCache.java:556) at org.apache.ignite.internal.client.thin.TcpClientCache.readObject(TcpClientCache.java:561) at org.apache.ignite.internal.client.thin.TcpClientCache$$Lambda$395/1950117092.apply(Unknown Source) at org.apache.ignite.internal.client.thin.TcpClientChannel.receive(TcpClientChannel.java:284) at org.apache.ignite.internal.client.thin.TcpClientChannel.service(TcpClientChannel.java:219) at org.apache.ignite.internal.client.thin.ReliableChannel.service(ReliableChannel.java:198) at org.apache.ignite.internal.client.thin.ReliableChannel.affinityService(ReliableChannel.java:261) at org.apache.ignite.internal.client.thin.TcpClientCache.cacheSingleKeyOperation(TcpClientCache.java:508) at org.apache.ignite.internal.client.thin.TcpClientCache.get(TcpClientCache.java:111) at com.ignite.example.service.ApacheIgniteService.printAllKeys(ApacheIgniteService.java:117) at com.ignite.example.service.ApacheIgniteService.init(ApacheIgniteService.java:103) at com.ignite.example.IgniteCacheExampleApplication.run(IgniteCacheExampleApplication.java:22) at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:768) at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:752) at org.springframework.boot.SpringApplication.run(SpringApplication.java:314) at com.ignite.example.IgniteCacheExampleApplication.main(IgniteCacheExampleApplication.java:17) Caused by: class org.apache.ignite.binary.BinaryObjectException: Failed to read field [name=accounts] at org.apache.ignite.internal.binary.BinaryFieldAccessor.read(BinaryFieldAccessor.java:192) at org.apache.ignite.internal.binary.BinaryClassDescriptor.read(BinaryClassDescriptor.java:888) ... 24 more Caused by: java.lang.ArrayIndexOutOfBoundsException: -430 at org.apache.ignite.internal.binary.streams.BinaryHeapInputStream.readByteAndShift(BinaryHeapInputStream.java:120) at org.apache.ignite.internal.binary.streams.BinaryAbstractInputStream.readByte(BinaryAbstractInputStream.java:37) at org.apache.ignite.internal.binary.BinaryReaderExImpl.<init>(BinaryReaderExImpl.java:219) at org.apache.ignite.internal.binary.BinaryReaderExImpl.<init>(BinaryReaderExImpl.java:186) at org.apache.ignite.internal.binary.BinaryUtils.doReadObject(BinaryUtils.java:1801) at org.apache.ignite.internal.binary.BinaryReaderExImpl.deserialize0(BinaryReaderExImpl.java:1748) at org.apache.ignite.internal.binary.BinaryReaderExImpl.deserialize(BinaryReaderExImpl.java:1716) at org.apache.ignite.internal.binary.BinaryReaderExImpl.readField(BinaryReaderExImpl.java:1978) at org.apache.ignite.internal.binary.BinaryFieldAccessor$DefaultFinalClassAccessor.read0(BinaryFieldAccessor.java:703) at org.apache.ignite.internal.binary.BinaryFieldAccessor.read(BinaryFieldAccessor.java:188)
Analysis
The exception occurs due to a OutOfBounds read happening in
obj = BinaryUtils.doReadObject(in, ctx, ldr, this);
This is because handlePos points to a location in the ByteBuffer which is outside that of the Buffer in the current object resulting in a negative offset (java.lang.ArrayIndexOutOfBoundsException: -430)
The serialization works and the Byte array response returned from the server is the same as that was written. It's the way HANDLE types within a Collection are read that's probably causing this.
Attachments
Attachments
Issue Links
- is related to
-
IGNITE-12625 Thin client: Marshaling/unmarshaling of objects performed twice
- Open
- links to