3

I am reading "The Go Programming Language" right now and I have read package initialization chapter which tells (or I read it wrong) that Go uses eagerly initialization.

So in time we saw say C++ eagerly initialization, then Java with on demand initialization, C# also on demand, and Go back with eager initialization (those languages are not strictly related, I am talking about time).

And I am curious about the reasons (in historical perspective) why on-demand model was chosen for Java and C#.

7

C++ and Go are designed to compile to native machine code. Both have a phase during building where separate modules are linked together to produce a single combined module. Once this has been done, a complete list of all available objects is available. Therefore, the easiest way to initialise any object that requires initialisation is to scan that list, check for init code, and call it (there may be slightly more subtlety to it than that, but as a broad conceptual level it's close enough to how it works for the purposes of this discussion).

Java and C# were both designed to run in a virtual machine environment. Java specifically was designed to perform on-demand loading of code. Linkage is deferred until runtime in order to allow, for example, modules to reside on a remote server where they may be updated without changing the remaining program (this is important for Java's original designed purpose, which was for writing applications for smart tv systems). Furthermore, classes may be added to the system at runtime (using Class.forName). This means that it is impossible for a Java application to determine a complete list of all classes it may use at build time, or even when the application begins running. Therefore it is impossible for Java to perform initialisation at application start.

C#, AFAIK, had a design goal that it needed to be able to be used for any kind of application where Java could already be used. It therefore needed to follow Java's lead in using on-demand loading, even though it does have a separate link step, because not doing so would make it hard to support network-loaded applications.

  • although C++ can load modules dynamically and it doesn't know about them until runtime either. What happens when you load a dll is that any statics are initialised at dll load time. So I think your explanation is incorrect. Java/C# probably do it because of optimisation - init onl;y occurs when the JIT first sees the bytecode and turns it into real code. – gbjbaanb Jan 25 '16 at 10:07
  • 1
    C++ doesn't know about dynamically loaded code at all, per se. A dynamic library which is loaded at runtime (as opposed to one which is integrated at build time) is not really integrated in the same way that Java runtime code is. There is no way, for example, for C++ code to directly refer to types in a runtime loaded library. In Java/C# there is such a way. – Jules Jan 25 '16 at 19:32
2

My ideas on why lazy initialization may be preferrable in .NET:

  1. Eager init can be quite hard to debug
    I don't know about now, but earlier, when I had problems with static init in C++, it was a nightmare and I rather went away from using static in some cases.
    Static init dependencies can be a headache even in C#, luckily they are much easier to debug and there are even limited testing posibilities. See this post by Jon Skeet for further information.
  2. Avoiding unnecessary init
    Unlike C++ constants, the .NET constants are not very powerful and so the static sees a very wide usage. With a vast amount of statically initialized memory, it might be wiser to initialize it on demand rather than further lengthen the program start-up which can already be a pain with a JIT-compiled language.
    This feels similar to .NET's exclusive usage of .dlls and their dynamic loading during program run-time.

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.