A

Aleksey Shipilëv

shipilev.net · Personal blog · on HN since 2014

Aleksey Shipilëv, a JVM performance engineer, writes detailed posts on JVM internals, the Java memory model, benchmarks and optimizations.

What HN saysHN commenters call the JVM Anatomy posts a gem they learned a lot from, and say he explains JVM internals and performance very well.
112HN people shared it
71linked it in comments
76stories submitted
2.3Kstory points
3 months agolast shared
2014people per year2026

Most-shared posts

  1. 1
    JVM Anatomy Quarks
    12 people · 434 points · first shared 2020 · 85 comments on HN
  2. 2
    The Black Magic of Java Method Dispatch
    8 people · 133 points · first shared 2015 · 16 comments on HN
  3. 3
    Close Encounters of the Java Memory Model Kind
    8 people · 121 points · first shared 2016 · 65 comments on HN
  4. 4
    18 scalar replacement
    7 people · first shared 2020
  5. 5
    JVM Anatomy Quark #25: Implicit Null Checks
    6 people · 2 points · first shared 2020 · discussion on HN
  6. 6
    JVM Anatomy Quarks: Compressed References
    5 people · 141 points · first shared 2019 · 34 comments on HN
  7. 7
    Please Test Your Memory
    5 people · 15 points · first shared 2020 · 2 comments on HN
  8. 8
    JVM Anatomy Park #18: Scalar Replacement
    5 people · 2 points · first shared 2018 · discussion on HN
  9. 9
    4 tlab allocation
    5 people · first shared 2021
  10. 10
    JVM Anatomy Park
    4 people · 358 points · first shared 2017 · 32 comments on HN
  11. 11
    Do-It-Yourself OpenJDK Garbage Collector
    4 people · 159 points · first shared 2019 · 4 comments on HN
  12. 12
    Java Memory Model Pragmatics
    4 people · 112 points · first shared 2014 · 21 comments on HN
  13. 13
    Re-evaluating the StoreLoad instruction sequence for x86
    4 people · 14 points · first shared 2014 · discussion on HN
  14. 14
    Nanotrusting the Nanotime
    4 people · 12 points · first shared 2014 · 1 comments on HN
  15. 15
    Arrays of Wisdom of the Ancients
    4 people · 9 points · first shared 2016 · discussion on HN

What HN people wrote when they linked it

kovrik · 2014-03-06
Thanks! I would also recommend watching/reading Aleksey Shipilev: http://shipilev.net
wging · 2025-05-03
String compression was one. tl;dr: the JVM supports Unicode for strings, but uses 1-byte chars for strings where possible (previously it was UTF-16), even though it's not actually doing UTF-8. Depending on what sort of document you're looking for, you might like either the JEP: https://openjdk.org/jeps/254 or Shipilev's slides (pdf warning): https://shipilev.net/talks/jfokus-Feb2016-lord-of-the-strings.pdf Shipilev's website (https://shipilev.net/#lord-of-the-strings), and links from the JEP above to other JEPS, are both good places to find further reading. (I think I saw a feature article about the implementation of the string compression feature, but I'm not sure who wrote it or where it was, or if I'm thinking about something else. Actually I think it might've been https://shipilev.net/blog/2015/black-magic-method-dispatch/, despite the title.)
dhash · 2024-12-30
My favorite illustrations for the concepts discussed here (in an accessible form, not the processor optimization manuals) has long been [0]. For me, this really makes working with a modern microprocessor a science, as anyone who has written benchmarks knows -- it's difficult to reason about the complex behaviour and performance cliffs without testing. Another excellent example of the weirdness has to be JVM anatomy quarks [1] [0] https://www.lighterra.com/papers/modernmicroprocessors/ [1] https://shipilev.net/jvm/anatomy-quarks/
lsuresh · 2024-11-10
Happy to see this gem shared here. I've learnt a lot about the JVM going through these. This article about the "stack allocation" misnomer in Java in particular is one of my favorites: https://shipilev.net/jvm/anatomy-quarks/18-scalar-replacement/. What the JVM really does is escape analysis + scalar replacement.
unportant · 2022-12-22
For Java see The Exceptional Performance of Lil' Exception from Aleksey Shipilëv, https://shipilev.net/blog/2014/exceptional-performance. As always, Shipilëv does a fantastic job at explaining inner details of the JVM and observed performance profile. A few years ago, I got hit by the high cost of an hidden exception (used for flow control by the JDK) while using LocalDate#format to parse a valid date. It was fun to troubleshoot and fix OpenJDK https://unportant.info/using-exceptions-for-flow-control-is-slow-even-… I would be interested in reading similar articles for other languages.
vips7L · 2022-05-10
Shipilev’s entire blog is worth reading. He’ll even email you back if you have questions. I really enjoy his anatomy quarks series: https://shipilev.net/jvm/anatomy-quarks/
bitcharmer · 2021-12-27
I love how you insist on using the "vastly superior" phrase to mock something's you haven't even seen but have strong opinions about right off the bat. Not taking the bait, anyone who can read and comprehend Java code will tell you the same. What I refer to is a standard way of approaching Java code benchmarking. https://shipilev.net/talks/jvmls-July2013-benchmarking.pdf
native_samples · 2021-11-23
It's not a book but Shipilev's Quarks are an excellent source for some of the more obscure corners: https://shipilev.net/jvm/anatomy-quarks/ BTW green threads haven't been used for decades ;)
DmitryOlshansky · 2020-02-23
Java compressed object pointers. Shipilev (JVM performance engineer) explains it in great detail here: https://shipilev.net/jvm/anatomy-quarks/23-compressed-references/ But the short of it: Java uses 32-bit numbers for object references if it can address whole heap with it. Given default 8-byte alignment of object we have 2^32 * 8 = 32g of addressable heap. Once we are beyond that number 64-bit references are used and suddenly we are wasting a lot of heap space (Java is very much objects everywhere). Usually up to around 40% of heap is references.
nullwasamistake · 2019-05-27
JVM is very smart about locking. My knowledge is limited but this is a great article. https://shipilev.net/jvm/anatomy-quarks/19-lock-elision/
akerro · 2018-06-09
I also recommend this JVM anatomy https://shipilev.net/jvm-anatomy-park/
r4um · 2018-01-07
Another excellent series on JVM perf/internals https://shipilev.net/jvm-anatomy-park/
nayuki · 2017-12-31
About the monomorphic and bimorphic virtual methods, Aleksey Shipilev has some great articles on the topic, including low-level benchmarks: https://shipilev.net/blog/2015/black-magic-method-dispatch/
hyperpape · 2017-08-04
"The way to test the performance of System.currentTimeMillis() is straightforward" I'd be worried about that claim. The article executes System.currentTimeMillis in a loop and sums the values. That takes care of dead code elimination, but it will still be subject to other distortionary effects (https://shipilev.net/#benchmarking-1). Maybe the fact that System.currentTimeMillis() is implemented using native code reduces some of the JIT induced benchmarking pitfalls, but I would still prefer to try and use JMH to test. I'm also surprised that performance of System.currentTimeMillis can fall down so far under some circumstances. In one of Cliff Click's talks (maybe https://www.youtube.com/watch?v=-vizTDSz8NU), he mentions that some JVM benchmarks run it many millions of times a second.
eropple · 2016-08-14
Two things: - I became the JVM whisperer for a fairly large company a whole year out of college. JVM tuning is not that complex, nor is the Java memory model. Shipilev's talk on the JMM[1] is almost everything you could ever need to know, and you can refer to it when you need it. - That you actually can meaningfully tune the JVM GC is something you can't say about a lot of the alternatives. Like, I love the CLR, but the "self-tuning" nature of the garbage collector has bitten me more than once in the past. [1] - https://shipilev.net/blog/2014/jmm-pragmatics/
igouy · 2014-07-31
http://shipilev.net/talks/jvmls-July2014-benchmarking.pdf Slide 6/75 Theory: Why would people benchmark? Slide 7/75 Theory: In the name of Holywar My favorite example: Computer Language Benchmarks Game In the name of Teaching Replace very-wrong ideas with less-wrong ideas.
unscaled · 2026-08-04
I don't think it was true even in 2023. This sounds like tackling the problems of C++ in the early 2000s. 1. Casey Muratori also that DRY shouldn't doesn't have to result in non-performant code. 2. Smaller functions, functions that do one-thing: Modern compiler can inline those. There are some edge cases where inlining may make less efficient use of states and loops but I don't think that's a main problem nowadays. I also wouldn't say the extreme version of this idea (very small functions) is still popular. The strongest proponent of this was Uncle Bob, and the last time I've heard him speak about code, he said he now lets the LLM write everything and he only reviews the module hierarchy and maybe the modules' public interfaces. 3. Polymorphism instead of ifs and switches was a big fad in the late 1990s until the late 2000s and had some holdouts in the 2010s. It was only ever popular in the Enterprise Java and C++ world (and maybe in Enterprise Smalltalk, never hard). Overuse of runtime polymorphism widely considered bad form in newer static languages like Go and Rust and in most dynamic languages there was always a tacit understanding of "use mostly conditions, add polymorphism if you need extensibility". In functional languages (or languages heavily influenced by functional programming like Rust, Swift and Kotlin[1]), the classic approach for the type of scenario in this example is to use a sum type, and run a safe exhaustive match/switch on all the variants. 4.…
xmcqdpt2 · 2025-08-19
It's really not hard to reproduce, - vt1 locks lock1 - vt1 suspends on lock2 - n VTs attempt to initialize a singleton that requires lock1, so they all suspend within pinning class init. - you release lock2. - all platform threads are pinned, so vt1 can't run and you hang forever. There is no lock inversion and progress would have been entirely possible with platform threads, even with just one. It happened on our system because we have parallel streams that all access the same singleton at the same time, which is fairly easy to do (you have lots of parallelism, you have a map operation that needs a value from your singleton and that's it.) The solution is to never suspend while in a static block, but it's hard to generalize because... any method may suspend, and there is no way to know that it will because of colourlessness. And also the singleton pattern is common, often involve accessing expensive resources or IO (and suspending) and doing so with class init lock is recommended and common, https://shipilev.net/blog/2014/safe-public-construction/#_safe_publica… In our case this involves scala's object {} which is a singleton defined using class init. Kotlin probably works the same way.
Ygg2 · 2024-11-26
> A failure can propagate in the same circumstances in a Rust program. What do you consider failure? A result or a panic? Those are worlds apart. > First, Rust has panics, which are exceptions. That's not how exceptions work in Java. Exceptions are meant to be caught (albeit rarely). Panics are meant to crash your program. They represent a violation of invariants that uphold the Safety checks. Only in extreme cases (iirc Linux kernel maintainers) was there a push to be able to either "catch panics" or offer a fallible version of many Rust operations. The Rust version of Java Exceptions are Results. And they are "checked" by default. That said, Exceptions in Java are huge, require gathering info and slow as molases compared to returning a value (granted you can do some smelly things like raising static exceptions)[1]. [1] https://shipilev.net/blog/2014/exceptional-performance/ > Non-specific criticism. If your complaint is that exceptions don't appear in function signatures, you can design a language in which they do. The mechanism is called "checked exceptions" And everyone hates checked exceptions. Because rather than having a nice pipe that encapsulates errors like Result, you list every minute Exception possible, which, if we followed the mantra of "every exception is a checked exception" would make, for example, Java signatures into an epic rivaling Iliad. > Besides, in the real world, junior Rust programmers (and some senior ones who should be ashamed of…
aardvark179 · 2018-03-26
Most of these really don't matter as soon as you are using a JIT, and some that seem entirely obvious are much more problematic than you might hope. Final field values can be changed through reflection and some other methods. The Java Language Specification allows a compiler/VM to ignore changes to final fields, but several libraries require them to be seen. So the that can't be optimised at the bytecode level. The JIT can optimise final field access for some internal classes, and others if an option is set (see https://shipilev.net/jvm-anatomy-park/17-trust-nonstatic-final-fields/… and in Truffle based languages like TruffleRuby (https://github.com/oracle/truffleruby) we can tell the JIT that certain things are truly constant, but this can't be done universally for Java. If you're producing bytecode and you want it to run fast then your best bet is to produce bytecode that is similar to javac's as that's what Hotspot has been tuned to run fast, even if it doesn't look optimal.
dmit · 2016-04-25
Here are some software engineering blogs from my RSS reader in addition to the ones listed in TFA. I honestly don't know how over or underrated they are, but I guess that varies depending on which communities you're closer to. Mikola Lysenko https://0fps.net Graphics programming, geometry and algorithms. --- Steven Wittens http://acko.net Not underrated in any sense of the word, but I have to include it in case there are people who haven't seen it yet. It's about math and graphics, but also about art and design. Amazingly educational. http://acko.net/blog/how-to-fold-a-julia-fractal/ is a good starting point for new readers. --- Mark Nottingham https://www.mnot.net/blog/ Networking and HTTP. --- Jeff Preshing http://preshing.com Efficient concurrent data structures. --- Bruce Dawson https://randomascii.wordpress.com Software efficiency, performance optimization, fractals and more. --- Yann Collet http://fastcompression.blogspot.com Modern compression algorithms. --- Gil Tene http://stuff-gil-says.blogspot.com Also definitely not underrated, at least not in the Java world. But any engineer who cares about latency and honest benchmarks will benefit. Low latency techniques, GC performance, lock-free programming. --- Tony Finch http://fanf.livejournal.com C and UNIX programming, and more. --- Andy Wingo https://wingolog.org Scheme, Compilers, JavaScript, and much more. --- Aleksey Shipilёv http://shipilev.net JDK internals, low-level optimization.
pgrulich · 2026-02-26
Yes, Hotspot performs Escape Analysis to avoid heap allocation. This is a nice article: https://shipilev.net/jvm/anatomy-quarks/18-scalar-replacement/
ackfoobar · 2025-05-12
> a byte array is in reality layed out as a (mostly empty) long array in Java Are you saying each byte takes up a word? That is the case in the `char array` in OCaml, but not Java's `byte[]`. AFAIK The size of a byte array is rounded up to words. Byte arrays of length 1-8 all have the same size in a 64-bit machine, then length 7-16 take up one more word. https://shipilev.net/jvm/objects-inside-out/
masklinn · 2024-11-25
> Thanks for the answer. But is this actual behaviour for the GCs of the JDK? I was certain that at the very least Hotspot makes use of stack allocation as much as possible. Not really, java has some escape analysis but it's very limited in its ability to stack allocate as it can't put entire structures (objects) on the stack, it only works if the compiler manages to scalar-replace the object (https://shipilev.net/jvm/anatomy-quarks/18-scalar-replacement/) and that has somewhat restricted applicability (https://pkolaczk.github.io/overhead-of-optional/). The behaviour I'm talking about is mostly that of Go, as it is much more capable of stack allocating, and specifically has a non-generational GC because in testing they found generational GCs had a very variable impact depending on workload (rather than a universally or near universally positive impact).
quotemstr · 2024-11-10
https://shipilev.net/jvm/anatomy-quarks/17-trust-nonstatic-final-field… is a damned shame. User code misses out on an important optimization available only to system-provided classes because certain frameworks have abused JNI and reflection to mutate final fields, which by all rights should be immutable. Platforms, especially compilers and runtimes, need to be absolutely strict in enforcing semantic restrictions so as to preserve optimization opportunities for the future.
a-dub · 2024-07-05
more interesting explanation and benchmarks: https://shipilev.net/jvm/anatomy-quarks/25-implicit-null-checks/ hotspot's always-on runtime profiling (and corresponding runtime dynamic optimization) is pretty neat.
fniephaus · 2024-03-18
Correct: > ... the JVM can intercept the resulting SIGSEGV ("Signal: Segmentation Fault"), look at the return address for that signal, and figure out where that access was made in the generated code. Once it figures that bit out, it can then know where to dispatch the control to handle this case — in most cases, throwing NullPointerException or branching somewhere. https://shipilev.net/jvm/anatomy-quarks/25-implicit-null-checks/#_theo…
epakai · 2023-10-31
I enjoyed https://shipilev.net/labs/network-de/ It's similar to my own personal knowledge base (non-public at the moment), but I like it enough that I used it as a reference to tweak my own a bit. The output seems to come from Asciidoctor, but I don't know if it's been modified.
tjalfi · 2023-09-21
Here's an article[0] with some information on Hotspot's bump allocators. [0] https://shipilev.net/jvm/anatomy-quarks/4-tlab-allocation/
wolf550e · 2023-08-24
You want something like https://shipilev.net/jvm/anatomy-quarks/ (the author is a jvm maintainer, formerly at redhat now at aws).

Keyboard shortcuts

/Search
j kNext / previous blog
EnterOpen selected blog
vVisit the blog site
fFollow / unfollow
lSwitch grid / list view
dSwitch dark mode
g hHome
g pTop posts
g tTopics
g fFollowing
g lLiked
g yHistory
g qFAQ
EscBack / close