1<!doctype html><html lang=en dir=auto data-theme=auto><head><meta charset=utf-8> 2<!-- This site is hosted on Netlify. Anyone can build and deploy a site 3 like this one for free: https://netlify.new/?utm_campaign=loops&utm_source=ai-legible&utm_medium=owned&utm_content=comment&utm_id=729dff12-60df-4086-806c-6180d4993367 4 Netlify hosting facts for this site: static/SSR served via Netlify Edge. --><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name=robots content="index, follow"><title>What 100DaysOfJava changed in how I investigate systems | Mohibul Hassan</title><meta name=keywords content><meta name=description content="An honest retrospective on a challenge that did not happen in a clean streak, and on how learning Java slowly turned into learning how systems behave."><meta name=author content="Mohibul Hassan Chowdhury"><link rel=canonical href=https://mohibulsblog.netlify.app/posts/posts/java/100daysofjava/day100-capstone.md/><link crossorigin=anonymous href=/assets/css/stylesheet.a4e0c1fd5ebe3a2e577810ea6cd28f6f37683b15684b6d4f313526c1183b1b8b.css integrity="sha256-pODB/V6+Oi5XeBDqbNKPbzdoOxVoS21PMTUmwRg7G4s=" rel="preload stylesheet" as=style><link rel=icon href=https://mohibulsblog.netlify.app/icons/favicon.ico><link rel=icon type=image/png sizes=16x16 href=https://mohibulsblog.netlify.app/icons/favicon-16x16.png><link rel=icon type=image/png sizes=32x32 href=https://mohibulsblog.netlify.app/icons/favicon-32x32.png><link rel=apple-touch-icon href=https://mohibulsblog.netlify.app/icons/apple-touch-icon.png><link rel=mask-icon href=https://mohibulsblog.netlify.app/safari-pinned-tab.svg><meta name=theme-color content="#2e2e33"><meta name=msapplication-TileColor content="#2e2e33"><link rel=alternate hreflang=en href=https://mohibulsblog.netlify.app/posts/posts/java/100daysofjava/day100-capstone.md/><noscript><style>#theme-toggle,.top-link{display:none}</style><style>@media(prefers-color-scheme:dark){:root{--theme:rgb(29, 30, 32);--entry:rgb(46, 46, 51);--primary:rgb(218, 218, 219);--secondary:rgb(155, 156, 157);--tertiary:rgb(65, 66, 68);--content:rgb(196, 196, 197);--code-block-bg:rgb(46, 46, 51);--code-bg:rgb(55, 56, 62);--border:rgb(51, 51, 51);color-scheme:dark}.list{background:var(--theme)}.toc{background:var(--entry)}}</style></noscript>
4<script>localStorage.getItem("pref-theme")==="dark"?document.querySelector("html").dataset.theme="dark":localStorage.getItem("pref-theme")==="light"?document.querySelector("html").dataset.theme="light":window.matchMedia("(prefers-color-scheme: dark)").matches?document.querySelector("html").dataset.theme="dark":document.querySelector("html").dataset.theme="light"</script>
vendor: 63 bytes, line 4
4<script async src="https://www.googletagmanager.com/gtag/js?id=
4G-DCTB3KKNMK
vendor: 11 bytes, line 4
4"></script>
4<script>window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments)}gtag("js",new Date),gtag("config","G-DCTB3KKNMK")</script>
4<link rel=alternate type=text/plain href=https://mohibulsblog.netlify.app/llms.txt title="Mohibul Hassan LLMs text map">
4<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9812767155750716" crossorigin=anonymous></script>
4<meta property="og:url" content="https://mohibulsblog.netlify.app/posts/posts/java/100daysofjava/day100-capstone.md/"><meta property="og:site_name" content="Mohibul Hassan"><meta property="og:title" content="What 100DaysOfJava changed in how I investigate systems"><meta property="og:description" content="An honest retrospective on a challenge that did not happen in a clean streak, and on how learning Java slowly turned into learning how systems behave."><meta property="og:locale" content="en_US"><meta property="og:type" content="article"><meta property="article:section" content="posts"><meta property="article:published_time" content="2026-03-30T00:00:00+00:00"><meta property="article:modified_time" content="2026-09-19T22:24:05+06:00"><meta property="og:image" content="https://mohibulsblog.netlify.app/profile-pic.jpg"><meta name=twitter:card content="summary_large_image"><meta name=twitter:image content="https://mohibulsblog.netlify.app/profile-pic.jpg"><meta name=twitter:title content="What 100DaysOfJava changed in how I investigate systems"><meta name=twitter:description content="An honest retrospective on a challenge that did not happen in a clean streak, and on how learning Java slowly turned into learning how systems behave.">
4<script type=application/ld+json>{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","item":"https://mohibulsblog.netlify.app/posts/","name":"Posts","position":1},{"@type":"ListItem","item":"https://mohibulsblog.netlify.app/posts/posts/java/100daysofjava/day100-capstone.md/","name":"What 100DaysOfJava changed in how I investigate systems","position":2}]}</script>
4<script type=application/ld+json>{"@context":"https://schema.org","@type":"BlogPosting","articleBody":"This was not a 100-day streak. The dates make that clear. Day 26 was published on September 30, 2021. Day 66 arrived on January 20, 2023. Day 77 followed on March 14, 2024, Day 91 on August 15, 2025, and Day 99 on February 13, 2026.\nI stopped and restarted several times. The questions changed with me. What began as a way to learn more Java became a record of how I investigate runtime behavior.\nAt the beginning, that mostly meant learning more APIs, more features, more idioms, and more little utilities I could reach for later. Some of the early posts are exactly that. They are small, direct, and useful in a narrow way: retrying a method with TimerTask, emulating a Pair, converting an Iterator into a Spliterator, working through individual language features one by one.\nI still value those posts. They show me learning in public in the most literal sense.\nBut when I look across the posts now, that is not the real story it tells. The bigger change is that the challenge slowly stopped being about collecting Java knowledge and started becoming a way to investigate behavior. I became less interested in naming abstractions and more interested in asking what they were hiding. Memory leaks. Heap dumps. JMX. Off-heap memory. Event loops. Virtual threads. Work distribution. Startup time. The center of gravity moved from \u0026ldquo;what does this API do?\u0026rdquo; to \u0026ldquo;why is this system behaving like that?\u0026rdquo;\nThe writing changed with that shift. Early on, I was still trying to sound like I understood the topic before I really did. Somewhere along the way, I stopped trying to sound authoritative and got more comfortable writing from confusion. That made the posts less polished in one sense, but more honest in a better one. The later posts that stayed with me usually begin with a wrong assumption, a gap in my mental model, or a question I could not shake. That is much closer to how I actually learn.\nIf I had to reduce the whole challenge to one sentence, it would be this: it started as learning Java and gradually became learning how systems behave.\nFrom Explaining Topics to Investigating Behavior One of the clearest differences between the earlier and later parts of these posts is not the topic list. It is the shape of the questions.\nThe earlier posts often behave like explainers. I pick a concept, define it, show a code snippet, and move on. That mode was useful because I was building vocabulary and touching a lot of surface area. It gave me repetition. It forced me to keep shipping. It also sometimes let me stay a little too comfortable. I could finish a post having explained a tool without really testing the edges of my own understanding.\nThe startup-time rabbit hole in Day 94 starts from a concrete problem and then keeps asking where startup time actually goes. It is less \u0026ldquo;here are some optimizations\u0026rdquo; and more \u0026ldquo;I had been thinking about startup time the wrong way.\u0026rdquo; That difference matters.\nBy Day 98, the frame is even clearer. The post is not built around \u0026ldquo;here is virtual threads.\u0026rdquo; It is built around a mistaken model: I thought virtual threads were just green threads, and that model stopped explaining what I was seeing. The writing gets better there because the question gets better.\nThen Day 99 does the same thing again. If virtual threads make blocking I/O scale, why do event loops still exist? That is a much more alive question than a generic comparison between two frameworks. It starts from a misconception, follows it down into selectors and multiplexing and then I understood that its a trade-off\nEven some of the posts I would now write differently were moving in that direction. The one about startup time, the one about printing and logging cost, the later concurrency series, the memory-mapping deep dive, all of them have the same underlying motion: they begin with something that I felt obvious from the surface and then stop being obvious as
4soon as I looked under it.\nMechanisms Started Mattering More Than Frameworks The other change is even simpler to name because I can feel it in the topics themselves: I became less interested in frameworks and more interested in systems and how are they working to make the things tha I want.\nThe memory leak series around Day 66, the heap dump post, the JMX posts, and the OutOfMemory alert post all pulled in the same direction. They made memory stop feeling like a mysterious background concern and start feeling like something I could inspect. Retained references, heap state, threshold notifications, dump files, leak patterns, object lifetime: those are runtime-behavior topics, not framework topics.\nThen the later memory-heavy posts pushed that further. In Day 77, I was writing to allocated memory through Unsafe. The next step was the safer FFM direction. By Day 91, I was looking at memory mapping not as a convenient API trick but as a question about where data actually lives, when it gets loaded, and how much of the work belongs to the heap versus the operating system.\nEven the JMH posts and the later performance posts helped here. They moved performance a little farther away from opinion and a little closer to measurement. The printing post is not really about println() versus file writing. It is about where overhead comes from and what kind of cost a friendly abstraction is hiding.That does not mean frameworks stopped mattering. They just stopped feeling sufficient as explanations.\nDay 95 and the two posts that follow it are broad on the surface. They cover concurrency tools. But even there, the interesting part is not \u0026ldquo;here are twelve APIs.\u0026rdquo; The interesting part is the repeated warning that concurrency is not automatically a win, that the wrong synchronizer creates the wrong shape of failure, and that production systems need coordination as much as they need execution.\nThat theme becomes much more concrete in those later virtual-thread and event-loop posts. Once I started looking at virtual threads as continuations, heap-allocated stack chunks, mount and unmount behavior, pinning, carrier threads, selectors, and event loops, the old question \u0026ldquo;which framework should I use?\u0026rdquo;. The new question I started to ask was what is happening inside and how can it help.\nThe spliterator material that I thought I would write for 100th day makes more sense to me as one late example of that shift than as the final centerpiece. The real lesson is not that I wrote a custom Spliterator. It is that .parallel() hid a work-distribution policy I had not thought about carefully enough. Once I noticed the growing-batch behavior, the problem stopped being \u0026ldquo;why is Java Streams slow?\u0026rdquo; and became \u0026ldquo;how is work being divided, why are cores going idle, and what happens when the default coordination strategy does not fit the workload?\u0026rdquo;\nAt the code level, the turning point was almost embarrassingly small:\n1 2 3 4 5 6 7 8 9 10 @Override public Spliterator\u0026lt;T\u0026gt; trySplit() { final HoldingConsumer\u0026lt;T\u0026gt; holder = new HoldingConsumer\u0026lt;\u0026gt;(); if (!tryAdvance(holder)) return null; final Object[] batch = new Object[batchSize]; int j = 0; do { batch[j] = holder.value; } while (++j \u0026lt; batchSize \u0026amp;\u0026amp; tryAdvance(holder)); return Spliterators.spliterator(batch, 0, j, characteristics()); } The code itself is not the point. The point is that the real problem was sitting one layer below the API I thought I was using. That is basically the whole point. I kept starting from an abstraction I already knew how to use. Then I ran into behavior that abstraction did not explain. Then I followed the behavior down a level.\nWhat the Writing Habit Changed This #100DaysOfJava challange helped me to better think by writing these online. Publishing regularly forced vague curiosity to become a good question. It is easy to carry around a fuzzy feeling that something is intriguing. It is harder to turn that into a post that begins somewhere concrete, moves through evidence, and ends with a claim that is modest enough to defend.\nI thought virtual threads were just green threads. I thought virtual threads might make event loops obsolete. I saw memory mapping as a magic trick and then tried to understand the path from kernel to code. I treated startup time like a vague Java problem and then tried to locate the actual bottlenecks.\nThat pattern is closer to how I really learn than the older style where I tried to sound finished too early. Writing from confusion did not make me less rigorous. It made the missing rigor easier to locate. If I can name the broken model, I know what I am testing.\nThat is probably the main writing lesson I want to keep. Not \u0026ldquo;publish every day.\u0026rdquo; Not \u0026ldquo;build in public.\u0026rdquo; Just this: when a question is still blurry, stay with it until its a little bit clearer.\nWhat Changed In How I Think About Software Engineering I did learn a littl bit more Java from this challenge.I learned APIs I never had to work with directly in my day job, internals which I didnt new how it worked or even existed, language features I had only used casually, and tools I probably would not have opened if I havent written these series.\nThis is not mastery. If anything, it has made me more aware of how much I still do not understand. But it is a better kind of ignorance. It gives me better questions.\nThat is also why Chaos;Code;Clarity my new newsletter where I will explore the chaotically beautiful world of Softw
4are Engineering and AI. This feels like a natural next step to me. Not because I am done with Java, and not because this challenge ended in some clean graduation. It feels natural because these posts was already moving there. The part I want to carry forward is the habit underneath it: think, probe, measure, question the default story, and keep following the system until the behavior becomes a little less mysterious.\nI started this project to learn more Java. I am closing the numbered series with a better method: begin with a concrete question, inspect the system, measure what changes, and state what the evidence cannot prove.\nLimitations The archive spans several years, JDK versions, and levels of rigor. Early posts are short learning notes, while later posts include larger experiments. Treat each article according to the versions, commands, and evidence it records. The series is a learning history, not one controlled study.\n","author":{"@type":"Person","jobTitle":"Software Engineer","knowsAbout":["Java","Spring Boot","software engineering","artificial intelligence","technical writing"],"name":"Mohibul Hassan Chowdhury","sameAs":["https://twitter.com/dhrubo555","https://github.com/dhrubo55","https://www.linkedin.com/in/mohibulhassan/"],"url":"https://mohibulsblog.netlify.app/"},"dateModified":"2026-09-19T22:24:05+06:00","datePublished":"2026-03-30T00:00:00Z","description":"An honest retrospective on a challenge that did not happen in a clean streak, and on how learning Java slowly turned into learning how systems behave.","headline":"What 100DaysOfJava changed in how I investigate systems","inLanguage":"en","keywords":["Java","100DaysOfJava"],"mainEntityOfPage":{"@id":"https://mohibulsblog.netlify.app/posts/posts/java/100daysofjava/day100-capstone.md/","@type":"WebPage"},"name":"What 100DaysOfJava changed in how I investigate systems","publisher":{"@type":"Person","jobTitle":"Software Engineer","knowsAbout":["Java","Spring Boot","software engineering","artificial intelligence","technical writing"],"name":"Mohibul Hassan Chowdhury","sameAs":["https://twitter.com/dhrubo555","https://github.com/dhrubo55","https://www.linkedin.com/in/mohibulhassan/"],"url":"https://mohibulsblog.netlify.app/"},"url":"https://mohibulsblog.netlify.app/posts/posts/java/100daysofjava/day100-capstone.md/"}</script>
4</head><body id=top><header class=header><nav class=header-nav><div class=logo><a href=https://mohibulsblog.netlify.app/ accesskey=h title="Mohibul Hassan (Alt + H)">Mohibul Hassan</a><div class=logo-switches><button id=theme-toggle class=theme-toggle accesskey=t title="(Alt + T)" aria-label="Toggle theme"> 5<svg class="moon" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z"/></svg> 6<svg class="sun" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></svg></button></div></div><ul id=menu class=menu><li><a href=https://mohibulsblog.netlify.app/about/ title=About><span>About</span></a></li><li><a href=https://mohibulsblog.netlify.app/blog/ title=Blog><span>Blog</span></a></li><li><a href=https://mohibulsblog.netlify.app/java/100daysofjava/graph/ title=100DaysOfJava><span>100DaysOfJava</span></a></li><li><a href=https://mohibulsblog.netlify.app/resume.pdf title=Resume><span>Resume</span></a></li><li><a href=https://mohibulsblog.netlify.app/support/ title=Support><span>Support</span></a></li><li><a href=https://mohibulsblog.netlify.app/index.xml title=RSS><span>RSS</span></a></li></ul></nav></header><main class=main><article class=post-single><header class=post-header><h1 class="post-title entry-hint-parent">What 100DaysOfJava changed in how I investigate systems</h1><div class=post-description>An honest retrospective on a challenge that did not happen in a clean streak, and on how learning Java slowly turned into learning how systems behave.</div><div class=post-meta><span title='2026-03-30 00:00:00 +0000 UTC'>March 30, 2026</span> · <span>9 min</span> · <span>Mohibul Hassan Chowdhury</span></div></header><div class="post-content md-content"><p>This was not a 100-day streak. The dates make that clear. Day 26 was published on September 30, 2021. Day 66 arrived on January 20, 2023. Day 77 followed on March 14, 2024, Day 91 on August 15, 2025, and Day 99 on February 13, 2026.</p><p>I stopped and restarted several times. The questions changed with me. What began as a way to learn more Java became a record of how I investigate runtime behavior.</p><p>At the beginning, that mostly meant learning more APIs, more features, more idioms, and more little utilities I could reach for later. Some of the early posts are exactly that. They are small, direct, and useful in a narrow way: retrying a method with <code>TimerTask</code>, emulating a Pair, converting an <code>Iterator</code> into a <code>Spliterator</code>, working through individual language features one by one.</p><p>I still value those posts. They show me learning in public in the most literal sense.</p><p>But when I look across the posts now, that is not the real story it tells. The bigger change is that the challenge slowly stopped being about collecting Java knowledge and started becoming a way to investigate behavior. I became less interested in naming abstractions and more interested in asking what they were hiding. Memory leaks. Heap dumps. JMX. Off-heap memory. Event loops. Virtual threads. Work distribution. Startup time. The center of gravity moved from “what does this API do?” to “why is this system behaving like that?”</p><p>The writing changed with that shift. Early on, I was still trying to sound like I understood the topic before I really did. Somewhere along the way, I stopped trying to sound authoritative and got more comfortable writing from confusion. That made the posts less polished in one sense, but more honest in a better one. The later posts that stayed with me usually begin with a wrong assumption, a gap in my mental model, or a question I could not shake. That is much closer to how I actually learn.</p><p>If I had to reduce the whole challenge to one sentence, it would be this: <code>it started as learning Java and gradually became learning how systems behave.</code></p><h2 id=from-explaining-topics-to-investigating-behavior>From Explaining Topics to Investigating Behavior<a hidden class=anchor aria-hidden=true href=#from-explaining-topics-to-investigating-behavior>#</a></h2><p>One of the clearest differences between the earlier and later parts of these posts is not the topic list. It is the shape of the questions.</p><p>The earlier posts often behave like explainers. I pick a concept, define it, show a code snippet, and move on. That mode was useful because I was building vocabulary and touching a lot of surface area. It gave me repetition. It forced me to keep shipping. It also sometimes let me stay a little too comfortable. I could finish a post having explained a tool without really testing the edges of my own understanding.</p><p>The startup-time rabbit hole in <a href=/posts/posts/java/100DaysOfJava/day94>Day 94</a> starts from a concrete problem and then keeps asking where startup time actually goe
6s. It is less “here are some optimizations” and more “I had been thinking about startup time the wrong way.” That difference matters.</p><p>By <a href=/posts/posts/java/100DaysOfJava/day98>Day 98</a>, the frame is even clearer. The post is not built around “here is virtual threads.” It is built around a mistaken model: I thought virtual threads were just green threads, and that model stopped explaining what I was seeing. The writing gets better there because the question gets better.</p><p>Then <a href=/posts/posts/java/100DaysOfJava/day99>Day 99</a> does the same thing again. If virtual threads make blocking I/O scale, why do event loops still exist? That is a much more alive question than a generic comparison between two frameworks. It starts from a misconception, follows it down into selectors and multiplexing and then I understood that its a trade-off</p><p>Even some of the posts I would now write differently were moving in that direction. The one about startup time, the one about printing and logging cost, the later concurrency series, the memory-mapping deep dive, all of them have the same underlying motion: they begin with something that I felt obvious from the surface and then stop being obvious as soon as I looked under it.</p><h2 id=mechanisms-started-mattering-more-than-frameworks>Mechanisms Started Mattering More Than Frameworks<a hidden class=anchor aria-hidden=true href=#mechanisms-started-mattering-more-than-frameworks>#</a></h2><p>The other change is even simpler to name because I can feel it in the topics themselves: I became less interested in frameworks and more interested in systems and how are they working to make the things tha I want.</p><p>The memory leak series around <a href=/posts/java/100daysofjava/day66/>Day 66</a>, the heap dump post, the JMX posts, and the OutOfMemory alert post all pulled in the same direction. They made memory stop feeling like a mysterious background concern and start feeling like something I could inspect. Retained references, heap state, threshold notifications, dump files, leak patterns, object lifetime: those are runtime-behavior topics, not framework topics.</p><p>Then the later memory-heavy posts pushed that further. In <a href=/posts/posts/java/100DaysOfJava/day77>Day 77</a>, I was writing to allocated memory through <code>Unsafe</code>. The next step was the safer FFM direction. By <a href=/posts/posts/java/100DaysOfJava/day91>Day 91</a>, I was looking at memory mapping not as a convenient API trick but as a question about where data actually lives, when it gets loaded, and how much of the work belongs to the heap versus the operating system.</p><p>Even the JMH posts and the later performance posts helped here. They moved performance a little farther away from opinion and a little closer to measurement. The printing post is not really about <code>println()</code> versus file writing. It is about where overhead comes from and what kind of cost a friendly abstraction is hiding.That does not mean frameworks stopped mattering. They just stopped feeling sufficient as explanations.</p><p><a href=/posts/posts/java/100daysofjava/day95/>Day 95</a> and the two posts that follow it are broad on the surface. They cover concurrency tools. But even there, the interesting part is not “here are twelve APIs.” The interesting part is the repeated warning that concurrency is not automatically a win, that the wrong synchronizer creates the wrong shape of failure, and that production systems need coordination as much as they need execution.</p><p>That theme becomes much more concrete in those later virtual-thread and event-loop posts. Once I started looking at virtual threads as continuations, heap-allocated stack chunks, mount and unmount behavior, pinning, carrier threads, selectors, and event loops, the old question “which framework should I use?”. The new question I started to ask was what is happening inside and how can it help.</p><p>The spliterator material that I thought I would write for <a href=/posts/posts/java/100daysofjava/day100-spliterator/>100th day</a> makes more sense to me as one late example of that shift than as the final centerpiece. The real lesson is not that I wrote a custom <code>Spliterator</code>. It is that <code>.parallel()</code> hid a work-distribution policy I had not thought about carefully enough. Once I noticed the growing-batch behavior, the problem stopped being “why is Java Streams slow?” and became “how is work being divided, why are cores going idle, and what happens when the default coordination strategy does not fit the workload?”</p><p>At the code level, the turning point was almost embarrassingly small:</p><div class=highlight><div style=color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><table style=border-spacing:0;padding:0;margin:0;border:0><tr><td style=vertical-align:top;padding:0;margin:0;border:0><pre tabindex=0 style=color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:.4em;padding:0 .4em;color:#686868"> 1 7</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:.4em;padding:0 .4em;color:#686868"> 2 8</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:.4em;padding:0 .4em;color:#686868"> 3 9</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:.4em;padding:0 .4em;color:#686868"> 4 10</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:.4em;padding:0 .4em;color:#686868"> 5 11</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:.4em;padding:0 .4em;color:#686868"> 6 12</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:.4em;padding:0 .4em;color:#686868"> 7 13</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:.4em;padding:0 .4em;color:#686868"> 8 14</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:.4em;padding:0 .4em;color:#686868"> 9 15</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:.4em;padding:0 .4em;color:#686868">10 16</span></code></pre></td><td style=vertical-align:top;padding:0;margin:0;border:0;width:100%><pre tabindex=0 style=color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none><code class=language-java data-lang=java><span style=display:flex><span><span style=color:orange>
16@Override</span><span style=color:#666> 17</span></span></span><span style=display:flex><span><span style=color:#6ab825;font-weight:700>public</span><span style=color:#666> </span>Spliterator<T><span style=color:#666> </span><span style=color:#447fcf>trySplit</span>()<span style=color:#666> </span>{<span style=color:#666> 18</span></span></span><span style=display:flex><span><span style=color:#666> </span><span style=color:#6ab825;font-weight:700>final</span><span style=color:#666> </span>HoldingConsumer<T><span style=color:#666> </span>holder<span style=color:#666> </span>=<span style=color:#666> </span><span style=color:#6ab825;font-weight:700>new</span><span style=color:#666> </span>HoldingConsumer<>();<span style=color:#666> 19</span></span></span><span style=display:flex><span><span style=color:#666> </span><span style=color:#6ab825;font-weight:700>if</span><span style=color:#666> </span>(!tryAdvance(holder))<span style=color:#666> </span><span style=color:#6ab825;font-weight:700>return</span><span style=color:#666> </span><span style=color:#6ab825;font-weight:700>null</span>;<span style=color:#666> 20</span></span></span><span style=display:flex><span><span style=color:#666> </span><span style=color:#6ab825;font-weight:700>final</span><span style=color:#666> </span>Object[]<span style=color:#666> </span>batch<span style=color:#666> </span>=<span style=color:#666> </span><span style=color:#6ab825;font-weight:700>new</span><span style=color:#666> </span>Object[batchSize];<span style=color:#666> 21</span></span></span><span style=display:flex><span><span style=color:#666> </span><span style=color:#6ab825;font-weight:700>int</span><span style=color:#666> </span>j<span style=color:#666> </span>=<span style=color:#666> </span>0;<span style=color:#666> 22</span></span></span><span style=display:flex><span><span style=color:#666> </span><span style=color:#6ab825;font-weight:700>do</span><span style=color:#666> </span>{<span style=color:#666> </span>batch[j]<span style=color:#666> </span>=<span style=color:#666> </span>holder.<span style=color:#bbb>value</span>;<span style=color:#666> </span>}<span style=color:#666> 23</span></span></span><span style=display:flex><span><span style=color:#666> </span><span style=color:#6ab825;font-weight:700>while</span><span style=color:#666> </span>(++j<span style=color:#666> </span><<span style=color:#666> </span>batchSize<span style=color:#666> </span>&&<span style=color:#666> </span>tryAdvance(holder));<span style=color:#666> 24</span></span></span><span style=display:flex><span><span style=color:#666> </span><span style=color:#6ab825;font-weight:700>return</span><span style=color:#666> </span>Spliterators.<span style=color:#bbb>spliterator</span>(batch,<span style=color:#666> </span>0,<span style=color:#666> </span>j,<span style=color:#666> </span>characteristics());<span style=color:#666> 25</span></span></span><span style=display:flex><span>}<span style=color:#666> 26</span></span></span></code></pre></td></tr></table></div></div><p>The code itself is not the point. The point is that the real problem was sitting one layer below the API I thought I was using. That is basically the whole point. 27I kept starting from an abstraction I already knew how to use. Then I ran into behavior that abstraction did not explain. Then I followed the behavior down a level.</p><h2 id=what-the-writing-habit-changed>What the Writing Habit Changed<a hidden class=anchor aria-hidden=true href=#what-the-writing-habit-changed>#</a></h2><p>This #100DaysOfJava challange helped me to better think by writing these online. Publishing regularly forced vague curiosity to become a good question. It is easy to carry around a fuzzy feeling that something is intriguing. It is harder to turn that into a post that begins somewhere concrete, moves through evidence, and ends with a claim that is modest enough to defend.</p><p>I thought virtual threads were just green threads. I thought virtual threads might make event loops obsolete. I saw memory mapping as a magic trick and then tried to understand the path from kernel to code. I treated startup time like a vague Java problem and then tried to locate the actual bottlenecks.</p><p>That pattern is closer to how I really learn than the older style where I tried to sound finished too early. Writing from confusion did not make me less rigorous. It made the missing rigor easier to locate. If I can name the broken model, I know what I am testing.</p><p>That is probably the main writing lesson I want to keep. Not “publish every day.” Not “build in public.” Just this: <code>when a question is still blurry, stay with it until its a little bit clearer.</code></p><h2 id=what-changed-in-how-i-think-about-software-engineering>What Changed In How I Think About Software Engineering<a hidden class=anchor aria-hidden=true href=#what-changed-in-how-i-think-about-software-engineering>#</a></h2><p>I did learn a littl bit more Java from this challenge.I learned APIs I never had to work with directly in my day job, internals which I didnt new how it worked or even existed, language features I had only used casually, and tools I probably would not have opened if I havent written these series.</p><p>This is not mastery. If anything, it has made me more aware of how much I still do not understand. But it is a better kind of ignorance. It gives me better questions.</p><p>That is also why <a href=https://chaoscodeclarity.substack.com/>Chaos;Code;Clarity</a> my new newsletter where I will explore the chaotically beautiful world of Softw
27are Engineering and AI. This feels like a natural next step to me. Not because I am done with Java, and not because this challenge ended in some clean graduation. It feels natural because these posts was already moving there. The part I want to carry forward is the habit underneath it: <code>think, probe, measure, question the default story</code>, and <code>keep following the system until the behavior becomes a little less mysterious</code>.</p><p>I started this project to learn more Java. I am closing the numbered series with a better method: begin with a concrete question, inspect the system, measure what changes, and state what the evidence cannot prove.</p><h2 id=limitations>Limitations<a hidden class=anchor aria-hidden=true href=#limitations>#</a></h2><p>The archive spans several years, JDK versions, and levels of rigor. Early posts are short learning notes, while later posts include larger experiments. Treat each article according to the versions, commands, and evidence it records. The series is a learning history, not one controlled study.</p></div><div class=form></div><footer class=post-footer><ul class=post-tags></ul><nav class=paginav><a class=next href=https://mohibulsblog.netlify.app/posts/posts/java/100daysofjava/day99/><span class=title>Next »</span> 28<span>Virtual threads and event loops solve different problems</span></a></nav><ul class=share-buttons><li><a target=_blank rel="noopener noreferrer" aria-label="share What 100DaysOfJava changed in how I investigate systems on x" href="https://x.com/intent/tweet/?text=What%20100DaysOfJava%20changed%20in%20how%20I%20investigate%20systems&url=https%3a%2f%2fmohibulsblog.netlify.app%2fposts%2fposts%2fjava%2f100daysofjava%2fday100-capstone.md%2f&hashtags="><svg viewBox="0 0 512 512" height="30" width="30" fill="currentColor"><path d="M512 62.554V449.446C512 483.97 483.97 512 449.446 512H62.554C28.03 512 0 483.97.0 449.446V62.554C0 28.03 28.029.0 62.554.0H449.446C483.971.0 512 28.03 512 62.554zM269.951 190.75 182.567 75.216H56L207.216 272.95 63.9 436.783h61.366L235.9 310.383l96.667 126.4H456L298.367 228.367l134-153.151H371.033zM127.633 110h36.468l219.38 290.065H349.5z"/></svg></a></li><li><a target=_blank rel="noopener noreferrer" aria-label="share What 100DaysOfJava changed in how I investigate systems on linkedin" href="https://www.linkedin.com/shareArticle?mini=true&url=https%3a%2f%2fmohibulsblog.netlify.app%2fposts%2fposts%2fjava%2f100daysofjava%2fday100-capstone.md%2f&title=What%20100DaysOfJava%20changed%20in%20how%20I%20investigate%20systems&summary=What%20100DaysOfJava%20changed%20in%20how%20I%20investigate%20systems&source=https%3a%2f%2fmohibulsblog.netlify.app%2fposts%2fposts%2fjava%2f100daysofjava%2fday100-capstone.md%2f"><svg viewBox="0 0 512 512" height="30" width="30" fill="currentColor"><path d="M449.446.0C483.971.0 512 28.03 512 62.554v386.892C512 483.97 483.97 512 449.446 512H62.554c-34.524.0-62.554-28.03-62.554-62.554V62.554c0-34.524 28.029-62.554 62.554-62.554h386.892zM160.461 423.278V197.561h-75.04v225.717h75.04zm270.539.0V293.839c0-69.333-37.018-101.586-86.381-101.586-39.804.0-57.634 21.891-67.617 37.266v-31.958h-75.021c.995 21.181.0 225.717.0 225.717h75.02V297.222c0-6.748.486-13.492 2.474-18.315 5.414-13.475 17.767-27.434 38.494-27.434 27.135.0 38.007 20.707 38.007 51.037v120.768H431zM123.448 88.722C97.774 88.722 81 105.601 81 127.724c0 21.658 16.264 39.002 41.455 39.002h.484c26.165.0 42.452-17.344 42.452-39.002-.485-22.092-16.241-38.954-41.943-39.002z"/></svg></a></li><li><a target=_blank rel="noopener noreferrer" aria-label="share What 100DaysOfJava changed in how I investigate systems on reddit" href="https://reddit.com/submit?url=https%3a%2f%2fmohibulsblog.netlify.app%2fposts%2fposts%2fjava%2f100daysofjava%2fday100-capstone.md%2f&title=What%20100DaysOfJava%20changed%20in%20how%20I%20investigate%20systems"><svg viewBox="0 0 512 512" height="30" width="30" fill="currentColor"><path d="M449.446.0C483.971.0 512 28.03 512 62.554v386.892C512 483.97 483.97 512 449.446 512H62.554c-34.524.0-62.554-28.03-62.554-62.554V62.554c0-34.524 28.029-62.554 62.554-62.554h386.892zM446 265.638c0-22.964-18.616-41.58-41.58-41.58-11.211.0-21.361 4.457-28.841 11.666-28.424-20.508-67.586-33.757-111.204-35.278l18.941-89.121 61.884 13.157c.756 15.734 13.642 28.29 29.56 28.29 16.407.0 29.706-13.299 29.706-29.701.0-16.403-13.299-29.702-29.706-29.702-11.
28666.0-21.657 6.792-26.515 16.578l-69.105-14.69c-1.922-.418-3.939-.042-5.585 1.036-1.658 1.073-2.811 2.761-3.224 4.686l-21.152 99.438c-44.258 1.228-84.046 14.494-112.837 35.232-7.468-7.164-17.589-11.591-28.757-11.591-22.965.0-41.585 18.616-41.585 41.58.0 16.896 10.095 31.41 24.568 37.918-.639 4.135-.99 8.328-.99 12.576.0 63.977 74.469 115.836 166.33 115.836s166.334-51.859 166.334-115.836c0-4.218-.347-8.387-.977-12.493 14.564-6.47 24.735-21.034 24.735-38.001zM326.526 373.831c-20.27 20.241-59.115 21.816-70.534 21.816-11.428.0-50.277-1.575-70.522-21.82-3.007-3.008-3.007-7.882.0-10.889 3.003-2.999 7.882-3.003 10.885.0 12.777 12.781 40.11 17.317 59.637 17.317 19.522.0 46.86-4.536 59.657-17.321 3.016-2.999 7.886-2.995 10.885.008 3.008 3.011 3.003 7.882-.008 10.889zm-5.23-48.781c-16.373.0-29.701-13.324-29.701-29.698.0-16.381 13.328-29.714 29.701-29.714 16.378.0 29.706 13.333 29.706 29.714.0 16.374-13.328 29.698-29.706 29.698zM160.91 295.348c0-16.381 13.328-29.71 29.714-29.71 16.369.0 29.689 13.329 29.689 29.71.0 16.373-13.32 29.693-29.689 29.693-16.386.0-29.714-13.32-29.714-29.693z"/></svg></a></li><li><a target=_blank rel="noopener noreferrer" aria-label="share What 100DaysOfJava changed in how I investigate systems on facebook" href="https://facebook.com/sharer/sharer.php?u=https%3a%2f%2fmohibulsblog.netlify.app%2fposts%2fposts%2fjava%2f100daysofjava%2fday100-capstone.md%2f"><svg viewBox="0 0 512 512" height="30" width="30" fill="currentColor"><path d="M449.446.0C483.971.0 512 28.03 512 62.554v386.892C512 483.97 483.97 512 449.446 512H342.978V319.085h66.6l12.672-82.621h-79.272v-53.617c0-22.603 11.073-44.636 46.58-44.636H425.6v-70.34s-32.71-5.582-63.982-5.582c-65.288.0-107.96 39.569-107.96 111.204v62.971h-72.573v82.621h72.573V512h-191.104c-34.524.0-62.554-28.03-62.554-62.554V62.554c0-34.524 28.029-62.554 62.554-62.554h386.892z"/></svg></a></li><li><a target=_blank rel="noopener noreferrer" aria-label="share What 100DaysOfJava changed in how I investigate systems on whatsapp" href="https://api.whatsapp.com/send?text=What%20100DaysOfJava%20changed%20in%20how%20I%20investigate%20systems%20-%20https%3a%2f%2fmohibulsblog.netlify.app%2fposts%2fposts%2fjava%2f100daysofjava%2fday100-capstone.md%2f"><svg viewBox="0 0 512 512" height="30" width="30" fill="currentColor"><path d="M449.446.0C483.971.0 512 28.03 512 62.554v386.892C512 483.97 483.97 512 449.446 512H62.554c-34.524.0-62.554-28.03-62.554-62.554V62.554c0-34.524 28.029-62.554 62.554-62.554h386.892zm-58.673 127.703c-33.842-33.881-78.847-52.548-126.798-52.568-98.799.0-179.21 80.405-179.249 179.234-.013 31.593 8.241 62.428 23.927 89.612l-25.429 92.884 95.021-24.925c26.181 14.28 55.659 21.807 85.658 21.816h.074c98.789.0 179.206-80.413 179.247-179.243.018-47.895-18.61-92.93-52.451-126.81zM263.976 403.485h-.06c-26.734-.01-52.954-7.193-75.828-20.767l-5.441-3.229-56.386 14.792 15.05-54.977-3.542-5.637c-14.913-23.72-22.791-51.136-22.779-79.287.033-82.142 66.867-148.971 149.046-148.971 39.793.014 77.199 15.531 105.329 43.692 28.128 28.16 43.609 65.592 43.594 105.4-.034 82.149-66.866 148.983-148.983 148.984zm81.721-111.581c-4.479-2.242-26.499-13.075-30.604-14.571-4.105-1.495-7.091-2.241-10.077 2.241-2.986 4.483-11.569 14.572-14.182 17.562-2.612 2.988-5.225 3.364-9.703 1.12-4.479-2.241-18.91-6.97-36.017-22.23C231.8 264.15 222.81 249.484 220.198 245s-.279-6.908 1.963-9.14c2.016-2.007 4.48-5.232 6.719-7.847 2.24-2.615 2.986-4.484 4.479-7.472 1.493-2.99.747-5.604-.374-7.846-1.119-2.241-10.077-24.288-13.809-33.256-3.635-8.733-7.327-7.55-10.077-7.688-2.609-.13-5.598-.158-8.583-.158-2.986.0-7.839 1.121-11.944 5.604-4.105 4.484-15.675 15.32-15.675 37.364.0 22.046 16.048 43.342 18.287 46.332 2.24 2.99 31.582 48.227 76.511 67.627 10.685 4.615 19.028 7.371 25.533 9.434 10.728 3.41 20.492 2.929 28.209 1.775 8.605-1.285 26.499-10.833 30.231-21.295 3.732-10.464 3.732-19.431 2.612-21.298-1.119-1.869-4.105-2.99-8.583-5.232z"/></svg></a></li><li><a target=_blank rel="noopener noreferrer" aria-label="share What 100DaysOfJava changed in how I investigate systems on telegram" href="https://telegram.me/share/url?text=What%20100DaysOfJava%20changed%20in%20how%20I%20investigate%20systems&url=https%3a%2f%2fmohibulsblog.netlify.app%2fposts%2fposts%2fjava%2f100daysofjava%2fday100-capstone.md%2f"><svg viewBox="2 2 28 28" height="30" width="30" fill="currentColor"><path d="M26.49 29.86H5.5a3.37 3.37.0 01-2.47-1 3.35 3.35.0 01-1-2.47V5.48A3.36 3.36.0 013 3 3.37 3.37.0 015.5 2h21A3.38 3.38.0 0129 3a3.36 3.36.0 011 2.46V26.37a3.35 3.35.0 01-1 2.47 3.38 3.38.0 01-2.51 1.02zm-5.38-6.71a.79.79.0 00.85-.66L24.73 9.24a.55.55.0 00-.18-.46.62.62.0 00-.41-.17q-.08.0-16.53 6.11a.59.59.0 00-.41.59.57.57.0 00.43.52l4 1.24 1.61 4.83a.62.62.0 00.63.43.56.56.0 00.4-.17L16.54 20l4.09 3A.9.9.0 0021.11 23.15zM13.8 20.71l-1.21-4q8.72-5.55 8.78-5.55c.15.0.23.0.23.16a.18.18.0 010 .06s-2.51 2.3-7.52 6.8z"/></svg></a></li><li><a target=_blank rel="noopener noreferrer" aria-label="share What 100DaysOfJava changed in how I investigate systems on ycombinator" href="https://news.ycombinator.com/submitlink?t=What%20100DaysOfJava%20changed%20in%20how%20I%20investigate%20systems&u=https%3a%2f%2fmohibulsblog.netlify.app%2fposts%2fposts%2fjava%2f100daysofjava%2fday100-capstone.md%2f"><svg width="30" height="30" viewBox="0 0 512 512" fill="currentColor"><path d="M449.446.0C483.971.0 512 28.03 512 62.554V449.446C512 483.97 483.97 512 449.446 512H62.554C28.03 512 0 483.97.0 449.446V62.5
2854C0 28.03 28.029.0 62.554.0H449.446zM183.8767 87.9921h-62.034L230.6673 292.4508V424.0079h50.6655V292.4508L390.1575 87.9921H328.1233L256 238.2489z"/></svg></a></li></ul></footer></article></main><footer class=footer><span>© 2026 Mohibul Hassan Chowdhury. All rights reserved.</span> · 29<a href=/terms-of-service-agreement/>Terms of Service</a> · <a href=/privacy-policy/>Privacy Policy</a> · 30<span>Powered by 31<a href="https://gohugo.io/?utm_source=papermod" rel=noopener target=_blank>Hugo</a> & 32<a href=https://github.com/adityatelange/hugo-PaperMod/ rel=noopener target=_blank>PaperMod</a></span></footer><a href=#top id=top-link class="top-link hidden" aria-label="go to top" title="Go to Top (Alt + G)" accesskey=g><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevrons-up"><polyline points="17 11 12 6 7 11"/><polyline points="17 18 12 13 7 18"/></svg> 33</a>
33<script>!function(e,t,n,s,o,i){e.twq||(s=e.twq=function(){s.exe?s.exe.apply(s,arguments):s.queue.push(arguments)},s.version="1.1",s.queue=[],o=t.createElement(n),o.async=!0,o.src="//static.ads-twitter.com/uwt.js",i=t.getElementsByTagName(n)[0],i.parentNode.insertBefore(o,i))}(window,document,"script"),twq("init","o5htq"),twq("track","PageView")</script>
33<script>let menu=document.getElementById("menu");if(menu){const e=localStorage.getItem("menu-scroll-position");e&&(menu.scrollLeft=parseInt(e,10)),menu.onscroll=function(){localStorage.setItem("menu-scroll-position",menu.scrollLeft)}}document.querySelectorAll('a[href^="#"]').forEach(e=>{e.addEventListener("click",function(e){e.preventDefault();var t=this.getAttribute("href").substr(1);window.matchMedia("(prefers-reduced-motion: reduce)").matches?document.querySelector(`[id='${decodeURIComponent(t)}']`).scrollIntoView():document.querySelector(`[id='${decodeURIComponent(t)}']`).scrollIntoView({behavior:"smooth"}),t==="top"?history.replaceState(null,null," "):history.pushState(null,null,`#${t}`)})})</script>
33<script>var toplink=document.getElementById("top-link");window.onscroll=function(){const e=window.innerHeight;document.body.scrollTop>e||document.documentElement.scrollTop>e?toplink.classList.remove("hidden"):toplink.classList.add("hidden")}</script>
33<script>document.getElementById("theme-toggle").addEventListener("click",()=>{const e=document.querySelector("html");e.dataset.theme==="dark"?(e.dataset.theme="light",localStorage.setItem("pref-theme","light")):(e.dataset.theme="dark",localStorage.setItem("pref-theme","dark"))})</script>
33<script>document.querySelectorAll("pre > code").forEach(e=>{const n=e.parentNode.parentNode,t=document.createElement("button");t.classList.add("copy-code"),t.innerHTML="copy";function s(){t.innerHTML="copied!",setTimeout(()=>{t.innerHTML="copy"},2e3)}t.addEventListener("click",t=>{if("clipboard"in navigator){navigator.clipboard.writeText(e.textContent),s();return}const n=document.createRange();n.selectNodeContents(e);const o=window.getSelection();o.removeAllRanges(),o.addRange(n);try{document.execCommand("copy"),s()}catch{}o.removeRange(n)}),n.classList.contains("highlight")?n.appendChild(t):n.parentNode.firstChild==n||(e.parentNode.parentNode.parentNode.parentNode.parentNode.nodeName=="TABLE"?e.parentNode.parentNode.parentNode.parentNode.parentNode.appendChild(t):e.parentNode.appendChild(t))})</script>
33</body></html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.