简体   繁体   中英

How does the CLR know if a static field has already been initialized?

There is one thing I have been always been wondering about static fields / constructors .

The static class initialized the first time one of it's fields is referenced, that is easy.

But how does the CLR know that it is the first time?

The CLR maintains a table of all types that have been loaded and their initialization status. If A is using a static field of B then the CLR knows that A is using B and while initializing A it will also initialize B . So the check if dependencies are initialized is not performed on each access. It is ensured though dependency graph of the types.

If you are interested in the implementation details you can have a look at the IsClassInitialized method of the DomainLocalModule in CoreCLR and its usage when instances of classes are created.

I hope this answers your question.

The static class initialized the first time one of it's fields is referenced, that is easy.

No, it's not that simple. Ignoring method calls, a static class has to be initialized just before one of its fields is accessed for the first time, if it's not marked beforefieldinit . If it is marked beforefieldinit , it can be initialized earlier than that. (Jon Skeet has an article with lots more information about beforefieldinit .)

How does this affect when is class initialization checked? Since CLR uses JIT compilation, it checks for class initialization when JIT compiling the method. If the class is marked beforefieldinit and it hasn't been initialized yet, the JIT compiler initializes it right away. It then actually compiles the method, where it can assume that the class has been initialized already, so no checks are necessary.

Without beforefieldinit , if the class hasn't been initialized yet, the JIT compiler has to emit code that checks for initialization before every potential first field access. But if the class is already initialized and another method is being JIT compiled, the JIT compiler doesn't have to emit the checks there anymore.

This can have negative effect on performance in some cases. From the above it's clear that to protect against this, you need to make sure the problematic classes are marked beforefieldinit . And the way to do that from C# is to not have a static constructor, use only static field initializers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM