2

I'm playing around with session/org caches, and I came across something interesting. It seems that if I create a class which can save itself to the cache, then change a member variable on an instance of that class, the cache seems to know the new value, even before I save it back to the cache. Any idea what is going on?

Note the following should run as an anonymous APEX block, once you have set up a cache partition called "TestPartition".

APEX

String CACHE_KEY='local.TestPartition.someKey';

public class CacheableClass {
    public Integer x;

    public void saveToCache() {
        Cache.Session.put(CACHE_KEY, this);
    }
}

void printCache(String label) {
    CacheableClass tc = (CacheableClass)Cache.Session.get(CACHE_KEY);
    System.debug(label.rightPad(35)+': '+tc);
}

Cache.Session.remove(CACHE_KEY);  //  in case it already existed
printCache('Before anything');
CacheableClass c = new CacheableClass();
printCache('After construction');
c.saveToCache();
printCache('After saveToCache()');
c.x=5;
printCache('After set x; before saveToCache()');  //  <--  why is it showing x=5 here FROM THE CACHE, even though I haven't yet saved it?
c.saveToCache();
printCache('After second saveToCache()');

Output

12:00:07.26 (35201148)|USER_DEBUG|[17]|DEBUG|Before anything                    : null
12:00:07.26 (35813582)|USER_DEBUG|[17]|DEBUG|After construction                 : null
12:00:07.26 (36718784)|USER_DEBUG|[17]|DEBUG|After saveToCache()                : CacheableClass:[x=null]
12:00:07.26 (37039696)|USER_DEBUG|[17]|DEBUG|After set x; before saveToCache()  : CacheableClass:[x=5]
12:00:07.26 (38777618)|USER_DEBUG|[17]|DEBUG|After second saveToCache()         : CacheableClass:[x=5]
  • Are you debugging c.x? – sfdcfox Aug 9 '16 at 17:14
  • 1
    x is a variable in your class. You are instantiating c as a CacheableClass and putting it in your cache, then modifying the same object c. Which is cached. – Jesse Milburn Aug 9 '16 at 17:16
2

I'm going to use my comment then expand on the explanation a little bit.

Comment from question:

x is a variable in your class. You are instantiating c as a CacheableClass and putting it in your cache, then modifying the same object c. Which is cached.

Deeper explanation:

The cache holds a reference to where c is held in memory. It doesn't make another copy of that already instantiated object somewhere else in memory. Therefore now your local code holds a pointer to where c is in memory and the cache holds a pointer to that as well. But you are still modifying the same instance of your CacheableClass.

So you now have two references to the same chunk of memory. Which is why if you let your local pointer go, the object still persists in memory because the cache maintains a pointer to it. Thus it stays in memory for you to call in the same session using the Cache.Session.get methods.

Computer Caching image

This image shows that the cache doesn't recreate the already instantiated object somewhere else in memory, but simply stores a pointer(reference) to where that already instantiated object is in memory.

  • Huh, that's really interesting. So if I pull something out of the cache, then modify it via that reference, I don't have to do anything to "put it back" in the cache? – loneboat Aug 9 '16 at 18:24
  • I think once you put it in the cache it now becomes stateful. So you would get a copy in a different place in memory of what it is currently like in the cache. So it doesn't change if you are using it across different processes. When I get some more time I will try and prove that. – Jesse Milburn Aug 9 '16 at 18:34
0

c is not linked to the cache. It's an in-memory representation that doesn't reflect the current status of the cache.

As a similar example, observe what happens when you run this code:

Account a = [SELECT Name FROM Account LIMIT 1];
System.debug(a.Name);
a.Name = 'New Account Name';
System.debug(a.Name);

You'll get something like:

DEBUG|Old Account Name
DEBUG|New Account Name

But, if you go back to the record, you'll see it's name is still "Old Account Name." We only updated an in-memory copy of the value, but did not commit it. This is essentially what's going on with your code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.