<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Pangin.pro</title>
    <description>JVM Treasure Hunt</description>
    <link>https://pangin.pro/</link>
    <atom:link href="https://pangin.pro/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Mon, 22 Jul 2019 23:25:12 +0300</pubDate>
    <lastBuildDate>Mon, 22 Jul 2019 23:25:12 +0300</lastBuildDate>
    <generator>Jekyll v3.7.4</generator>
    
      <item>
        <title>Stack Overflow handling in HotSpot JVM</title>
        <description>&lt;p&gt;As you probably know, HotSpot JVM has one-to-one mapping of Java threads to OS threads.
Each thread is associated with its own stack. Sounds simple… until you realize
that in Java there are at least 3 different notions of a stack:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.5.2&quot;&gt;Java Virtual Machine Stack&lt;/a&gt;,
which stores local variables and keeps track of method invocations.
As the specification says, this stack does not need to be contiguous
and may be heap allocated. E.g. Java ME virtual machine (that I worked on at Sun Microsystems)
indeed had chunked stacks allocated in Java heap.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.6.2&quot;&gt;Operand Stack&lt;/a&gt;,
which holds operands for bytecode instructions.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html#jvms-2.5.6&quot;&gt;Native Stack&lt;/a&gt; -
the classical “C” stack required for native method execution.&lt;/li&gt;
&lt;/ul&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;jvm-stack-layout&quot;&gt;JVM stack layout&lt;/h2&gt;

&lt;p&gt;HotSpot JVM uses one contiguous stack for all the above purposes.
Java methods and native methods share the same stack with Java and native frames
interleaved. Unlike C, where stack space can be allocated dynamically with
&lt;a href=&quot;http://man7.org/linux/man-pages/man3/alloca.3.html&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;alloca()&lt;/code&gt;&lt;/a&gt;,
the maximum stack usage of any Java method is known beforehand,
but may very depending on whether the method is interpreted or compiled.
The compiled frame is often smaller than the interpreter frame for the same method –
this seems intuitive, since the optimizing compiler does not need to have
all the local variables and all the monitors on the stack.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/stack-frames.png&quot; width=&quot;240&quot; alt=&quot;Stack frames&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Each thread stack has limited capacity.
The stack size is configured with &lt;code class=&quot;highlighter-rouge&quot;&gt;-Xss&lt;/code&gt; option and defaults to 1 MB on a 64-bit system.
This is usually enough to place several thousand average frames.&lt;/p&gt;

&lt;p&gt;When a call chain becomes too deep and there is no free space on the stack to create more frames,
Java obviously throws StackOverflowError. But how does JVM know when it’s time to throw an error?
It simply performs a stack overflow check on every method invocation.
There are some interesting details though.&lt;/p&gt;

&lt;h2 id=&quot;interpreter-vs-stack-banging&quot;&gt;Interpreter vs. Stack banging&lt;/h2&gt;

&lt;p&gt;Interpreter performs a straightforward check in a method prologue.
It takes the address of a stack limit for the current thread and compares it
to the stack pointer in RSP register adjusted by the size of the current stack frame,
see &lt;a href=&quot;http://hg.openjdk.java.net/jdk/jdk/file/8ae33203d600/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp#l512&quot;&gt;TemplateInterpreterGenerator::generate_stack_overflow_check&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-nasm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;k&quot;&gt;mov&lt;/span&gt;    &lt;span class=&quot;err&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;edx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;eax&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;shl&lt;/span&gt;    &lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rax&lt;/span&gt;         &lt;span class=&quot;c&quot;&gt;; rax = number_of_locals * 8 bytes&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;add&lt;/span&gt;    &lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x58&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rax&lt;/span&gt;        &lt;span class=&quot;c&quot;&gt;; + constant frame overhead&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;add&lt;/span&gt;    &lt;span class=&quot;mh&quot;&gt;0x410&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r15&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rax&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;; + current_thread.stack_limit&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;cmp&lt;/span&gt;    &lt;span class=&quot;err&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rsp&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;ja&lt;/span&gt;     &lt;span class=&quot;mh&quot;&gt;0x7fffe054e55f&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;; if rsp &amp;gt; rax, continue normally&lt;/span&gt;
                           &lt;span class=&quot;c&quot;&gt;; otherwise throw StackOverflowError&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Even though the check is relatively simple, it still involves at least one memory load,
a few arithmetic instructions and a conditional jump on &lt;em&gt;every&lt;/em&gt; method invocation.
That would be too much for a hot JITted code.&lt;/p&gt;

&lt;p&gt;Compiler’s strategy is different. In most cases, the stack overflow check in
C1- or C2-compiled code is just a single store instruction:&lt;/p&gt;

&lt;div class=&quot;language-nasm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;k&quot;&gt;mov&lt;/span&gt;    &lt;span class=&quot;err&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x14000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rsp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It writes any meaningless value from EAX register onto the stack somewhere above
the current stack pointer. If there is enough free space above the current frame,
this instruction is harmless. Otherwise it touches one of the &lt;strong&gt;guard pages&lt;/strong&gt;,
and the hardware exception is triggered. This technique is called &lt;strong&gt;stack banging&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;guard-pages&quot;&gt;Guard pages&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/img/stack-guardzone.png&quot; width=&quot;360&quot; alt=&quot;Guard zone&quot; /&gt;&lt;/p&gt;

&lt;p&gt;When JVM allocates a stack for a new thread, it reserves a few pages
on the top of the stack – the &lt;strong&gt;guard zone&lt;/strong&gt;. All the guard pages are initially
&lt;a href=&quot;http://man7.org/linux/man-pages/man2/mprotect.2.html&quot;&gt;protected&lt;/a&gt;
from both reading and writing, so that any access to these pages causes
Segmentation Fault (SIGSEGV). However, these SIGSEGVs are managed by the JVM,
i.e. the signal handler detects which guard page has been accessed, and acts accordingly.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;span style=&quot;background-color: #ffc000&quot;&gt;Yellow zone&lt;/span&gt; is used for detecting
recoverable stack overflows. If a stack banging instruction hits the yellow zone,
SIGSEGV happens, and the signal handler resumes the current thread from the continuation
that throws StackOverflowError. Meanwhile the yellow zone is disabled
(i.e. the pages are unprotected) to give some extra stack space for the exception
throwing code. The yellow pages are reguarded later during stack unwinding.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;span style=&quot;background-color: #d04040; color: #ffffff&quot;&gt;Red zone&lt;/span&gt; is for handling
unrecoverable stack overflows. This is the last line of defence. Normally, the red pages
should never been touched, but if this happens for any reason, JVM treats this
as a fatal error and dies leaving the final crash report. The red zone is unguared only
to provide some stack space for writing &lt;code class=&quot;highlighter-rouge&quot;&gt;hs_err_pid.log&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;span style=&quot;background-color: #bf9000; color: #ffffff&quot;&gt;Reserved zone&lt;/span&gt;
has been added in JDK 9 to address the problem when StackOverflowError occurs
in a critical section, e.g. while executing &lt;code class=&quot;highlighter-rouge&quot;&gt;ReentrantLock.lock()&lt;/code&gt;. If an error is thrown
in the middle of &lt;code class=&quot;highlighter-rouge&quot;&gt;lock()&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;unlock()&lt;/code&gt; method, the ReentrantLock object may remain
in an inconsistent state, so no other thread would be able to acquire the lock again.&lt;/p&gt;

    &lt;p&gt;The problem and the solution is described in &lt;a href=&quot;https://openjdk.java.net/jeps/270&quot;&gt;JEP 270&lt;/a&gt;.
The idea is to reserve an additional stack page for execution of such critical methods.
Reserved zone acts like a yellow zone with one exception: when stack banging hits
the reserved zone during the execution of a critical method, JVM unprotects
the reserved pages allowing the critical method to finish.
StackOverflowError is deferred until the critical method returns.&lt;/p&gt;

    &lt;p&gt;Current HotSpot implementation treats a method &lt;em&gt;critical&lt;/em&gt; if it is annotated with
&lt;code class=&quot;highlighter-rouge&quot;&gt;@jdk.internal.vm.annotation.ReservedStackAccess&lt;/code&gt;.
As of JDK 12, there are only a few of them:&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;acquire / release methods in &lt;code class=&quot;highlighter-rouge&quot;&gt;ReentrantLock.Sync&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;ReentrantReadWriteLock.Sync&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;lock / unlock methods in &lt;code class=&quot;highlighter-rouge&quot;&gt;StampedLock&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;AccessController.wrapException&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When a stack overflow happens in one of the above methods, JVM emits the warning
and allow the method to complete:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;OpenJDK 64-Bit Server VM warning: Potentially dangerous stack overflow in ReservedStackAccess annotated method
java.util.concurrent.locks.ReentrantLock$FairSync.tryAcquire(I)Z
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Although JEP 270 makes &lt;code class=&quot;highlighter-rouge&quot;&gt;lock&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;unlock&lt;/code&gt; methods somewhat atomic, it does not guarantee
the invocation of these methods will always succeed. Unfortunately, the simplest lock-unlock
pattern remains fragile:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;n&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;deepCall&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;finally&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;unlock&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If StackOverflowError happens here inside &lt;code class=&quot;highlighter-rouge&quot;&gt;deepCall&lt;/code&gt;, JVM will attempt to execute
the finally block, but a call to &lt;code class=&quot;highlighter-rouge&quot;&gt;unlock&lt;/code&gt; method may result in another StackOverflowError,
leaving the object locked forever. For some reason &lt;code class=&quot;highlighter-rouge&quot;&gt;ReentrantLock.unlock()&lt;/code&gt; method itself
is not annotated with &lt;code class=&quot;highlighter-rouge&quot;&gt;@ReservedStackAccess&lt;/code&gt; :disappointed:&lt;/p&gt;

&lt;h2 id=&quot;shadow-pages&quot;&gt;Shadow pages&lt;/h2&gt;

&lt;p&gt;Remember that HotSpot has Java and native frames on the same stack?
This means, a stack overflow may also happen inside a native method.
The problem is that JVM knows nothing about the layout of non-Java frames,
and of course, cannot unwind the native part of the stack.&lt;/p&gt;

&lt;p&gt;How to deal with that? The idea is to ensure the stack overflow does not happen
in the native code at all! For this purpose HotSpot reserves yet another bunch of stack pages.
This &lt;strong&gt;shadow zone&lt;/strong&gt; is a normal unprotected stack area, except that it can be used
exclusively by the native or VM code, but not by Java methods.
The shadow zone must be large enough to accommodate the deepest VM call or
the deepest native function from the standard JDK library.
The typical example is &lt;a href=&quot;http://hg.openjdk.java.net/jdk/jdk/file/8ae33203d600/src/java.base/unix/native/libnet/SocketOutputStream.c#l57&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Java_java_net_SocketOutputStream_socketWrite0&lt;/code&gt;&lt;/a&gt;
which allocates 64 KB buffer on the stack.&lt;/p&gt;

&lt;p&gt;The default number of shadow pages on Linux x64 is 20 – this means,
native methods can use up to 80 KB of the stack without a risk of JVM crash.
This is where the offset &lt;code class=&quot;highlighter-rouge&quot;&gt;-0x14000(%rsp)&lt;/code&gt; in the bang instruction comes from.&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;0x14000 = 80 KB = 20 pages  -- exactly the size of the shadow zone
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Okay, can I create a JNI method that will allocate more than 80 KB on the stack?
It’s better no to, or I won’t be protected from the crash anymore. If I &lt;em&gt;really&lt;/em&gt; need
so much stack space (perhaps, because of a 3rd party native library out of my control),
I can always add more shadow pages with &lt;code class=&quot;highlighter-rouge&quot;&gt;-XX:StackShadowPages=N&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;NativeStackOverflow&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;recursion&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;depth&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Runnable&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nativeCall&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;nativeCall&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;recursion&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;depth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nativeCall&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;loadLibrary&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;deepNative&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;// Fails with StackOverflowError&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;recursion&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;NativeStackOverflow:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deepNative64K&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;// Crashes JVM, unless StackShadowPages &amp;gt; 32&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;recursion&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;NativeStackOverflow:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deepNative128K&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// JNIEXPORT void JNICALL&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Java_NativeStackOverflow_deepNative64K() {&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//     char buf[64 * 1024];&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//     memset(buf, sizeof(buf), 1);&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// }&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;native&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;deepNative64K&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// JNIEXPORT void JNICALL&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Java_NativeStackOverflow_deepNative128K() {&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//     char buf[128 * 1024];&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//     memset(buf, sizeof(buf), 1);&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// }&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;native&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;deepNative128K&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;hit-the-mark&quot;&gt;Hit the mark&lt;/h2&gt;

&lt;p&gt;By default, the yellow zone consists of two 4 KB pages (&lt;code class=&quot;highlighter-rouge&quot;&gt;-XX:StackYellowPages=2&lt;/code&gt;).
But what if a Java frame is larger than that? A very exotic, but still valid case.
Does not stack banging accidentally jump over the yellow zone?
To ensure the overflow check does not miss the yellow zone, HotSpot touches
&lt;em&gt;all&lt;/em&gt; the involved pages from the bottom to the top.
E.g. before entering a Java method with 10 KB frame, the compiler issues 3 bang instructions:&lt;/p&gt;

&lt;div class=&quot;language-nasm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;k&quot;&gt;mov&lt;/span&gt;    &lt;span class=&quot;err&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x14000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rsp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;mov&lt;/span&gt;    &lt;span class=&quot;err&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x15000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rsp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;mov&lt;/span&gt;    &lt;span class=&quot;err&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x16000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rsp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Not all Java methods require a stack overflow check though.
HotSpot has an optimization to skip stack banging for &lt;strong&gt;small leaf methods&lt;/strong&gt;,
i.e. the methods with no Java calls and with the frame size less than 1/8 page,
see &lt;a href=&quot;http://hg.openjdk.java.net/jdk/jdk/file/8ae33203d600/src/hotspot/share/opto/output.cpp#l158&quot;&gt;Compile::need_stack_bang&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;how-large-is-the-guard-zone&quot;&gt;How large is the guard zone&lt;/h2&gt;

&lt;p&gt;All the guard and shadow zones can be resized with the corresponding JVM options.
The defaults for Linux x64 are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;-XX:StackRedPages=1&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;-XX:StackYellowPages=2&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;-XX:StackReservedPages=1&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;-XX:StackShadowPages=20&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These values affect the minimum stack size a thread can have. Given that HotSpot considers
the &lt;a href=&quot;http://hg.openjdk.java.net/jdk/jdk/file/8ae33203d600/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp#l687&quot;&gt;minimum usable stack&lt;/a&gt;
of 40 KB, the lower bound of the actual &lt;code class=&quot;highlighter-rouge&quot;&gt;-Xss&lt;/code&gt; in JDK 11/12 is&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;min_stack_size = 40 KB + (1 + 2 + 1 + 20) * 4 KB = 136 KB
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If I try to set a lower value, I’ll expectedly get an error:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ /usr/java/jdk-12.0.2/bin/java -Xss100k

The Java thread stack size specified is too small. Specify at least 136k
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Not only HotSpot JVM uses guard pages.
&lt;strong&gt;Glibc&lt;/strong&gt; also reservers a page or a few at the end of the stack when creating
a new thread. However, since JVM already handles stack overflows on its own,
additional glibc guard would be a waste. That’s why HotSpot
&lt;a href=&quot;http://hg.openjdk.java.net/jdk/jdk/file/8ae33203d600/src/hotspot/os/linux/os_linux.cpp#l3168&quot;&gt;explicitly disables&lt;/a&gt;
glibc guard by calling &lt;a href=&quot;https://linux.die.net/man/3/pthread_attr_setguardsize&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;pthread_attr_setguardsize&lt;/code&gt;&lt;/a&gt;
with zero argument.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;HotSpot employs a very efficient stack overflow check which is usually a single
harmless store instruction. The further optimization allows to skip
an overflow check in the compiled code for small leaf methods.&lt;/p&gt;

&lt;p&gt;Special mprotect’ed guard pages at the top of the stack are responsible for
detecting overflows. Yellow pages detect regular Java stack overflows.
Red pages are for handling fatal errors. 
Starting from JDK 9, an additional page is reserved below the yellow zone for
graceful handling of overflows occured in java.util.concurrent lock methods,
however, the mechanism is not bullet-proof.&lt;/p&gt;

&lt;p&gt;For more information about Java stack I invite you to watch my presentation&lt;br /&gt;
&lt;a href=&quot;https://2017.javazone.no/program/c5577d90198b474cbf14c7867209d96c&quot;&gt;&lt;img src=&quot;/img/film.png&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt; Everything you wanted to know about Stack Traces and Heap Dumps&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Mon, 22 Jul 2019 00:00:00 +0300</pubDate>
        <link>https://pangin.pro/posts/stack-overflow-handling</link>
        <guid isPermaLink="true">https://pangin.pro/posts/stack-overflow-handling</guid>
        
        
        <category>jvm</category>
        
        <category>runtime</category>
        
      </item>
    
      <item>
        <title>Beware of computation in static initializer</title>
        <description>&lt;p&gt;It’s a quite common practice to prepare immutable data during class
initialization and save the results in &lt;code class=&quot;highlighter-rouge&quot;&gt;static final&lt;/code&gt; fields.
In fact, this is exactly what static initializers are designed for.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;Here is a typical example that builds some static table at
initialization time:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StaticExample&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100_000_000&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;];&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;TABLE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TABLE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;TABLE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nextValue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TABLE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]);&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;nextValue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;seed&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;seed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x123456789&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;L&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;On my laptop with JDK 11.0.1 static initializer fills the array
of 100M elements in about &lt;strong&gt;540 ms&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Now let’s simply remove &lt;code class=&quot;highlighter-rouge&quot;&gt;static&lt;/code&gt; and fill the array in the constructor.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;NonStaticExample&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100_000_000&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;];&lt;/span&gt;

    &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;TABLE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TABLE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;TABLE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nextValue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TABLE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]);&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;nextValue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;seed&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;seed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x123456789&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;L&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;NonStaticExample&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The constructor fills the similar array in &lt;strong&gt;138 ms&lt;/strong&gt;.
Almost 4 times faster!&lt;/p&gt;

&lt;h2 id=&quot;why-is-static-initializer-slow&quot;&gt;Why is static initializer slow?&lt;/h2&gt;

&lt;p&gt;This must be related to JIT compilation, so let’s run the test with&lt;br /&gt;
&lt;code class=&quot;highlighter-rouge&quot;&gt;-XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;   443   75     3   StaticExample::&amp;lt;clinit&amp;gt; (45 bytes)
                       @ 34   StaticExample::nextValue (10 bytes)   not inlineable
   444   76 %   4   StaticExample::&amp;lt;clinit&amp;gt; @ 15 (45 bytes)
   445   74 %   3   StaticExample::&amp;lt;clinit&amp;gt; @ 15 (45 bytes)   made not entrant
                       @ 34   StaticExample::nextValue (10 bytes)   failed initial checks
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Oops… When compiling static initializer (called &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;clinit&amp;gt;&lt;/code&gt; in a class file) both C1 and C2
failed to inline &lt;code class=&quot;highlighter-rouge&quot;&gt;nextValue&lt;/code&gt; method. Here we get to the first problem:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;HotSpot does not inline methods of uninitialized classes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The explicit check can be found in the &lt;a href=&quot;https://hg.openjdk.java.net/jdk-updates/jdk11u/file/cd1c042181e9/src/hotspot/share/opto/bytecodeInfo.cpp#l455&quot;&gt;source code&lt;/a&gt;.
Since invocation of &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;clinit&amp;gt;&lt;/code&gt; is a part of &lt;a href=&quot;https://docs.oracle.com/javase/specs/jls/se11/html/jls-12.html#jls-12.4.2&quot;&gt;class initialization procedure&lt;/a&gt;,
the class is not considered initialized while &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;clinit&amp;gt;&lt;/code&gt; is running.&lt;/p&gt;

&lt;h2 id=&quot;surprise-in-recent-jdk-updates&quot;&gt;Surprise in recent JDK updates&lt;/h2&gt;

&lt;p&gt;Would you expect JDK updates 11.0.2 and 8u202 to fix the problem?
Just try to run the above example. What took 540 ms on JDK 11.0.1
now lasted &lt;strong&gt;60 seconds&lt;/strong&gt; on JDK 11.0.2! :open_mouth:&lt;/p&gt;

&lt;p&gt;However, the output of &lt;code class=&quot;highlighter-rouge&quot;&gt;-XX:+PrintCompilation&lt;/code&gt; was the same as before,
&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;clinit&amp;gt;&lt;/code&gt; was still compiled. What caused the dramatic slowdown then?
Time to engage &lt;a href=&quot;https://github.com/jvm-profiling-tools/async-profiler/&quot;&gt;async-profiler&lt;/a&gt;.&lt;/p&gt;

&lt;object type=&quot;image/svg+xml&quot; data=&quot;/img/clinit-jdk11.svg&quot; width=&quot;100%&quot;&gt;
  Your browser does not support SVG
&lt;/object&gt;

&lt;p&gt;Most of CPU time is spent inside JVM runtime - &lt;a href=&quot;https://hg.openjdk.java.net/jdk-updates/jdk11u/file/cd1c042181e9/src/hotspot/share/runtime/sharedRuntime.cpp#l1490&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;SharedRuntime::resolve_static_call_C()&lt;/code&gt;&lt;/a&gt;.
But why?&lt;/p&gt;

&lt;p&gt;We’ve seen that class initialization is a &lt;a href=&quot;https://docs.oracle.com/javase/specs/jls/se11/html/jls-12.html#jls-12.4.2&quot;&gt;complicated procedure&lt;/a&gt;
which ensures that static initializer executes in a thread-safe manner at most once.
However, there was a zero-day bug &lt;a href=&quot;https://bugs.openjdk.java.net/browse/JDK-8215634&quot;&gt;JDK-8215634&lt;/a&gt;
that allowed HotSpot JVM to invoke a static method in violation of JVMS.
I explained this problem in detail on &lt;a href=&quot;https://stackoverflow.com/questions/53724687/why-using-parallel-streams-in-static-initializer-leads-to-not-stable-deadlock&quot;&gt;Stack Overflow&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The bug has been fixed in JDK 11.0.2 and 8u201, but at the cost of the terrible
performance degradation :disappointed:&lt;br /&gt;
Now if the class is uninitialized, the resolved &lt;code class=&quot;highlighter-rouge&quot;&gt;invokestatic&lt;/code&gt; target is not saved
in the constant pool cache, so each invocation of a static method needs to go
through the resolution procedure again and again.&lt;/p&gt;

&lt;h2 id=&quot;deoptimization-knock-out&quot;&gt;Deoptimization knock-out&lt;/h2&gt;

&lt;p&gt;It sounds unbelievable, but the above slowdown is not even the worst one.
Let’s slightly modify the example by moving array update out of &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;clinit&amp;gt;&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StaticExample&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100_000_000&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;];&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;TABLE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TABLE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;calcNextValue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;calcNextValue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;TABLE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TABLE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x123456789&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;L&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The algorithm hasn’t changed, right? Except that now it takes forever.&lt;br /&gt;
Or, to be precise, more than &lt;strong&gt;20 minutes&lt;/strong&gt; :sleeping::sleeping::sleeping:&lt;/p&gt;

&lt;p&gt;Compilation log shows desperate attemts to compile the method, but they
all eventually result in deoptimization and a fall back to the interpreter.&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;   610  238   4   StaticExample::calcNextValue (21 bytes)
   610  238   4   StaticExample::calcNextValue (21 bytes)   made not entrant
   611  239   4   StaticExample::calcNextValue (21 bytes)
   611  239   4   StaticExample::calcNextValue (21 bytes)   made not entrant
   611  240   4   StaticExample::calcNextValue (21 bytes)
   612  240   4   StaticExample::calcNextValue (21 bytes)   made not entrant
   612  241   4   StaticExample::calcNextValue (21 bytes)
   612  241   4   StaticExample::calcNextValue (21 bytes)   made not entrant
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It turns out that access to a static field from a static method of
uninitialized class may be an overwhelming obstacle for HotSpot compiler.&lt;/p&gt;

&lt;h2 id=&quot;will-it-be-fixed-anytime-soon&quot;&gt;Will it be fixed anytime soon?&lt;/h2&gt;

&lt;p&gt;Yes, to some extent. The bug is known - &lt;a href=&quot;https://bugs.openjdk.java.net/browse/JDK-8188133&quot;&gt;JDK-8188133&lt;/a&gt;
and is addressed in OpenJDK 13 with a possibility to backport later to OpenJDK 11.&lt;/p&gt;

&lt;p&gt;Unfortunately, the fix covers only one particular case when &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;clinit&amp;gt;&lt;/code&gt;
is the &lt;a href=&quot;https://hg.openjdk.java.net/jdk/jdk/rev/d620a4a1d5ed#l3.7&quot;&gt;root method of the compilation&lt;/a&gt;.
It’s too easy to break the precondition if a hot loop moves from &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;clinit&amp;gt;&lt;/code&gt;
to some other method called by static initializer.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;prepareTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;prepareTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;TABLE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TABLE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;calcNextValue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here &lt;code class=&quot;highlighter-rouge&quot;&gt;prepareTable()&lt;/code&gt; becomes the compilation root, and all the problems of
uninitialized class return back.&lt;/p&gt;

&lt;h2 id=&quot;how-to-live-with-this-knowledge-then&quot;&gt;How to live with this knowledge then?&lt;/h2&gt;

&lt;p&gt;A good news - the workaround is pretty straightforward:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Just don’t do heavy computation in an uninitialized class directly.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you put the computation logic in a helper class with no static initializer,
it won’t suffer from performance penalty.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StaticExample&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Helper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;prepareTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Helper&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

        &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;prepareTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;table&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100_000_000&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;];&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nextValue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]);&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;nextValue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;seed&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;seed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x123456789&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;L&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;see-also&quot;&gt;See also&lt;/h2&gt;

&lt;p&gt;UPDATE: For some reason I missed the &lt;a href=&quot;https://cl4es.github.io/2019/02/21/Cljinit-Woes.html&quot;&gt;recent post&lt;/a&gt;
by Claes Redestad on the same topic. Sorry about that.
I still think my article complements it with some interesting details.&lt;/p&gt;
</description>
        <pubDate>Tue, 26 Feb 2019 00:00:00 +0300</pubDate>
        <link>https://pangin.pro/posts/computation-in-static-initializer</link>
        <guid isPermaLink="true">https://pangin.pro/posts/computation-in-static-initializer</guid>
        
        
        <category>jvm</category>
        
        <category>performance</category>
        
      </item>
    
  </channel>
</rss>
