<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Spring/Java universe]]></title><description><![CDATA[Spring/Java universe]]></description><link>https://mnafshin.info</link><generator>RSS for Node</generator><lastBuildDate>Thu, 09 Apr 2026 10:16:41 GMT</lastBuildDate><atom:link href="https://mnafshin.info/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Java Synchronization Mechanisms: A Comprehensive Comparison]]></title><description><![CDATA[Java Synchronization Mechanisms: A Comprehensive Comparison
Introduction
Concurrent programming in Java requires careful management of shared resources. The Java platform provides multiple synchronization mechanisms to prevent data races and ensure t...]]></description><link>https://mnafshin.info/java-synchronization-mechanisms-a-comprehensive-comparison</link><guid isPermaLink="true">https://mnafshin.info/java-synchronization-mechanisms-a-comprehensive-comparison</guid><category><![CDATA[Java]]></category><category><![CDATA[lock]]></category><dc:creator><![CDATA[Afshin Amini]]></dc:creator><pubDate>Mon, 16 Feb 2026 01:15:54 GMT</pubDate><content:encoded><![CDATA[<h1 id="heading-java-synchronization-mechanisms-a-comprehensive-comparison">Java Synchronization Mechanisms: A Comprehensive Comparison</h1>
<h2 id="heading-introduction">Introduction</h2>
<p>Concurrent programming in Java requires careful management of shared resources. The Java platform provides multiple synchronization mechanisms to prevent data races and ensure thread safety. This blog post explores the nuances of intrinsic locks, <code>ReentrantLock</code>, <code>ReadWriteLock</code>, <code>Semaphore</code>, and other synchronization primitives, helping you choose the right tool for your specific use case.</p>
<hr />
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><a class="post-section-overview" href="#intrinsic-locks">Intrinsic Locks (synchronized)</a></li>
<li><a class="post-section-overview" href="#reentrantlock">ReentrantLock</a></li>
<li><a class="post-section-overview" href="#readwritelock">ReadWriteLock</a></li>
<li><a class="post-section-overview" href="#reentrantreadwritelock">ReentrantReadWriteLock</a></li>
<li><a class="post-section-overview" href="#semaphore">Semaphore</a></li>
<li><a class="post-section-overview" href="#stampedlock">StampedLock</a></li>
<li><a class="post-section-overview" href="#countdownlatch">CountDownLatch</a></li>
<li><a class="post-section-overview" href="#cyclicbarrier">CyclicBarrier</a></li>
<li><a class="post-section-overview" href="#phaser">Phaser</a></li>
<li><a class="post-section-overview" href="#comparison-table">Comparison Table</a></li>
<li><a class="post-section-overview" href="#best-practices">Best Practices</a></li>
</ol>
<hr />
<h2 id="heading-intrinsic-locks-intrinsic-locks">Intrinsic Locks {#intrinsic-locks}</h2>
<h3 id="heading-overview">Overview</h3>
<p>Intrinsic locks (also called monitor locks) are the synchronization mechanism built into the Java language itself. Every object in Java has an associated lock that is automatically managed by the JVM.</p>
<h3 id="heading-usage">Usage</h3>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Counter</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> count = <span class="hljs-number">0</span>;

    <span class="hljs-comment">// Synchronize on the instance</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">synchronized</span> <span class="hljs-keyword">void</span> <span class="hljs-title">increment</span><span class="hljs-params">()</span> </span>{
        count++;
    }

    <span class="hljs-comment">// Synchronize on a specific object</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">incrementSafe</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">synchronized</span>(<span class="hljs-keyword">this</span>) {
            count++;
        }
    }
}
</code></pre>
<h3 id="heading-characteristics">Characteristics</h3>
<ul>
<li><strong>Automatic Release</strong>: Locks are automatically released when exiting a synchronized block</li>
<li><strong>Reentrancy</strong>: The same thread can acquire the same lock multiple times</li>
<li><strong>No Timeout</strong>: Cannot timeout waiting for a lock</li>
<li><strong>Simple</strong>: Easy to use and understand</li>
<li><strong>JVM Optimizations</strong>: Subject to optimization (biased locking, lock coarsening)</li>
</ul>
<h3 id="heading-advantages">Advantages</h3>
<p>✅ Simple and straightforward syntax<br />✅ Automatically released (no risk of forgetting to unlock)<br />✅ Reentrant by default<br />✅ Efficient for uncontended locks  </p>
<h3 id="heading-disadvantages">Disadvantages</h3>
<p>❌ Cannot check if lock is available without attempting to acquire it<br />❌ No timeout support<br />❌ Must use nested synchronized blocks for multiple locks (deadlock risk)<br />❌ Less flexible than explicit locks  </p>
<h3 id="heading-example">Example</h3>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BankAccount</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> balance = <span class="hljs-number">0</span>;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">synchronized</span> <span class="hljs-keyword">void</span> <span class="hljs-title">deposit</span><span class="hljs-params">(<span class="hljs-keyword">double</span> amount)</span> </span>{
        balance += amount;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">synchronized</span> <span class="hljs-keyword">void</span> <span class="hljs-title">withdraw</span><span class="hljs-params">(<span class="hljs-keyword">double</span> amount)</span> </span>{
        balance -= amount;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">synchronized</span> <span class="hljs-keyword">double</span> <span class="hljs-title">getBalance</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> balance;
    }
}
</code></pre>
<hr />
<h2 id="heading-reentrantlock-reentrantlock">ReentrantLock {#reentrantlock}</h2>
<h3 id="heading-overview-1">Overview</h3>
<p><code>ReentrantLock</code> is an explicit implementation of the <code>Lock</code> interface that provides similar functionality to intrinsic locks but with additional features and flexibility.</p>
<h3 id="heading-usage-1">Usage</h3>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.concurrent.locks.ReentrantLock;
<span class="hljs-keyword">import</span> java.util.concurrent.locks.Lock;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Counter</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> count = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> Lock lock = <span class="hljs-keyword">new</span> ReentrantLock();

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">increment</span><span class="hljs-params">()</span> </span>{
        lock.lock();
        <span class="hljs-keyword">try</span> {
            count++;
        } <span class="hljs-keyword">finally</span> {
            lock.unlock();
        }
    }
}
</code></pre>
<h3 id="heading-characteristics-1">Characteristics</h3>
<ul>
<li><strong>Explicit Control</strong>: Manual lock and unlock</li>
<li><strong>Reentrancy</strong>: Same thread can acquire multiple times</li>
<li><strong>Fairness</strong>: Optional fair queuing policy (FIFO)</li>
<li><strong>Timeout Support</strong>: Can timeout waiting for lock</li>
<li><strong>Interruptible</strong>: Can be interrupted while waiting</li>
<li><strong>Try Lock</strong>: Can attempt non-blocking lock acquisition</li>
</ul>
<h3 id="heading-advantages-1">Advantages</h3>
<p>✅ Supports timeout with <code>tryLock(long, TimeUnit)</code><br />✅ Interruptible via <code>lockInterruptibly()</code><br />✅ Can check lock status with <code>tryLock()</code><br />✅ Fair scheduling option available<br />✅ Works with Conditions for advanced synchronization  </p>
<h3 id="heading-disadvantages-1">Disadvantages</h3>
<p>❌ Manual unlock required (easy to forget)<br />❌ More verbose than <code>synchronized</code><br />❌ Slightly higher overhead than intrinsic locks  </p>
<h3 id="heading-example-1">Example</h3>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.concurrent.TimeUnit;
<span class="hljs-keyword">import</span> java.util.concurrent.locks.ReentrantLock;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TimedLockExample</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> ReentrantLock lock = <span class="hljs-keyword">new</span> ReentrantLock();
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> value = <span class="hljs-number">0</span>;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">updateValue</span><span class="hljs-params">(<span class="hljs-keyword">int</span> newValue)</span> <span class="hljs-keyword">throws</span> InterruptedException </span>{
        <span class="hljs-keyword">if</span> (lock.tryLock(<span class="hljs-number">5</span>, TimeUnit.SECONDS)) {
            <span class="hljs-keyword">try</span> {
                value = newValue;
                System.out.println(<span class="hljs-string">"Value updated to: "</span> + newValue);
            } <span class="hljs-keyword">finally</span> {
                lock.unlock();
            }
        } <span class="hljs-keyword">else</span> {
            System.out.println(<span class="hljs-string">"Could not acquire lock within timeout"</span>);
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">interruptibleUpdate</span><span class="hljs-params">(<span class="hljs-keyword">int</span> newValue)</span> <span class="hljs-keyword">throws</span> InterruptedException </span>{
        lock.lockInterruptibly();
        <span class="hljs-keyword">try</span> {
            value = newValue;
        } <span class="hljs-keyword">finally</span> {
            lock.unlock();
        }
    }
}
</code></pre>
<hr />
<h2 id="heading-readwritelock-readwritelock">ReadWriteLock {#readwritelock}</h2>
<h3 id="heading-overview-2">Overview</h3>
<p><code>ReadWriteLock</code> maintains a pair of locks: one for read access and one for write access. Multiple threads can hold the read lock simultaneously, but only one thread can hold the write lock.</p>
<h3 id="heading-characteristics-2">Characteristics</h3>
<ul>
<li><strong>Concurrent Reads</strong>: Multiple threads can read simultaneously</li>
<li><strong>Exclusive Writes</strong>: Only one thread can write, and no reads happen during writes</li>
<li><strong>Improved Throughput</strong>: Better performance when reads greatly outnumber writes</li>
<li><strong>Read-Write Lock Semantics</strong>: Readers don't block each other</li>
</ul>
<h3 id="heading-usage-2">Usage</h3>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.concurrent.locks.ReadWriteLock;
<span class="hljs-keyword">import</span> java.util.concurrent.locks.ReentrantReadWriteLock;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DataCache</span> </span>{
    <span class="hljs-keyword">private</span> String data = <span class="hljs-string">""</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> ReadWriteLock rwLock = <span class="hljs-keyword">new</span> ReentrantReadWriteLock();

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getData</span><span class="hljs-params">()</span> </span>{
        rwLock.readLock().lock();
        <span class="hljs-keyword">try</span> {
            <span class="hljs-keyword">return</span> data;
        } <span class="hljs-keyword">finally</span> {
            rwLock.readLock().unlock();
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setData</span><span class="hljs-params">(String newData)</span> </span>{
        rwLock.writeLock().lock();
        <span class="hljs-keyword">try</span> {
            data = newData;
        } <span class="hljs-keyword">finally</span> {
            rwLock.writeLock().unlock();
        }
    }
}
</code></pre>
<h3 id="heading-advantages-2">Advantages</h3>
<p>✅ Excellent for read-heavy workloads<br />✅ Multiple concurrent readers<br />✅ Exclusive write access<br />✅ Prevents writer starvation  </p>
<h3 id="heading-disadvantages-2">Disadvantages</h3>
<p>❌ More overhead than simple locks<br />❌ Not beneficial when reads and writes are balanced<br />❌ More complex to understand and use  </p>
<hr />
<h2 id="heading-reentrantreadwritelock-reentrantreadwritelock">ReentrantReadWriteLock {#reentrantreadwritelock}</h2>
<h3 id="heading-overview-3">Overview</h3>
<p><code>ReentrantReadWriteLock</code> is the standard implementation of <code>ReadWriteLock</code> in Java. It provides reentrancy for both read and write locks with optional fairness.</p>
<h3 id="heading-example-2">Example</h3>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.concurrent.locks.ReentrantReadWriteLock;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CachedData</span> </span>{
    <span class="hljs-keyword">private</span> String value = <span class="hljs-string">""</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> ReentrantReadWriteLock lock = <span class="hljs-keyword">new</span> ReentrantReadWriteLock();

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getValue</span><span class="hljs-params">()</span> </span>{
        lock.readLock().lock();
        <span class="hljs-keyword">try</span> {
            <span class="hljs-keyword">return</span> value;
        } <span class="hljs-keyword">finally</span> {
            lock.readLock().unlock();
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setValue</span><span class="hljs-params">(String newValue)</span> </span>{
        lock.writeLock().lock();
        <span class="hljs-keyword">try</span> {
            value = newValue;
        } <span class="hljs-keyword">finally</span> {
            lock.writeLock().unlock();
        }
    }

    <span class="hljs-comment">// Downgrade write lock to read lock</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">processData</span><span class="hljs-params">()</span> </span>{
        lock.writeLock().lock();
        <span class="hljs-keyword">try</span> {
            <span class="hljs-comment">// Perform write operation</span>
            value = <span class="hljs-string">"processed"</span>;

            <span class="hljs-comment">// Acquire read lock before releasing write lock (downgrade)</span>
            lock.readLock().lock();
        } <span class="hljs-keyword">finally</span> {
            lock.writeLock().unlock();
        }

        <span class="hljs-keyword">try</span> {
            <span class="hljs-comment">// Now we only hold the read lock</span>
            System.out.println(<span class="hljs-string">"Current value: "</span> + value);
        } <span class="hljs-keyword">finally</span> {
            lock.readLock().unlock();
        }
    }
}
</code></pre>
<hr />
<h2 id="heading-semaphore-semaphore">Semaphore {#semaphore}</h2>
<h3 id="heading-overview-4">Overview</h3>
<p>A <code>Semaphore</code> maintains a set of permits. Threads call <code>acquire()</code> to wait for a permit and <code>release()</code> to release one. When no permits are available, <code>acquire()</code> blocks the thread.</p>
<h3 id="heading-characteristics-3">Characteristics</h3>
<ul>
<li><strong>Permit-Based</strong>: Controls access through a pool of permits</li>
<li><strong>Resource Pooling</strong>: Useful for limiting concurrent access to a resource pool</li>
<li><strong>Counting Semaphore</strong>: Maintains a count of permits</li>
<li><strong>Binary Semaphore</strong>: Acts as a lock when permit count = 1</li>
<li><strong>Non-Reentrant</strong>: By default, doesn't allow the same thread to acquire twice</li>
</ul>
<h3 id="heading-usage-3">Usage</h3>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.concurrent.Semaphore;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ConnectionPool</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> Semaphore semaphore = <span class="hljs-keyword">new</span> Semaphore(<span class="hljs-number">5</span>); <span class="hljs-comment">// 5 connections available</span>

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">executeTask</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> InterruptedException </span>{
        semaphore.acquire(); <span class="hljs-comment">// Wait for a permit</span>
        <span class="hljs-keyword">try</span> {
            System.out.println(<span class="hljs-string">"Executing task with connection"</span>);
            <span class="hljs-comment">// Simulate work</span>
            Thread.sleep(<span class="hljs-number">1000</span>);
        } <span class="hljs-keyword">finally</span> {
            semaphore.release(); <span class="hljs-comment">// Release the permit</span>
        }
    }
}
</code></pre>
<h3 id="heading-advantages-3">Advantages</h3>
<p>✅ Excellent for resource pooling<br />✅ Simple counting mechanism<br />✅ Can be used as a binary lock (Mutex)<br />✅ Supports timeout with <code>tryAcquire(long, TimeUnit)</code>  </p>
<h3 id="heading-disadvantages-3">Disadvantages</h3>
<p>❌ Not reentrant (unless you track permits manually)<br />❌ Less intuitive than locks for mutual exclusion<br />❌ No condition variables  </p>
<h3 id="heading-binary-semaphore-mutex">Binary Semaphore (Mutex)</h3>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.concurrent.Semaphore;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MutexExample</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> Semaphore mutex = <span class="hljs-keyword">new</span> Semaphore(<span class="hljs-number">1</span>); <span class="hljs-comment">// Binary semaphore</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> counter = <span class="hljs-number">0</span>;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">incrementCounter</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> InterruptedException </span>{
        mutex.acquire();
        <span class="hljs-keyword">try</span> {
            counter++;
        } <span class="hljs-keyword">finally</span> {
            mutex.release();
        }
    }
}
</code></pre>
<hr />
<h2 id="heading-stampedlock-stampedlock">StampedLock {#stampedlock}</h2>
<h3 id="heading-overview-5">Overview</h3>
<p><code>StampedLock</code> is a high-performance lock introduced in Java 8 that provides three modes: write lock, read lock, and optimistic read. The optimistic read mode doesn't acquire a lock at all but checks a "stamp" to detect conflicts.</p>
<h3 id="heading-characteristics-4">Characteristics</h3>
<ul>
<li><strong>Optimistic Reading</strong>: Can read without acquiring a lock</li>
<li><strong>Stamp-Based Validation</strong>: Uses stamps to detect write conflicts</li>
<li><strong>High Performance</strong>: Designed for low-contention scenarios</li>
<li><strong>Three Modes</strong>: Optimistic read, pessimistic read, write</li>
<li><strong>Non-Reentrant</strong>: Cannot be reacquired by the same thread</li>
</ul>
<h3 id="heading-usage-4">Usage</h3>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.concurrent.locks.StampedLock;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OptimizedData</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> value = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> StampedLock lock = <span class="hljs-keyword">new</span> StampedLock();

    <span class="hljs-comment">// Optimistic read - fast path</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">readOptimistic</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">long</span> stamp = lock.tryOptimisticRead();
        <span class="hljs-keyword">int</span> result = value;

        <span class="hljs-keyword">if</span> (!lock.validate(stamp)) {
            <span class="hljs-comment">// Conflict detected, fall back to pessimistic read</span>
            stamp = lock.readLock();
            <span class="hljs-keyword">try</span> {
                result = value;
            } <span class="hljs-keyword">finally</span> {
                lock.unlockRead(stamp);
            }
        }
        <span class="hljs-keyword">return</span> result;
    }

    <span class="hljs-comment">// Pessimistic read</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">readPessimistic</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">long</span> stamp = lock.readLock();
        <span class="hljs-keyword">try</span> {
            <span class="hljs-keyword">return</span> value;
        } <span class="hljs-keyword">finally</span> {
            lock.unlockRead(stamp);
        }
    }

    <span class="hljs-comment">// Write lock</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">write</span><span class="hljs-params">(<span class="hljs-keyword">int</span> newValue)</span> </span>{
        <span class="hljs-keyword">long</span> stamp = lock.writeLock();
        <span class="hljs-keyword">try</span> {
            value = newValue;
        } <span class="hljs-keyword">finally</span> {
            lock.unlockWrite(stamp);
        }
    }
}
</code></pre>
<h3 id="heading-advantages-4">Advantages</h3>
<p>✅ Excellent performance for read-heavy, low-contention scenarios<br />✅ Optimistic read avoids blocking<br />✅ Lower overhead than ReentrantReadWriteLock  </p>
<h3 id="heading-disadvantages-4">Disadvantages</h3>
<p>❌ Not reentrant<br />❌ More complex API<br />❌ Should only be used when you understand the implications<br />❌ Optimistic reads can fail (need validation logic)  </p>
<hr />
<h2 id="heading-countdownlatch-countdownlatch">CountDownLatch {#countdownlatch}</h2>
<h3 id="heading-overview-6">Overview</h3>
<p><code>CountDownLatch</code> is a synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.</p>
<h3 id="heading-characteristics-5">Characteristics</h3>
<ul>
<li><strong>One-Time Use</strong>: Cannot be reset once count reaches zero</li>
<li><strong>Countdown Mechanism</strong>: Count decrements with each <code>countDown()</code> call</li>
<li><strong>Blocking Wait</strong>: <code>await()</code> blocks until count reaches zero</li>
<li><strong>Simple Coordination</strong>: Good for one-off synchronization</li>
</ul>
<h3 id="heading-usage-5">Usage</h3>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.concurrent.CountDownLatch;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ParallelProcessing</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> InterruptedException </span>{
        <span class="hljs-keyword">int</span> numWorkers = <span class="hljs-number">3</span>;
        CountDownLatch latch = <span class="hljs-keyword">new</span> CountDownLatch(numWorkers);

        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; numWorkers; i++) {
            <span class="hljs-keyword">new</span> Thread(() -&gt; {
                System.out.println(Thread.currentThread().getName() + <span class="hljs-string">" is working"</span>);
                <span class="hljs-keyword">try</span> {
                    Thread.sleep(<span class="hljs-number">2000</span>);
                } <span class="hljs-keyword">catch</span> (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
                System.out.println(Thread.currentThread().getName() + <span class="hljs-string">" finished"</span>);
                latch.countDown();
            }).start();
        }

        latch.await(); <span class="hljs-comment">// Wait for all workers to finish</span>
        System.out.println(<span class="hljs-string">"All workers completed!"</span>);
    }
}
</code></pre>
<h3 id="heading-advantages-5">Advantages</h3>
<p>✅ Simple and intuitive for one-off synchronization<br />✅ Lightweight and efficient<br />✅ Supports timeout with <code>await(long, TimeUnit)</code>  </p>
<h3 id="heading-disadvantages-5">Disadvantages</h3>
<p>❌ Cannot be reused (count cannot be reset)<br />❌ Only useful for one-time events<br />❌ Not suitable for repeating synchronization  </p>
<hr />
<h2 id="heading-cyclicbarrier-cyclicbarrier">CyclicBarrier {#cyclicbarrier}</h2>
<h3 id="heading-overview-7">Overview</h3>
<p><code>CyclicBarrier</code> allows a fixed number of parties to wait for each other at a barrier point. Unlike <code>CountDownLatch</code>, it can be reused.</p>
<h3 id="heading-characteristics-6">Characteristics</h3>
<ul>
<li><strong>Reusable</strong>: Can be used multiple times (cyclic)</li>
<li><strong>Mutual Waiting</strong>: All threads wait for each other</li>
<li><strong>Barrier Action</strong>: Optional action executed when all parties arrive</li>
<li><strong>Fixed Number of Parties</strong>: Number of threads must be known upfront</li>
</ul>
<h3 id="heading-usage-6">Usage</h3>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.concurrent.CyclicBarrier;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BarrierExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-keyword">int</span> numThreads = <span class="hljs-number">3</span>;
        CyclicBarrier barrier = <span class="hljs-keyword">new</span> CyclicBarrier(numThreads, () -&gt; {
            System.out.println(<span class="hljs-string">"All threads have reached the barrier!"</span>);
        });

        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; numThreads; i++) {
            <span class="hljs-keyword">new</span> Thread(() -&gt; {
                <span class="hljs-keyword">try</span> {
                    System.out.println(Thread.currentThread().getName() + <span class="hljs-string">" is working"</span>);
                    Thread.sleep((<span class="hljs-keyword">long</span>)(Math.random() * <span class="hljs-number">3000</span>));
                    System.out.println(Thread.currentThread().getName() + <span class="hljs-string">" reached barrier"</span>);
                    barrier.await(); <span class="hljs-comment">// Wait for others</span>
                    System.out.println(Thread.currentThread().getName() + <span class="hljs-string">" passed barrier"</span>);
                } <span class="hljs-keyword">catch</span> (Exception e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}
</code></pre>
<h3 id="heading-advantages-6">Advantages</h3>
<p>✅ Reusable (cyclic)<br />✅ Symmetric - all threads wait for each other<br />✅ Optional barrier action supports coordinated tasks<br />✅ Good for iterative synchronization  </p>
<h3 id="heading-disadvantages-6">Disadvantages</h3>
<p>❌ All threads must wait (no timeout)<br />❌ Breaking the barrier (exception) may cause issues<br />❌ Less flexible than Phaser  </p>
<hr />
<h2 id="heading-phaser-phaser">Phaser {#phaser}</h2>
<h3 id="heading-overview-8">Overview</h3>
<p><code>Phaser</code> is a more flexible version of <code>CyclicBarrier</code> and <code>CountDownLatch</code> combined. It supports dynamic party registration and can be reused across multiple phases.</p>
<h3 id="heading-characteristics-7">Characteristics</h3>
<ul>
<li><strong>Flexible Parties</strong>: Can dynamically register/deregister threads</li>
<li><strong>Multiple Phases</strong>: Can synchronize through multiple phases</li>
<li><strong>Phased Execution</strong>: Better control over multi-phase synchronization</li>
<li><strong>Timeout Support</strong>: Can timeout waiting for a phase to complete</li>
<li><strong>Terminal Phase</strong>: Can handle completion elegantly</li>
</ul>
<h3 id="heading-usage-7">Usage</h3>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.concurrent.Phaser;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PhaserExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Phaser phaser = <span class="hljs-keyword">new</span> Phaser(<span class="hljs-number">1</span>); <span class="hljs-comment">// Register the main thread</span>

        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">3</span>; i++) {
            phaser.register(); <span class="hljs-comment">// Register each worker</span>
            <span class="hljs-keyword">new</span> Thread(() -&gt; {
                <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> phase = <span class="hljs-number">0</span>; phase &lt; <span class="hljs-number">3</span>; phase++) {
                    System.out.println(Thread.currentThread().getName() + 
                        <span class="hljs-string">" working on phase "</span> + phase);
                    <span class="hljs-keyword">try</span> {
                        Thread.sleep((<span class="hljs-keyword">long</span>)(Math.random() * <span class="hljs-number">2000</span>));
                    } <span class="hljs-keyword">catch</span> (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                    System.out.println(Thread.currentThread().getName() + 
                        <span class="hljs-string">" finished phase "</span> + phase);
                    phaser.arriveAndAwaitAdvance(); <span class="hljs-comment">// Move to next phase</span>
                }
            }).start();
        }

        phaser.arriveAndAwaitAdvance(); <span class="hljs-comment">// Advance from phase 0</span>
        System.out.println(<span class="hljs-string">"Phase 0 complete!"</span>);

        phaser.arriveAndAwaitAdvance(); <span class="hljs-comment">// Advance from phase 1</span>
        System.out.println(<span class="hljs-string">"Phase 1 complete!"</span>);

        phaser.arriveAndAwaitAdvance(); <span class="hljs-comment">// Advance from phase 2</span>
        System.out.println(<span class="hljs-string">"Phase 2 complete!"</span>);
    }
}
</code></pre>
<h3 id="heading-advantages-7">Advantages</h3>
<p>✅ Dynamic party registration<br />✅ Multiple phases support<br />✅ Timeout support with <code>awaitAdvanceInterruptibly()</code><br />✅ Elegant handling of completion<br />✅ Most flexible synchronization primitive  </p>
<h3 id="heading-disadvantages-7">Disadvantages</h3>
<p>❌ More complex API<br />❌ Slight overhead compared to simpler mechanisms<br />❌ Requires careful understanding of phase advancement  </p>
<hr />
<h2 id="heading-comparison-table-comparison-table">Comparison Table {#comparison-table}</h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Feature</td><td>Intrinsic Lock</td><td>ReentrantLock</td><td>ReadWriteLock</td><td>Semaphore</td><td>StampedLock</td><td>CountDownLatch</td><td>CyclicBarrier</td><td>Phaser</td></tr>
</thead>
<tbody>
<tr>
<td><strong>Mutual Exclusion</strong></td><td>✅</td><td>✅</td><td>✅ (Write)</td><td>✅</td><td>✅</td><td>❌</td><td>❌</td><td>❌</td></tr>
<tr>
<td><strong>Reentrancy</strong></td><td>✅</td><td>✅</td><td>✅</td><td>❌</td><td>❌</td><td>N/A</td><td>N/A</td><td>N/A</td></tr>
<tr>
<td><strong>Fairness Option</strong></td><td>❌</td><td>✅</td><td>✅</td><td>❌</td><td>❌</td><td>N/A</td><td>N/A</td><td>N/A</td></tr>
<tr>
<td><strong>Timeout Support</strong></td><td>❌</td><td>✅</td><td>✅</td><td>✅</td><td>✅</td><td>✅</td><td>❌</td><td>✅</td></tr>
<tr>
<td><strong>Interruptible</strong></td><td>❌</td><td>✅</td><td>✅</td><td>✅</td><td>❌</td><td>✅</td><td>❌</td><td>✅</td></tr>
<tr>
<td><strong>Conditions</strong></td><td>✅</td><td>✅</td><td>❌</td><td>❌</td><td>❌</td><td>❌</td><td>❌</td><td>❌</td></tr>
<tr>
<td><strong>Read-Write Separation</strong></td><td>❌</td><td>❌</td><td>✅</td><td>❌</td><td>✅</td><td>❌</td><td>❌</td><td>❌</td></tr>
<tr>
<td><strong>Concurrent Reads</strong></td><td>❌</td><td>❌</td><td>✅</td><td>❌</td><td>✅</td><td>N/A</td><td>N/A</td><td>N/A</td></tr>
<tr>
<td><strong>Reusable</strong></td><td>✅</td><td>✅</td><td>✅</td><td>✅</td><td>✅</td><td>❌</td><td>✅</td><td>✅</td></tr>
<tr>
<td><strong>Dynamic Parties</strong></td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>❌</td><td>✅</td></tr>
<tr>
<td><strong>Multiple Phases</strong></td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>❌</td><td>✅</td><td>✅</td></tr>
<tr>
<td><strong>Performance</strong></td><td>⚡⚡⚡</td><td>⚡⚡</td><td>⚡⚡</td><td>⚡⚡⚡</td><td>⚡⚡⚡⚡</td><td>⚡⚡⚡</td><td>⚡⚡⚡</td><td>⚡⚡⚡</td></tr>
<tr>
<td><strong>Complexity</strong></td><td>⭐</td><td>⭐⭐</td><td>⭐⭐</td><td>⭐⭐</td><td>⭐⭐⭐</td><td>⭐</td><td>⭐⭐</td><td>⭐⭐⭐</td></tr>
</tbody>
</table>
</div><hr />
<h2 id="heading-best-practices-best-practices">Best Practices {#best-practices}</h2>
<h3 id="heading-1-choose-the-right-tool">1. <strong>Choose the Right Tool</strong></h3>
<ul>
<li><strong>Simple mutual exclusion</strong>: Use <code>synchronized</code> for simplicity</li>
<li><strong>Advanced locking needs</strong>: Use <code>ReentrantLock</code> for flexibility</li>
<li><strong>Read-heavy workloads</strong>: Use <code>ReadWriteLock</code> or <code>StampedLock</code></li>
<li><strong>Resource pooling</strong>: Use <code>Semaphore</code></li>
<li><strong>One-time coordination</strong>: Use <code>CountDownLatch</code></li>
<li><strong>Iterative synchronization</strong>: Use <code>CyclicBarrier</code></li>
<li><strong>Multi-phase synchronization</strong>: Use <code>Phaser</code></li>
</ul>
<h3 id="heading-2-always-release-locks">2. <strong>Always Release Locks</strong></h3>
<pre><code class="lang-java">Lock lock = <span class="hljs-keyword">new</span> ReentrantLock();
lock.lock();
<span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// Critical section</span>
} <span class="hljs-keyword">finally</span> {
    lock.unlock(); <span class="hljs-comment">// Always execute in finally</span>
}
</code></pre>
<h3 id="heading-3-avoid-deadlocks">3. <strong>Avoid Deadlocks</strong></h3>
<pre><code class="lang-java"><span class="hljs-comment">// ❌ BAD: Risk of deadlock with nested locks</span>
lock1.lock();
lock2.lock();

<span class="hljs-comment">// ✅ GOOD: Consistent lock ordering</span>
<span class="hljs-keyword">if</span> (lock1.getId() &lt; lock2.getId()) {
    lock1.lock();
    lock2.lock();
} <span class="hljs-keyword">else</span> {
    lock2.lock();
    lock1.lock();
}
</code></pre>
<h3 id="heading-4-use-try-finally-or-try-with-resources">4. <strong>Use Try-Finally or Try-With-Resources</strong></h3>
<pre><code class="lang-java"><span class="hljs-comment">// ✅ GOOD: Modern approach with try-with-resources (if available)</span>
<span class="hljs-keyword">try</span> (Locker locked = <span class="hljs-keyword">new</span> Locker(lock)) {
    <span class="hljs-comment">// Critical section</span>
}

<span class="hljs-comment">// ✅ GOOD: Traditional try-finally</span>
lock.lock();
<span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// Critical section</span>
} <span class="hljs-keyword">finally</span> {
    lock.unlock();
}
</code></pre>
<h3 id="heading-5-consider-high-level-abstractions">5. <strong>Consider High-Level Abstractions</strong></h3>
<pre><code class="lang-java"><span class="hljs-comment">// ❌ Low-level: Manual synchronization</span>
<span class="hljs-comment">// ✅ High-level: Collections.synchronizedList or ConcurrentHashMap</span>
List&lt;String&gt; list = Collections.synchronizedList(<span class="hljs-keyword">new</span> ArrayList&lt;&gt;());
</code></pre>
<h3 id="heading-6-profile-before-optimizing">6. <strong>Profile Before Optimizing</strong></h3>
<p>StampedLock and other advanced locks introduce complexity. Profile your application to ensure the performance gains justify the complexity.</p>
<pre><code class="lang-java"><span class="hljs-comment">// ❌ Premature optimization</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> StampedLock lock = <span class="hljs-keyword">new</span> StampedLock(); <span class="hljs-comment">// Might be overkill</span>

<span class="hljs-comment">// ✅ Thoughtful choice based on workload analysis</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> ReentrantReadWriteLock lock = <span class="hljs-keyword">new</span> ReentrantReadWriteLock(); <span class="hljs-comment">// Suitable for the workload</span>
</code></pre>
<h3 id="heading-7-document-lock-ordering">7. <strong>Document Lock Ordering</strong></h3>
<pre><code class="lang-java"><span class="hljs-comment">/**
 * Locks must be acquired in this order to prevent deadlocks:
 * 1. accountLock
 * 2. transactionLock
 */</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">transfer</span><span class="hljs-params">(Account from, Account to, <span class="hljs-keyword">double</span> amount)</span> </span>{
    <span class="hljs-comment">// Lock in documented order</span>
}
</code></pre>
<h3 id="heading-8-use-javautilconcurrent-collections">8. <strong>Use java.util.concurrent Collections</strong></h3>
<pre><code class="lang-java"><span class="hljs-comment">// ✅ Preferred: Concurrent collections handle synchronization internally</span>
Map&lt;String, Integer&gt; map = <span class="hljs-keyword">new</span> ConcurrentHashMap&lt;&gt;();
List&lt;String&gt; list = <span class="hljs-keyword">new</span> CopyOnWriteArrayList&lt;&gt;();
Queue&lt;String&gt; queue = <span class="hljs-keyword">new</span> ConcurrentLinkedQueue&lt;&gt;();
</code></pre>
<hr />
<h2 id="heading-summary">Summary</h2>
<p>Java provides multiple synchronization mechanisms, each suited for different scenarios:</p>
<ul>
<li><strong><code>synchronized</code> (Intrinsic Locks)</strong>: Simple, built-in, suitable for basic synchronization</li>
<li><strong><code>ReentrantLock</code></strong>: Flexible, feature-rich alternative to synchronized with timeout and interruptibility</li>
<li><strong><code>ReadWriteLock</code></strong>: Optimized for read-heavy workloads with concurrent readers</li>
<li><strong><code>Semaphore</code></strong>: Perfect for resource pooling and limiting concurrent access</li>
<li><strong><code>StampedLock</code></strong>: High-performance option for low-contention scenarios with optimistic reads</li>
<li><strong><code>CountDownLatch</code></strong>: Simple one-time synchronization for waiting on completion</li>
<li><strong><code>CyclicBarrier</code></strong>: For reusable barrier points where threads wait for each other</li>
<li><strong><code>Phaser</code></strong>: Most flexible for multi-phase, dynamic synchronization scenarios</li>
</ul>
<p>The key is understanding your workload and choosing the appropriate primitive that provides the necessary functionality with minimal complexity. In most cases, simple solutions like <code>synchronized</code> or the concurrent collections are sufficient and preferable.</p>
<hr />
<h2 id="heading-interactive-demos">Interactive Demos</h2>
<p>This blog post comes with comprehensive, runnable demonstrations of each synchronization mechanism. Each demo includes:</p>
<ul>
<li><strong>Real-world scenarios</strong> (bank accounts, caches, connection pools, pipelines, game rounds)</li>
<li><strong>Best practices</strong> with detailed comments</li>
<li><strong>Multiple example classes</strong> per synchronization type</li>
<li><strong>Performance comparisons</strong> where applicable</li>
<li><strong>Exception handling</strong> and timeout patterns</li>
</ul>
<h3 id="heading-demo-files">Demo Files</h3>
<ol>
<li><strong>IntrinsicLockDemo</strong> - Bank accounts, thread-safe counters, and caches</li>
<li><strong>ReentrantLockDemo</strong> - Timeout support, producer-consumer queues, and fair scheduling</li>
<li><strong>ReadWriteLockDemo</strong> - Concurrent readers with performance comparison</li>
<li><strong>SemaphoreDemo</strong> - Connection pooling, rate limiting, and thread pool control</li>
<li><strong>StampedLockDemo</strong> - Optimistic reads with pessimistic fallback</li>
<li><strong>CountDownLatchDemo</strong> - Parallel task execution and pipeline coordination</li>
<li><strong>CyclicBarrierDemo</strong> - Iterative processing and game round synchronization</li>
<li><strong>PhaserDemo</strong> - Multi-phase execution and dynamic party management</li>
</ol>
<h3 id="heading-running-the-demos">Running the Demos</h3>
<p>Run the interactive launcher:</p>
<pre><code class="lang-bash">java info.mnafshin.locks_in_java.demos.DemoLauncher
</code></pre>
<p>Or run individual demos:</p>
<pre><code class="lang-bash">java info.mnafshin.locks_in_java.demos.IntrinsicLockDemo
java info.mnafshin.locks_in_java.demos.ReentrantLockDemo
java info.mnafshin.locks_in_java.demos.SemaphoreDemo
<span class="hljs-comment"># ... etc</span>
</code></pre>
<p>See <a target="_blank" href="DEMOS_README.md">DEMOS_README.md</a> for detailed documentation and usage instructions for each demo.</p>
<hr />
<h2 id="heading-further-reading">Further Reading</h2>
<ul>
<li>Java Concurrency in Practice (Book)</li>
<li>Java API Documentation: <code>java.util.concurrent</code> package</li>
<li>Oracle Java Tutorials on Concurrency</li>
</ul>
<hr />
<h2 id="heading-get-the-code">Get the Code</h2>
<p>The source code for this project is available on GitHub: 
https://github.com/mnafshin/locks-in-java.git</p>
]]></content:encoded></item><item><title><![CDATA[Debugging Java SSL/TLS Connections: A Guide to javax.net.debug]]></title><description><![CDATA[Introduction
Understanding SSL/TLS handshakes is crucial for debugging secure connections in Java applications. In this guide, I'll walk you through a real-world example of capturing and analyzing an SSL/TLS handshake using Java's built-in debugging ...]]></description><link>https://mnafshin.info/debugging-java-ssltls-connections-a-guide-to-javaxnetdebug</link><guid isPermaLink="true">https://mnafshin.info/debugging-java-ssltls-connections-a-guide-to-javaxnetdebug</guid><category><![CDATA[SSL]]></category><category><![CDATA[debugging]]></category><category><![CDATA[troubleshooting]]></category><dc:creator><![CDATA[Afshin Amini]]></dc:creator><pubDate>Fri, 23 Jan 2026 17:10:22 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>Understanding SSL/TLS handshakes is crucial for debugging secure connections in Java applications. In this guide, I'll walk you through a real-world example of capturing and analyzing an SSL/TLS handshake using Java's built-in debugging capabilities.</p>
<p>This article covers:</p>
<ul>
<li>How to enable SSL/TLS debugging in Java</li>
<li>Real handshake flow with detailed timing</li>
<li>Complete working example with <code>HttpURLConnection</code></li>
<li>Step-by-step breakdown of the TLS 1.2 handshake</li>
</ul>
<hr />
<h2 id="heading-enabling-ssltls-debug-output">Enabling SSL/TLS Debug Output</h2>
<p>To capture SSL/TLS debugging information, simply set this system property before establishing any connections:</p>
<pre><code class="lang-java">System.setProperty(<span class="hljs-string">"javax.net.debug"</span>, <span class="hljs-string">"all"</span>);
</code></pre>
<p>This enables comprehensive logging of:</p>
<ul>
<li>Cipher suite negotiation</li>
<li>Certificate validation</li>
<li>Handshake messages</li>
<li>Raw bytes sent/received</li>
<li>Session information</li>
</ul>
<h2 id="heading-real-world-tls-12-handshake-flow">Real-World TLS 1.2 Handshake Flow</h2>
<p>When you connect to an HTTPS endpoint (in our example: <code>https://httpbin.org/get</code>), the following handshake occurs:</p>
<h3 id="heading-ascii-diagram-complete-tls-12-handshake">ASCII Diagram: Complete TLS 1.2 Handshake</h3>
<pre><code>CLIENT (Java App)                           SERVER (httpbin.org)
════════════════════════════════════════════════════════════════

        ┌─────────────────────────────────┐
        │  <span class="hljs-number">1.</span> ClientHello                 │
        │  (<span class="hljs-number">22</span>:<span class="hljs-number">20</span>:<span class="hljs-number">06.819</span> CET)             │
        │  - Ciphers, Extensions          │
        │  - Random value                 │
        └────────────────────┬────────────┘
                             │
                             │ [Raw write]
                             │ TLS <span class="hljs-number">1.2</span> record
                             ├──────────────────────────────────&gt;
                                                                │
                                           ┌────────────────────┘
                                           │
                                           ▼
                            ┌──────────────────────────────────┐
                            │  <span class="hljs-number">2.</span> ServerHello                  │
                            │  (<span class="hljs-number">22</span>:<span class="hljs-number">20</span>:<span class="hljs-number">06.924</span> CET)              │
                            │  - Selected cipher suite:        │
                            │    TLS_ECDHE_RSA_WITH_AES_128... │
                            │  - Server random                 │
                            │  - Session ID                    │
                            └────────────────┬──────────────────┘
                                             │
                                             │ [Raw read]
        ┌────────────────────────────────────┤
        │                                     │
        ▼                                     ▼
┌──────────────────────────────┐  ┌──────────────────────────────────┐
│  <span class="hljs-number">3.</span> Server Certificate       │  │  <span class="hljs-number">4.</span> ServerKeyExchange (ECDH)     │
│  (<span class="hljs-number">22</span>:<span class="hljs-number">20</span>:<span class="hljs-number">06.930</span> CET)          │  │  (<span class="hljs-number">22</span>:<span class="hljs-number">20</span>:<span class="hljs-number">06.950</span> CET)              │
│  - Certificate chain:        │  │  - ECDH parameters               │
│    └─ httpbin.org            │  │  - Server<span class="hljs-string">'s ECDH public key      │
│    └─ Amazon RSA 2048 M      │  │  - Signature                     │
│    └─ Root CA                │  │                                  │
└──────────────────────────────┘  └──────────────────────────────────┘
        │                                    │
        └────────────────────┬───────────────┘
                             │
                             ▼
                    ┌──────────────────────┐
                    │  5. ServerHelloDone  │
                    │  (22:20:06.951 CET)  │
                    └────────┬─────────────┘
                             │
                             │ [Raw read]
        ┌────────────────────┘
        │
        ▼
┌───────────────────────────────────────────┐
│  6. ClientKeyExchange (ECDHE)             │
│  (22:20:06.951 CET)                       │
│  - Client'</span>s ECDH public key               │
│  - Compute shared secret (PreMasterKey)   │
└────────────────┬────────────────────────────┐
                 │                            │
                 │ [Raw write]                │
                 │ TLS <span class="hljs-number">1.2</span> handshake         │
                 ├───────────────────────────────────────────────&gt;
                 │                            │
                 ▼                            │
┌────────────────────────────────────────┐   │
│  <span class="hljs-number">7.</span> ChangeCipherSpec (Client)          │   │
│  (<span class="hljs-number">22</span>:<span class="hljs-number">20</span>:<span class="hljs-number">06.952</span> CET)                    │   │
│  - Switch to encrypted traffic         │   │
└────────────────┬─────────────────────────┐ │
                 │                          │ │
                 │ [Raw write]              │ │
                 │ TLS <span class="hljs-number">1.2</span> change spec      │ │
                 ├──────────────────────────────&gt;
                 │                          │ │
                 ▼                          │ │
┌────────────────────────────────────────┐   │
│  <span class="hljs-number">8.</span> Finished (Client)                  │   │
│  (<span class="hljs-number">22</span>:<span class="hljs-number">20</span>:<span class="hljs-number">06.954</span> CET)                    │   │
│  - MAC <span class="hljs-keyword">of</span> all handshake messages       │   │
│  - Encrypted <span class="hljs-keyword">with</span> session key          │   │
└────────────────┬─────────────────────────┐ │
                 │                          │ │
                 │ [Raw write]              │ │
                 │ TLS <span class="hljs-number">1.2</span> handshake       │ │
                 ├──────────────────────────────&gt;
                 │                          │ │
                 │                          │ │
                 │                   ┌──────┘ │
                 │                   │        │
                 │                   ▼        ▼
                 │        ┌──────────────────────────────┐
                 │        │  <span class="hljs-number">9.</span> NewSessionTicket         │
                 │        │  (<span class="hljs-number">22</span>:<span class="hljs-number">20</span>:<span class="hljs-number">07.056</span> CET)          │
                 │        │  - For session resumption    │
                 │        └────────┬─────────────────────┘
                 │                 │
                 │                 │ [Raw read]
        ┌────────┴─────────────────┤
        │                          │
        ▼                          ▼
┌──────────────────────┐  ┌────────────────────────────┐
│  <span class="hljs-number">10.</span> ChangeCipherSpec│  │  <span class="hljs-number">11.</span> Server Finished       │
│  (Server)            │  │  (<span class="hljs-number">22</span>:<span class="hljs-number">20</span>:<span class="hljs-number">07.056</span> CET)       │
│  (<span class="hljs-number">22</span>:<span class="hljs-number">20</span>:<span class="hljs-number">07.056</span> CET)  │  │  - MAC <span class="hljs-keyword">of</span> all handshake   │
└──────────────────────┘  │  - Encrypted <span class="hljs-keyword">with</span> key     │
                          └────────┬──────────────────┘
                                   │
                                   │ [Raw read]
                    ┌──────────────┘
                    │
                    ▼
        ┌───────────────────────────────┐
        │  ✓ HANDSHAKE COMPLETE        │
        │  (<span class="hljs-number">22</span>:<span class="hljs-number">20</span>:<span class="hljs-number">07.057</span> CET)          │
        │                              │
        │  Secure Channel Established  │
        │  - Ready <span class="hljs-keyword">for</span> application     │
        │  - All data encrypted/MAC<span class="hljs-string">'d  │
        └───────────────────────────────┘</span>
</code></pre><h3 id="heading-handshake-timing-amp-summary">Handshake Timing &amp; Summary</h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Step</td><td>Message Type</td><td>Direction</td><td>Timestamp</td><td>Duration</td></tr>
</thead>
<tbody>
<tr>
<td>1</td><td>ClientHello</td><td>Client → Server</td><td>22:20:06.819</td><td>-</td></tr>
<tr>
<td>2</td><td>ServerHello</td><td>Server → Client</td><td>22:20:06.924</td><td>+105ms</td></tr>
<tr>
<td>3</td><td>Certificate</td><td>Server → Client</td><td>22:20:06.930</td><td>+6ms</td></tr>
<tr>
<td>4</td><td>ServerKeyExchange</td><td>Server → Client</td><td>22:20:06.950</td><td>+20ms</td></tr>
<tr>
<td>5</td><td>ServerHelloDone</td><td>Server → Client</td><td>22:20:06.951</td><td>+1ms</td></tr>
<tr>
<td>6</td><td>ClientKeyExchange</td><td>Client → Server</td><td>22:20:06.951</td><td>-</td></tr>
<tr>
<td>7</td><td>ChangeCipherSpec</td><td>Client → Server</td><td>22:20:06.952</td><td>+1ms</td></tr>
<tr>
<td>8</td><td>Finished</td><td>Client → Server</td><td>22:20:06.954</td><td>+2ms</td></tr>
<tr>
<td>9</td><td>NewSessionTicket</td><td>Server → Client</td><td>22:20:07.056</td><td>+102ms</td></tr>
<tr>
<td>10</td><td>ChangeCipherSpec</td><td>Server → Client</td><td>22:20:07.056</td><td>-</td></tr>
<tr>
<td>11</td><td>Finished</td><td>Server → Client</td><td>22:20:07.056</td><td>-</td></tr>
<tr>
<td><strong>Total Duration</strong></td><td></td><td></td><td><strong>22:20:07.057</strong></td><td><strong>~238ms</strong></td></tr>
</tbody>
</table>
</div><h3 id="heading-negotiated-security-parameters">Negotiated Security Parameters</h3>
<ul>
<li><strong>Protocol Version</strong>: TLS 1.2</li>
<li><strong>Cipher Suite</strong>: <code>TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256</code> (0xC02F)</li>
<li><strong>Key Exchange</strong>: ECDHE (Elliptic Curve Diffie-Hellman Ephemeral)</li>
<li><strong>Encryption</strong>: AES-128-GCM</li>
<li><strong>Hash Algorithm</strong>: SHA256</li>
<li><strong>Server Certificate</strong>: httpbin.org (issued by Amazon RSA 2048 M)</li>
</ul>
<h3 id="heading-negotiated-extensions">Negotiated Extensions</h3>
<ul>
<li>✓ <code>renegotiation_info</code> - Controls renegotiation</li>
<li>✓ <code>server_name</code> - SNI (Server Name Indication)</li>
<li>✓ <code>ec_point_formats</code> - Supported EC point formats (uncompressed)</li>
<li>✓ <code>extended_master_secret</code> - Enhanced security</li>
<li>✓ <code>session_ticket</code> - Session resumption capability</li>
</ul>
<hr />
<h2 id="heading-handshake-phase-breakdown">Handshake Phase Breakdown</h2>
<h3 id="heading-phase-1-key-exchange-amp-authentication">Phase 1: Key Exchange &amp; Authentication</h3>
<p>The client and server exchange their capabilities and parameters:</p>
<ol>
<li><strong>ClientHello</strong> → Client offers supported ciphers, TLS versions, and extensions</li>
<li><strong>ServerHello</strong> → Server selects cipher, version, and confirms capabilities</li>
<li><strong>Certificate</strong> → Server proves identity with certificate chain</li>
<li><strong>ServerKeyExchange</strong> → Server sends ECDH parameters for key agreement</li>
<li><strong>ServerHelloDone</strong> → Marks end of server's initial messages</li>
</ol>
<h3 id="heading-phase-2-key-derivation">Phase 2: Key Derivation</h3>
<p>Both sides generate the shared secret:</p>
<ol start="6">
<li><strong>ClientKeyExchange</strong> → Client sends ECDH public key<ul>
<li>Both sides compute: <code>PreMasterSecret = ECDH(client_key, server_key)</code></li>
<li>Both derive: <code>MasterSecret = PRF(PreMasterSecret, "master secret", client_random || server_random)</code></li>
<li>Both generate session encryption/decryption keys</li>
</ul>
</li>
</ol>
<h3 id="heading-phase-3-cipher-activation-amp-verification">Phase 3: Cipher Activation &amp; Verification</h3>
<p>Both sides verify the handshake and activate encryption:</p>
<ol start="7">
<li><strong>ChangeCipherSpec (Client)</strong> → "Start encrypting from now on"</li>
<li><strong>Finished (Client)</strong> → Encrypted MAC of all handshake messages</li>
<li><strong>NewSessionTicket (Server)</strong> → Optional ticket for future session resumption</li>
<li><strong>ChangeCipherSpec (Server)</strong> → "Start encrypting from now on"</li>
<li><strong>Finished (Server)</strong> → Encrypted MAC of all handshake messages</li>
</ol>
<h3 id="heading-phase-4-secure-communication">Phase 4: Secure Communication</h3>
<p>Application data is now encrypted using the derived session keys.</p>
<hr />
<h2 id="heading-complete-working-example">Complete Working Example</h2>
<p>Here's the complete Java code that produces the above handshake:</p>
<h3 id="heading-appjava-main-application">App.java - Main Application</h3>
<pre><code class="lang-java"><span class="hljs-comment">/*
 * This source file was generated by the Gradle 'init' task
 */</span>
<span class="hljs-keyword">package</span> ssl.debug;

<span class="hljs-keyword">import</span> ssl.debug.adapter.BasicHttpsClient;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">App</span> </span>{

    BasicHttpsClient basicHttpsClient = <span class="hljs-keyword">new</span> BasicHttpsClient();

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getGreeting</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> Exception </span>{
        <span class="hljs-keyword">return</span> basicHttpsClient.get(<span class="hljs-string">"https://httpbin.org/get"</span>);
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getSslInfo</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> Exception </span>{
        <span class="hljs-keyword">return</span> basicHttpsClient.getSSLInfo(<span class="hljs-string">"https://httpbin.org/get"</span>);
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> Exception </span>{
        System.setProperty(<span class="hljs-string">"javax.net.debug"</span>, <span class="hljs-string">"all"</span>);
        App app = <span class="hljs-keyword">new</span> App();
        System.out.println(app.getGreeting());
        System.out.println(app.getSslInfo());
    }
}
</code></pre>
<h3 id="heading-basichttpsclientjava-https-client-library">BasicHttpsClient.java - HTTPS Client Library</h3>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> ssl.debug.adapter;

<span class="hljs-keyword">import</span> java.io.BufferedReader;
<span class="hljs-keyword">import</span> java.io.InputStreamReader;
<span class="hljs-keyword">import</span> java.net.HttpURLConnection;
<span class="hljs-keyword">import</span> java.net.URI;
<span class="hljs-keyword">import</span> java.net.URL;
<span class="hljs-keyword">import</span> java.nio.charset.StandardCharsets;
<span class="hljs-keyword">import</span> java.util.List;
<span class="hljs-keyword">import</span> java.util.Map;

<span class="hljs-comment">/**
 * A simple HTTPS client for making secure HTTP requests.
 * Useful for demonstrating SSL/TLS handshake and debugging.
 */</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BasicHttpsClient</span> </span>{

    <span class="hljs-keyword">private</span> String userAgent = <span class="hljs-string">"Mozilla/5.0 (Java SSL Debug)"</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> connectionTimeout = <span class="hljs-number">10000</span>; <span class="hljs-comment">// 10 seconds</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> readTimeout = <span class="hljs-number">10000</span>; <span class="hljs-comment">// 10 seconds</span>

    <span class="hljs-comment">/**
     * Performs a GET request to the specified URL
     * 
     * <span class="hljs-doctag">@param</span> urlString The HTTPS URL to connect to
     * <span class="hljs-doctag">@return</span> The response body as a string
     * <span class="hljs-doctag">@throws</span> Exception if connection fails
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">get</span><span class="hljs-params">(String urlString)</span> <span class="hljs-keyword">throws</span> Exception </span>{
        <span class="hljs-keyword">return</span> get(urlString, <span class="hljs-keyword">null</span>);
    }

    <span class="hljs-comment">/**
     * Performs a GET request with custom headers
     * 
     * <span class="hljs-doctag">@param</span> urlString The HTTPS URL to connect to
     * <span class="hljs-doctag">@param</span> headers Custom headers to send (can be null)
     * <span class="hljs-doctag">@return</span> The response body as a string
     * <span class="hljs-doctag">@throws</span> Exception if connection fails
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">get</span><span class="hljs-params">(String urlString, Map&lt;String, String&gt; headers)</span> <span class="hljs-keyword">throws</span> Exception </span>{
        HttpURLConnection connection = <span class="hljs-keyword">null</span>;
        <span class="hljs-keyword">try</span> {
            URL url = <span class="hljs-keyword">new</span> URI(urlString).toURL();
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod(<span class="hljs-string">"GET"</span>);
            connection.setConnectTimeout(connectionTimeout);
            connection.setReadTimeout(readTimeout);
            connection.setRequestProperty(<span class="hljs-string">"User-Agent"</span>, userAgent);

            <span class="hljs-comment">// Add custom headers if provided</span>
            <span class="hljs-keyword">if</span> (headers != <span class="hljs-keyword">null</span>) {
                headers.forEach(connection::setRequestProperty);
            }

            <span class="hljs-keyword">int</span> responseCode = connection.getResponseCode();
            String responseBody = readResponse(connection);

            System.out.println(<span class="hljs-string">"Status Code: "</span> + responseCode);
            System.out.println(<span class="hljs-string">"Response Headers:"</span>);
            printHeaders(connection.getHeaderFields());

            <span class="hljs-keyword">return</span> responseBody;

        } <span class="hljs-keyword">finally</span> {
            <span class="hljs-keyword">if</span> (connection != <span class="hljs-keyword">null</span>) {
                connection.disconnect();
            }
        }
    }

    <span class="hljs-comment">/**
     * Gets SSL/TLS information from the connection
     * 
     * <span class="hljs-doctag">@param</span> urlString The HTTPS URL to connect to
     * <span class="hljs-doctag">@return</span> SSL information as a formatted string
     * <span class="hljs-doctag">@throws</span> Exception if connection fails
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getSSLInfo</span><span class="hljs-params">(String urlString)</span> <span class="hljs-keyword">throws</span> Exception </span>{
        HttpURLConnection connection = <span class="hljs-keyword">null</span>;
        <span class="hljs-keyword">try</span> {
            URL url = <span class="hljs-keyword">new</span> URI(urlString).toURL();
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod(<span class="hljs-string">"HEAD"</span>);
            connection.setConnectTimeout(connectionTimeout);
            connection.setReadTimeout(readTimeout);

            <span class="hljs-comment">// Trigger connection to perform SSL handshake</span>
            connection.getResponseCode();

            StringBuilder info = <span class="hljs-keyword">new</span> StringBuilder();
            info.append(<span class="hljs-string">"=== SSL/TLS Information ===\n"</span>);
            info.append(<span class="hljs-string">"URL: "</span>).append(urlString).append(<span class="hljs-string">"\n"</span>);
            info.append(<span class="hljs-string">"Status Code: "</span>).append(connection.getResponseCode()).append(<span class="hljs-string">"\n"</span>);
            info.append(<span class="hljs-string">"Content Type: "</span>).append(connection.getContentType()).append(<span class="hljs-string">"\n"</span>);

            <span class="hljs-comment">// Get cipher suite if available (only on HTTPS)</span>
            <span class="hljs-keyword">if</span> (connection <span class="hljs-keyword">instanceof</span> javax.net.ssl.HttpsURLConnection httpsConnection) {
                httpsConnection.connect();
                info.append(<span class="hljs-string">"Cipher Suite: "</span>).append(httpsConnection.getCipherSuite()).append(<span class="hljs-string">"\n"</span>);
                <span class="hljs-keyword">var</span> sslSession = httpsConnection.getSSLSession();
                <span class="hljs-keyword">if</span> (sslSession.isPresent()) {
                    info.append(<span class="hljs-string">"Protocol: "</span>).append(sslSession.get().getProtocol()).append(<span class="hljs-string">"\n"</span>);
                }
            }

            <span class="hljs-keyword">return</span> info.toString();

        } <span class="hljs-keyword">finally</span> {
            <span class="hljs-keyword">if</span> (connection != <span class="hljs-keyword">null</span>) {
                connection.disconnect();
            }
        }
    }

    <span class="hljs-comment">/**
     * Reads the response body from the connection
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">private</span> String <span class="hljs-title">readResponse</span><span class="hljs-params">(HttpURLConnection connection)</span> <span class="hljs-keyword">throws</span> Exception </span>{
        StringBuilder response = <span class="hljs-keyword">new</span> StringBuilder();
        <span class="hljs-keyword">try</span> (BufferedReader reader = <span class="hljs-keyword">new</span> BufferedReader(
                <span class="hljs-keyword">new</span> InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
            String line;
            <span class="hljs-keyword">while</span> ((line = reader.readLine()) != <span class="hljs-keyword">null</span>) {
                response.append(line).append(<span class="hljs-string">"\n"</span>);
            }
        }
        <span class="hljs-keyword">return</span> response.toString();
    }

    <span class="hljs-comment">/**
     * Prints response headers
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">printHeaders</span><span class="hljs-params">(Map&lt;String, List&lt;String&gt;&gt; headers)</span> </span>{
        headers.forEach((key, values) -&gt; {
            <span class="hljs-keyword">if</span> (key != <span class="hljs-keyword">null</span>) { <span class="hljs-comment">// null key is the status line</span>
                values.forEach(value -&gt; System.out.println(<span class="hljs-string">"  "</span> + key + <span class="hljs-string">": "</span> + value));
            }
        });
    }

    <span class="hljs-comment">/**
     * Sets the connection timeout
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setConnectionTimeout</span><span class="hljs-params">(<span class="hljs-keyword">int</span> timeout)</span> </span>{
        <span class="hljs-keyword">this</span>.connectionTimeout = timeout;
    }

    <span class="hljs-comment">/**
     * Sets the read timeout
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setReadTimeout</span><span class="hljs-params">(<span class="hljs-keyword">int</span> timeout)</span> </span>{
        <span class="hljs-keyword">this</span>.readTimeout = timeout;
    }

    <span class="hljs-comment">/**
     * Sets the User-Agent header
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setUserAgent</span><span class="hljs-params">(String userAgent)</span> </span>{
        <span class="hljs-keyword">this</span>.userAgent = userAgent;
    }
}
</code></pre>
<hr />
<h2 id="heading-how-to-run-the-example">How to Run the Example</h2>
<h3 id="heading-prerequisites">Prerequisites</h3>
<ul>
<li>Java 21+ (or JDK 17+ minimum)</li>
<li>Gradle 8.x</li>
</ul>
<h3 id="heading-steps">Steps</h3>
<ol>
<li><p><strong>Clone or download the project</strong>:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> ssl-debug
</code></pre>
</li>
<li><p><strong>Build the project</strong>:</p>
<pre><code class="lang-bash">./gradlew build
</code></pre>
</li>
<li><p><strong>Run with SSL debugging enabled</strong>:</p>
<pre><code class="lang-bash">./gradlew run
</code></pre>
</li>
<li><p><strong>Capture output to file</strong>:</p>
<pre><code class="lang-bash">./gradlew run &gt; all.log 2&gt;&amp;1
</code></pre>
</li>
</ol>
<p>The application will:</p>
<ul>
<li>Enable <code>javax.net.debug=all</code></li>
<li>Make a GET request to <code>https://httpbin.org/get</code></li>
<li>Log all TLS handshake messages</li>
<li>Display SSL/TLS information (cipher suite, protocol version, etc.)</li>
</ul>
<hr />
<h2 id="heading-key-insights-from-the-handshake">Key Insights from the Handshake</h2>
<h3 id="heading-certificate-chain-validation">Certificate Chain Validation</h3>
<p>The SSL/TLS debug output shows the server provided three certificates:</p>
<ol>
<li><strong>End-Entity Certificate</strong>: httpbin.org (issued by Amazon RSA 2048 M CA)</li>
<li><strong>Intermediate CA</strong>: Amazon RSA 2048 M</li>
<li><strong>Root CA</strong>: Amazon Root CA (trusted in system trust store)</li>
</ol>
<p>The JVM validates this chain by:</p>
<ul>
<li>Loading 152 trusted CA certificates from <code>cacerts</code></li>
<li>Verifying each certificate's signature against its issuer</li>
<li>Checking validity dates</li>
<li>Confirming key usage extensions</li>
</ul>
<h3 id="heading-cipher-suite-selection">Cipher Suite Selection</h3>
<p>The server chose <code>TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256</code> because it's:</p>
<ul>
<li><strong>Secure</strong>: Modern encryption standard</li>
<li><strong>Forward-Secure</strong>: Uses ephemeral ECDH keys (PFS)</li>
<li><strong>Authenticated</strong>: RSA signature verification</li>
<li><strong>Authenticated Encryption</strong>: AES-GCM prevents tampering</li>
</ul>
<h3 id="heading-key-exchange-details">Key Exchange Details</h3>
<ul>
<li><strong>Algorithm</strong>: ECDHE (Elliptic Curve Diffie-Hellman Ephemeral)</li>
<li><strong>Benefits</strong>: <ul>
<li>Perfect Forward Secrecy (PFS) - past sessions are safe even if long-term keys are compromised</li>
<li>Faster than traditional DHE</li>
<li>Smaller key sizes with equivalent security</li>
</ul>
</li>
</ul>
<hr />
<h2 id="heading-common-ssltls-debugging-scenarios">Common SSL/TLS Debugging Scenarios</h2>
<h3 id="heading-debug-level-options">Debug Level Options</h3>
<pre><code class="lang-java"><span class="hljs-comment">// Full debug (as shown in this guide)</span>
System.setProperty(<span class="hljs-string">"javax.net.debug"</span>, <span class="hljs-string">"all"</span>);

<span class="hljs-comment">// Specific areas only</span>
System.setProperty(<span class="hljs-string">"javax.net.debug"</span>, <span class="hljs-string">"ssl"</span>);           <span class="hljs-comment">// SSL records</span>
System.setProperty(<span class="hljs-string">"javax.net.debug"</span>, <span class="hljs-string">"ssl:handshake"</span>); <span class="hljs-comment">// Handshake only</span>
System.setProperty(<span class="hljs-string">"javax.net.debug"</span>, <span class="hljs-string">"ssl:trustmanager"</span>); <span class="hljs-comment">// Certificate validation</span>
System.setProperty(<span class="hljs-string">"javax.net.debug"</span>, <span class="hljs-string">"ssl:record"</span>);    <span class="hljs-comment">// Record layer details</span>
</code></pre>
<h3 id="heading-troubleshooting-common-issues">Troubleshooting Common Issues</h3>
<p><strong>Issue</strong>: <code>PKIX path building failed</code></p>
<ul>
<li><strong>Cause</strong>: Certificate not in trust store</li>
<li><strong>Solution</strong>: Import certificate or use custom TrustManager</li>
</ul>
<p><strong>Issue</strong>: <code>Unsupported or unrecognized SSL message</code></p>
<ul>
<li><strong>Cause</strong>: Connecting to non-HTTPS endpoint</li>
<li><strong>Solution</strong>: Verify URL starts with <code>https://</code></li>
</ul>
<p><strong>Issue</strong>: <code>Excessive network latency</code></p>
<ul>
<li><strong>Cause</strong>: Certificate revocation checks (OCSP, CRL)</li>
<li><strong>Solution</strong>: Disable revocation checks if acceptable for your use case</li>
</ul>
<hr />
<h2 id="heading-conclusion">Conclusion</h2>
<p>Understanding TLS/TLS handshakes is essential for:</p>
<ul>
<li><strong>Debugging</strong>: Identifying connection issues quickly</li>
<li><strong>Security</strong>: Understanding what's being negotiated</li>
<li><strong>Performance</strong>: Analyzing handshake overhead</li>
<li><strong>Compliance</strong>: Verifying secure cipher suites are used</li>
</ul>
<p>The <code>javax.net.debug</code> system property provides deep visibility into Java's SSL/TLS layer, making it invaluable for developers working with secure connections.</p>
<p><strong>Remember</strong>: The SSL/TLS logs contain sensitive handshake information. Only enable debugging in development environments, never in production without careful security considerations.</p>
<hr />
<h2 id="heading-resources">Resources</h2>
<ul>
<li><a target="_blank" href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html">Java JSSE Documentation</a></li>
<li><a target="_blank" href="https://tools.ietf.org/html/rfc5246">RFC 5246 - TLS 1.2</a></li>
<li><a target="_blank" href="https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Protection_Cheat_Sheet.html">OWASP Transport Layer Protection</a></li>
<li><a target="_blank" href="https://httpbin.org/">httpbin.org</a> - HTTP Request/Response Service</li>
</ul>
<hr />
<h2 id="heading-get-the-code">Get the Code</h2>
<p>The source code for this project is available on GitHub:</p>
<p><strong>📚 <a target="_blank" href="https://github.com/mnafshin/ssl-debug">github.com/mnafshin/ssl-debug</a></strong></p>
<p>Feel free to fork, clone, and experiment with the examples to deepen your understanding of SSL/TLS handshakes!</p>
]]></content:encoded></item></channel></rss>