How Exactly Do Static Fields Work Internally

How exactly do static fields work internally?

While the exact details of the type system are implementation dependent, let me go into some more detail than just stating that it depends and you should not care. I'll describe how it approximately works in Microsoft's implementation (.NET) according to the book CLR via C# by Jeffrey Richter and the article See How the CLR Creates Runtime Objects by Hanu Kommalapati et al. (original MSDN May 2005 issue).


Say you have a class:

class Foo
{
// Instance fields
string myBar = "Foobar";
int myNum;

// Static fields
static string bar = "Foobar";
static int num;
}

Foo myFoo = new Foo();
Type typeOfFoo = typeof(Foo);

Where do the instance fields live?

Whenever you say new Foo(), space is allocated and initialized for the object instance, and the constructor is called. This instance is shown as instance of Foo in the image below. Such as instance contains only the instance fields of the class (in this case myBar and myNum), and for objects allocated on the heap two extra fields used by the runtime (Sync block index and Type handle). The type handle is a pointer to a Type object that describes the type of the instance, in this case type of Foo.

When you say new Foo() again, new space is allocated which will again contain space for the instance fields of the type. As you can see, instance fields are associated with object instances.

The runtime puts each instance field at a fixed offset from the start of the object's data. For example, myBar might live at offset +4. The address of the instance field is simply the address of the object plus the offset of the field.

Where do the static fields live?

Static fields in C# and Java are not associated with any object instance, but with a type. Classes, structs and enums are examples of types. Only once (per type) is some space allocated to hold the values of the static fields. It would make sense to allocate space for the static fields in the Type structure that describes the type, since there is also only one Type object per type. This is the approach taken by C# and Java.

The Type object1 is created when the type is loaded by the runtime. This structure contains all sorts of information needed for the runtime to be able to allocate new instances, call methods and perform casting, among other things. It also contains the space for the static fields, in this case bar and num.

The runtime has put each static field at some offset from the start of the type's data. This is different for each type. For example, bar might live at offset +64. The address of the static field is the address of the Type object plus the offset of the field. The type is statically known.

Displays some object structures, and their relationships.

1) In Microsoft .NET multiple different structures describe a type, such as the MethodTable and the EEClass structures.

How does the static keyword work in Java?

Where is this copy stored?

The copy (static variable) is stored in the Permanent Generation section, but if you use Java8 the Permanent Generation section no longer exists.
The static variables and static methods are part of the reflection data which are class-related data and not instance-related.

How do the objects access that copy?

Every instance of class (object) that you have created has a reference to the class.

When is this copy created?

It is created at runtime when the class is loaded: this is done by the classloader of the JVM when the class is first referenced.

Static variables belong to the class, and not to instances of the class.
Your intuition is right - you have only one copy regardless of how many object you create.

You can access a static variable using the name of the class, like in this example:

class Static {

static int staticField;

}

public class UseStatic {

public static void main(String[] args) {

System.out.println(Static.staticField);

}
}

The static fields are useful to create some kind of class constants.

Finally, to easily initialize a static field of a specific class you can use Static Initialization Blocks.

Sources: University course on java, java official documentation

Java: where do static fields live within the memory?

Static fields are class variables, and are shared amongst all instances of that class. Instance variables (or object fields as I think you are referring to them as) belong to individual instances of a class and are not shared.

As for where they are stored in memory is going to based on the implementation of the JVM and there is no reason two different JVMs would be required to store them in the same place by specification (to the best of my knowledge at least - should insert appropriate spec sheet link here).

Where are all the static members stored?

First, note that all of this is an implementation detail. The only thing the runtime guarantees is:

  • When you ask for a static field, it's there
  • A static constructor is executed at some point before you use the type

That's pretty much it. Everything else is an implementation detail - the specification doesn't care about stack, heap or anything else. It's up to the implementation of the runtime, and a valid runtime could put everything on the stack, if it so desired, or on the heap. And don't forget registers.

Now, let's see some of the misconceptions you already managed to pick up:

  • Static is just for the lifetime - yes. It doesn't say anything about when or where it is stored - just that it's available when you asked for it. A compliant runtime is free to use whatever memory it wants, or even never to load the fields in memory (e.g. keeping it in the image, which is already in memory anyway)
  • Static will go on heap, for life time - most likely, yes. But it's not part of the specification, and a compliant runtime can store it wherever it wants, or nowhere at all, as long as the proper guarantees hold. Also, don't forget that "for life time" means "at least for the life time of the AppDomain"; it may or may not be released when the domain is unloaded.
  • Static value type will go on stack, for life time - most likely, no. Again, an implementation detail, but the stack has completely different semantics than what makes sense for a static value. And the next point will give you more of a reason why:
  • When the assambly is loaded, all static constructors are called, including static fields. - No. There is no such requirement, and no such guarantee. If you rely on this, your program is going to break (and I've seen that plenty of times before). Again, an implementation detail, but in the current MSCLR implementations, statics tend to be allocated in a heap of their own, and some time before the type they are defined in is needed. You can easily see this if you throw an exception in a static constructor - it will cause a TypeLoadException, most likely in a method that first references the type (needless to say, this can make debugging statics tricky).
  • Reference types go on the heap, value types go on the stack. - No. This is confusing the mechanism with the semantics. The only difference between the two are their semantics - everything else is up to the implementation. If a runtime can preserve reference semantics for reference types on the stack, that's perfectly valid. And even with current MSCLR runtimes, value types are stored on the heap all the time - whenever they are boxed, or members of a reference type, for example.

Some folks may be confused. Some don't understand the difference between the contract, and the practical implementations. Some simply don't know what they're talking about. I wish there was an easy way to know which is which, but there isn't. If in doubt, you can go to the C#/CLR specifications, but that only tells you about the contract, not the practical reality.

The whole point of managed memory is that you aren't supposed to care about these implementation details. Of course, like any abstraction, it leaks - and it makes sense to know how things really are, down to the CPU micro-intructions, memory caching etc., through all the various layers and abstractions. But it's nothing to rely on - the implementation can change at any time, and it has many times in the past.

When and who creates the instance of static class?

A static class cannot be instantiated. In other words, you cannot use the new keyword to create a variable of the class type. Because there is no instance variable, you access the members of a static class by using the class name itself.

The following list provides the main features of a static class:

  • Contains only static members.
  • Cannot be instantiated.
  • Is sealed.
  • Cannot contain Instance Constructors.

In C#, what refers to a static variable of a reference type in runtime that makes in accessible in heap?

Static variables “always” exist and represent strong roots (if they have no assigned value the point is moot).

As noted, static variables are stored independent of any instance. Consider that each loaded class type is also modeled as Type (ie. there is runtime metadata and designated internal implementation structures for each type). Conceptually, this is “how” such static variables can be associated and backed by specialized internal heaps.

However, the objects assigned to static variables follow normal “heap allocation” rules as the storage of a variable is different from the storage of objects it refers to. (So don’t worry about the implementation details of static variables.)

Relating to object lifetimes, value assignment to static members only occurs during and after static class initialization. That is, while static variables “always” exist, they are not always initialized.

In the above case, “new B()” is only invoked if something else causes A to go through static initialization. The ‘something else’ is an implementation detail, although it is guaranteed to occur before any static member is accessed or instance is created.

Thus the reachable lifetime of the object assigned to A::b is from the static initialization of A until the variable is re-assigned or the program ends. And in the shown code, there is no guarantee that A is ever initialized..

In laymans terms, what does 'static' mean in Java?

static means that the variable or method marked as such is available at the class level. In other words, you don't need to create an instance of the class to access it.

public class Foo {
public static void doStuff(){
// does stuff
}
}

So, instead of creating an instance of Foo and then calling doStuff like this:

Foo f = new Foo();
f.doStuff();

You just call the method directly against the class, like so:

Foo.doStuff();


Related Topics



Leave a reply



Submit