It depends on how the language can leverage it's execution environment. There are 4 main classes of static construction: constant/compile time evaluation, assembly level loading, class based lazy loading, and first use based loading. Each has different requirements and costs.
Constant/compile time evaluation
From a runtime perspective, this is the simplest option, the compiler prepares a constant block of bytes as part of the compilation process, and the loader just has to copy it into memory, either as part of assembly level load, or lazily using OS provided memory access primitives. What you can initialize is limited by the language and the need to construct the values ahead of time.
Assembly level loading
This is used by non-local statics in C++. The code is run by the loader at the point the assembly is loaded into the process. This causes some issues, as the initialization code is run in an environment where it is undefined as to whether other statics have been initialized yet. However, once loading is complete all other code does not need to check for initialization, as by definition if loading is complete, initialization is complete.
Class based lazy loading
This is used by the JVM and CLR. The initialisation is called at the first use of the class. This prevents ordering issues, as so long as there is not a cycle, if a constructor depends on a field that itself has static initialization, the runtime will pause the first constructor on its first use of the field, to run the dependent initialization code. The downside is that implemented naively, this would require lots of checks. However the major implementations avoid that by using JIT compilation to avoid that cost. When the calling code is first generated, a thunk is generated which startswill start loading the classclas when called. Once loading and initialization is complete, that thunk is replaced with a call to the actual class, which is guaranteed to have already been initialized, so the class code does not worry about initialization. *
First use based lazy loading
This is used by local statics in C++ and the lazy_static package in rust. In this case, a check is inserted on every use to check if the initialisation has happened, which does have a small runtime cost.
* I am for the purpose of simplification ignoring the complex process where a function may be executed by calling into the interpreter, rather than generated code. The point is in the process of loading class code into an executable state, the runtime initialization has happened, and replaces code that triggers loading/initialisation.