You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@geode.apache.org by "Darrel Schneider (Jira)" <ji...@apache.org> on 2020/11/11 23:43:00 UTC

[jira] [Comment Edited] (GEODE-8685) Exporting data causes a ClassNotFoundException

    [ https://issues.apache.org/jira/browse/GEODE-8685?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17230293#comment-17230293 ] 

Darrel Schneider edited comment on GEODE-8685 at 11/11/20, 11:42 PM:
---------------------------------------------------------------------

Why is the value being deserialized at all?

_The following is based on code on the develop branch (post 1.13)._


 In this particular case is is because the Entry instances being iterated over are instances of EntrySnapshot (only used by partitioned regions) instead of NonTXEntry instances.
 This code would have saved us and passed the serialized CachedDeserializable to "convertToBytes" if the entry had been a NonTXEntry:
{code:java}
    public <K, V> SnapshotRecord(LocalRegion region, Entry<K, V> entry) throws IOException {
      key = BlobHelper.serializeToBlob(entry.getKey());
      if (entry instanceof NonTXEntry && region != null) {
        @Released
        Object v =
            ((NonTXEntry) entry).getRegionEntry().getValueOffHeapOrDiskWithoutFaultIn(region);
        try {
          value = convertToBytes(v);
        } finally {
          OffHeapHelper.release(v);
        }
      } else {
        value = convertToBytes(entry.getValue());
      }
    }
 
{code}
 But because it was an EntrySnapshot it goes down to the else and just call entry.getValue() which on an EntrySnapshot always returns the deserialized value. This is the getValue() call we see fail because the class is not found.
 I could not find any evidence that we have changed the code that iterates the region entries or that we changed the implementation of the entry iteration on a partitioned region. It looks like it has used EntrySnapshot instances since geode existed. We probably have export tests for partitioned regions but they may not check that the value is not being deserialized.
 It would be rather easy to add a method on EntrySnapshot that exposes the CachedDeserializable and pass that to convertToBytes which already does the right thing with a CachedDeserializable.


was (Author: dschneider):
Why is the value being deserialized at all?
In this particular case is is because the Entry instances being iterated over are instances of EntrySnapshot (only used by partitioned regions) instead of NonTXEntry instances.
This code would have saved us and passed the serialized CachedDeserializable to "convertToBytes" if the entry had been a NonTXEntry:
{code:java}
    public <K, V> SnapshotRecord(LocalRegion region, Entry<K, V> entry) throws IOException {
      key = BlobHelper.serializeToBlob(entry.getKey());
      if (entry instanceof NonTXEntry && region != null) {
        @Released
        Object v =
            ((NonTXEntry) entry).getRegionEntry().getValueOffHeapOrDiskWithoutFaultIn(region);
        try {
          value = convertToBytes(v);
        } finally {
          OffHeapHelper.release(v);
        }
      } else {
        value = convertToBytes(entry.getValue());
      }
    }
 
{code}
 But because it was an EntrySnapshot it goes down to the else and just call entry.getValue() which on an EntrySnapshot always returns the deserialized value. This is the getValue() call we see fail because the class is not found.
I could not find any evidence that we have changed the code that iterates the region entries or that we changed the implementation of the entry iteration on a partitioned region. It looks like it has used EntrySnapshot instances since geode existed. We probably have export tests for partitioned regions but they may not check that the value is not being deserialized.
It would be rather easy to add a method on EntrySnapshot that exposes the CachedDeserializable and pass that to convertToBytes which already does the right thing with a CachedDeserializable.

> Exporting data causes a ClassNotFoundException
> ----------------------------------------------
>
>                 Key: GEODE-8685
>                 URL: https://issues.apache.org/jira/browse/GEODE-8685
>             Project: Geode
>          Issue Type: Task
>          Components: regions
>    Affects Versions: 1.13.0
>            Reporter: Anthony Baker
>            Assignee: Darrel Schneider
>            Priority: Major
>              Labels: GeodeOperationAPI
>
> See [https://lists.apache.org/thread.html/rfa4fc47eb4cb4e75c39d7cb815416bebf2ec233d4db24e37728e922e%40%3Cuser.geode.apache.org%3E.]
>  
> Report is that exporting data whose values are Classes defined in a deployed jar result in a ClassNotFound exception:
> {noformat}
> [error 2020/10/30 08:54:29.317 PDT <Function Execution Processor2> tid=0x41] org.apache.geode.cache.execute.FunctionException: org.apache.geode.SerializationException: A ClassNotFoundException was thrown while trying to deserialize cached value.
> java.io.IOException: org.apache.geode.cache.execute.FunctionException: org.apache.geode.SerializationException: A ClassNotFoundException was thrown while trying to deserialize cached value.
>         at org.apache.geode.internal.cache.snapshot.WindowedExporter.export(WindowedExporter.java:106)
>         at org.apache.geode.internal.cache.snapshot.RegionSnapshotServiceImpl.exportOnMember(RegionSnapshotServiceImpl.java:361)
>         at org.apache.geode.internal.cache.snapshot.RegionSnapshotServiceImpl.save(RegionSnapshotServiceImpl.java:161)
>         at org.apache.geode.internal.cache.snapshot.RegionSnapshotServiceImpl.save(RegionSnapshotServiceImpl.java:146)
>         at org.apache.geode.management.internal.cli.functions.ExportDataFunction.executeFunction(ExportDataFunction.java:62)
>         at org.apache.geode.management.cli.CliFunction.execute(CliFunction.java:37)
>         at org.apache.geode.internal.cache.MemberFunctionStreamingMessage.process(MemberFunctionStreamingMessage.java:201)
>         at org.apache.geode.distributed.internal.DistributionMessage.scheduleAction(DistributionMessage.java:376)
>         at org.apache.geode.distributed.internal.DistributionMessage$1.run(DistributionMessage.java:441)
>         at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
>         at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
>         at org.apache.geode.distributed.internal.ClusterOperationExecutors.runUntilShutdown(ClusterOperationExecutors.java:442)
>         at org.apache.geode.distributed.internal.ClusterOperationExecutors.doFunctionExecutionThread(ClusterOperationExecutors.java:377)
>         at org.apache.geode.logging.internal.executors.LoggingThreadFactory.lambda$newThread$0(LoggingThreadFactory.java:119)
>         at java.base/java.lang.Thread.run(Thread.java:834)
> Caused by: org.apache.geode.cache.execute.FunctionException: org.apache.geode.SerializationException: A ClassNotFoundException was thrown while trying to deserialize cached value.
>         at org.apache.geode.internal.cache.snapshot.WindowedExporter$WindowedExportCollector.setException(WindowedExporter.java:383)
>         at org.apache.geode.internal.cache.snapshot.WindowedExporter$WindowedExportCollector.addResult(WindowedExporter.java:346)
>         at org.apache.geode.internal.cache.execute.PartitionedRegionFunctionResultSender.lastResult(PartitionedRegionFunctionResultSender.java:195)
>         at org.apache.geode.internal.cache.execute.AbstractExecution.handleException(AbstractExecution.java:502)
>         at org.apache.geode.internal.cache.execute.AbstractExecution.executeFunctionLocally(AbstractExecution.java:353)
>         at org.apache.geode.internal.cache.execute.AbstractExecution.lambda$executeFunctionOnLocalPRNode$0(AbstractExecution.java:273)
>         ... 6 more
> Caused by: org.apache.geode.SerializationException: A ClassNotFoundException was thrown while trying to deserialize cached value.
>         at org.apache.geode.internal.cache.EntryEventImpl.deserialize(EntryEventImpl.java:2046)
>         at org.apache.geode.internal.cache.EntryEventImpl.deserialize(EntryEventImpl.java:2032)
>         at org.apache.geode.internal.cache.VMCachedDeserializable.getDeserializedValue(VMCachedDeserializable.java:135)
>         at org.apache.geode.internal.cache.EntrySnapshot.getRawValue(EntrySnapshot.java:111)
>         at org.apache.geode.internal.cache.EntrySnapshot.getRawValue(EntrySnapshot.java:99)
>         at org.apache.geode.internal.cache.EntrySnapshot.getValue(EntrySnapshot.java:129)
>         at org.apache.geode.internal.cache.snapshot.SnapshotPacket$SnapshotRecord.<init>(SnapshotPacket.java:79)
>         at org.apache.geode.internal.cache.snapshot.WindowedExporter$WindowedExportFunction.execute(WindowedExporter.java:197)
>         at org.apache.geode.internal.cache.execute.AbstractExecution.executeFunctionLocally(AbstractExecution.java:328)
>         ... 7 more
> Caused by: java.lang.ClassNotFoundException: org.myApp.domain.myClass
>         at org.apache.geode.internal.ClassPathLoader.forName(ClassPathLoader.java:186)
>         at org.apache.geode.internal.InternalDataSerializer.getCachedClass(InternalDataSerializer.java:3114)
>         at org.apache.geode.DataSerializer.readClass(DataSerializer.java:264)
>         at org.apache.geode.internal.InternalDataSerializer.readDataSerializable(InternalDataSerializer.java:2327)
>         at org.apache.geode.internal.InternalDataSerializer.basicReadObject(InternalDataSerializer.java:2513)
>         at org.apache.geode.DataSerializer.readObject(DataSerializer.java:2864)
> {noformat}
> This seemed to work in 1.10.0.  Test case is at https://github.com/claudiu-balciza/GeodeDeserializationErrorPOC/tree/develop.



--
This message was sent by Atlassian Jira
(v8.3.4#803005)