@Released({ENTRY_EVENT_NEW_VALUE, ENTRY_EVENT_OLD_VALUE})
  public void copyOffHeapToHeap() {
    if (!mayHaveOffHeapReferences()) {
      offHeapOk = false;
      return;
    }
    synchronized (offHeapLock) {
      Object ov = basicGetOldValue();
      if (StoredObject.isOffHeapReference(ov)) {
        if (ReferenceCountHelper.trackReferenceCounts()) {
          ReferenceCountHelper.setReferenceCountOwner(new OldValueOwner());
          oldValue = OffHeapHelper.copyAndReleaseIfNeeded(ov, getRegion().getCache());
          ReferenceCountHelper.setReferenceCountOwner(null);
        } else {
          oldValue = OffHeapHelper.copyAndReleaseIfNeeded(ov, getRegion().getCache());
        }
      }
      Object nv = basicGetNewValue();
      if (StoredObject.isOffHeapReference(nv)) {
        ReferenceCountHelper.setReferenceCountOwner(this);
        newValue = OffHeapHelper.copyAndReleaseIfNeeded(nv, getRegion().getCache());
        ReferenceCountHelper.setReferenceCountOwner(null);
      }
      if (StoredObject.isOffHeapReference(newValue)
          || StoredObject.isOffHeapReference(oldValue)) {
        throw new IllegalStateException(
            "event's old/new value still off-heap after calling copyOffHeapToHeap");
      }
      offHeapOk = false;
    }
  }
This copies the off-heap new and/or old value to the heap. As a result the current off-heap
new/old will be released.
geode-core/src/main/java/org/apache/geode/internal/cache/EntryEventImpl.java