10

I am actually adding a static field to one of the classes. The field would hold a small cache. The documentation says that the static fields are initialized when the classes are loaded. But, when are the classes actually loaded? Are they loaded when they are first created? Are they reloaded each time I modify it? Or does reload whenever any class or object in the Salesforce Org changes.

2

5 Answers 5

15

One fundamental principle of apex to remember is that there are no long running processes. As opposed to something like an app running in tomcat where your static variables are shared between multiple requests apex threads are totally isolated and share nothing outside of the database with each other.

Thus in two requests that happen simultaneously from the same user it's possible to have two different values for the same static variable, since each thread is totally independent from each other. When the thread completes the action is was started to perform (a single API request, a visualforce page action, etc.) it's state is discarded and the thread terminates. This is why the other answers are valid technically - the class is loaded once per transaction and then is unloaded when the transaction completes. Modifying an apex class doesn't load it because there's no running apex thread that needs to reference it at that point.

With that in mind static blocks and initializers in apex are run once the class is first referenced in your code. Running the constructor, referencing a static property, method, or any other reference to the class causes the system to load the class at that point.

0
4

Classes are loaded when they are instantiated. For Visualforce page controllers, this is when the page is loaded, for other classes, this is when the class is instantiated via the code.

For example:

Myclass mClass = new Myclass();

When this line is executed the Myclass class is loaded, and the constructor is executed. The instance is destroyed when the transaction ends, and a new instance is created the next time the code is executed.

6
  • I am actually confused because of my background in Java. In Java a class is typically loaded on the first use and typically remains loaded for the life of the application (it may be unloaded if there are not instances of it and application needs to reclaim memory)
    – Amit
    Commented Mar 27, 2014 at 20:30
  • 2
    You are not that far off. It is the life of the application that is different in this case. If you are talking about a trigger, then the life is the duration of the transaction (usually a very brief amount of time). If this is a batch job, it could be longer, but still will terminate when complete and unload the classes. A visualforce page controller only lives as long as the page is rendered (in most cases) and is reinitialized when accessed again.
    – JimRae
    Commented Mar 27, 2014 at 20:37
  • Ahh that clears it. That brings another question. So, if there are multiple requests hitting the server simultaneously, do we end up with multiple instances of the same static field (and even the whole application)?
    – Amit
    Commented Mar 27, 2014 at 20:40
  • 2
    Yes, each request would be treated in isolation. If you need the data to persist across transactions or users, you would need to either: store it in a custom object or create a Custom Setting to store it in. If my answer helped you, please vote it up and/or accept it as the answer to your question.
    – JimRae
    Commented Mar 27, 2014 at 20:53
  • I selected the other answer as I found that to be complete. I am unable to upvote your answer as I am not eligible for. Thanks for the help.
    – Amit
    Commented Mar 27, 2014 at 21:04
3

According to that definition: Loading = when the class is being used

That means it loads when you try to access the class.

So, you have a controller, it will 'load' the static variables in the controller when the page calls it.

public class MyController
{
  public static String TEMP = 'abc';

  public MyController()
  {
    //Your variable was loaded as soon as this controller got referenced by the Visualforce page
  }

  public PageReference someAction()
  {
    String otherVal = Util.OTHER_VAL;//The variables in your util class I believe are loaded here
  }
}

util class

public class Util
{
  public static String OTHER_VAL = 'something';
}
6
  • Does it mean that it will load the class each time an instance is created or only the first time an instance is created?
    – Amit
    Commented Mar 27, 2014 at 20:36
  • Only the first time.
    – dphil
    Commented Mar 27, 2014 at 20:41
  • So, what happens in case I update the class? Is the class loaded again? By the way, please check the comments on the other answer salesforce.stackexchange.com/a/31104/7231 .
    – Amit
    Commented Mar 27, 2014 at 20:44
  • If you are on a Visualforce page that uses it, your Visualforce page will give you an error saying you need to refresh the page which would reload it. If there is a batch or something using it already, it won't let you change the code during that.
    – dphil
    Commented Mar 27, 2014 at 20:46
  • I understand that visualforce would error out because it would not be able to deserialize the view-state. Also, it seems that salesforce platform locks the source-code while it is in use. But, that could create problems if you have to perform an urgent fix on a heavily used live application. Is that never done?
    – Amit
    Commented Mar 27, 2014 at 20:52
3

As other answers talk about, static variables in Apex are short lived compared with other environments and are not preserved between requests.

But they are useful for caching within an individual request. For example, if you have code in a controller that requires a record type id and code in a trigger that requires the same record type id, then "lazily loading" once into a static variable can make sense (and make your code cleaner too). This particularly benefits larger code bases where the cached data gets referenced many times per request.

But caching too much would be a mistake because every request would carry the overhead of the cache filling work whether the cache content was used or not.

Dan Appleman's Advanced Apex Programming book covers the topic of how static works well. I recommend anyone working in Apex to read it (and no I am not on commission).

6
  • 3
    Agreed, and the transient nature of statics actually makes them even better for caching since you don't have to worry about other contexts. Go ahead, cache things from the perspective of the running user! Commented Mar 27, 2014 at 23:17
  • That's exactly what I am doing.
    – Amit
    Commented Mar 27, 2014 at 23:32
  • @Keith, does your example about querying a record type Id in a controller and trigger imply the need for a util class that would provide that static variable so that both the controller and trigger would reference it once in the same transaction? For instance, when a controller performs an update on an object, the trigger for that object is invoked and it's in the same apex transaction. Hence, when the trigger references the record type id, it's been already queried and cached. Am I right here?
    – Eduard
    Commented Oct 30, 2018 at 11:19
  • @Eduard It does imply the need for a class, but that class could be the controller. Really depends on how many examples of this sort of sharing there are; if you have lots of record type Id based logic then a separate class would make sense.
    – Keith C
    Commented Oct 30, 2018 at 11:48
  • 1
    @Eduard I'd say it's possible rather than good. Certainly not consistent with en.wikipedia.org/wiki/Single_responsibility_principle.
    – Keith C
    Commented Oct 30, 2018 at 13:16
0

This issue affects unit testing with Apex as well. I recently had a test classes that was failing because of a static variable that I initialized like this:

private static final String testName = getRandomString();

I used testName in an @testSetup to create some records. But in the @isTest methods I was getting failures because testName had changed. What happened was that the class got reloaded in between running @testSetup and the @isTest. So the static final variable's value at @isTest runtime was different from what had been used to create the records in @testSetup.

Apex classes get loaded and unloaded all the time. Behavior that you take for granted in the JVM does not apply in Apex.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .