<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Travis Haagen&#x27;s Blog</title>
    <subtitle>Travis Haagen&#x27;s blog for Software Engineers</subtitle>
    <link rel="self" type="application/atom+xml" href="https://travishaagen.github.io/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://travishaagen.github.io"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-01-16T00:00:00+00:00</updated>
    <id>https://travishaagen.github.io/atom.xml</id>
    <entry xml:lang="en">
        <title>Backpressure in Client-Server Applications</title>
        <published>2026-01-16T00:00:00+00:00</published>
        <updated>2026-01-16T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://travishaagen.github.io/posts/backpressure-in-client-server-applications/"/>
        <id>https://travishaagen.github.io/posts/backpressure-in-client-server-applications/</id>
        
        <content type="html" xml:base="https://travishaagen.github.io/posts/backpressure-in-client-server-applications/">&lt;p&gt;Backpressure, in client-server applications, is accomplished when a client adjusts its transmission of
messages in response to a server that has slowed its processing of messages.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;stuck-in-traffic&quot;&gt;Stuck in Traffic&lt;&#x2F;h2&gt;
&lt;p&gt;Ideally, when a networked client connects to a server, messages are sent at maximum speed and responses are likewise
returned quickly. To handle more client traffic we scale horizontally by adding additional server instances and
our long-tail latency metrics are stable over time. However, in most real world applications the server is not a
monolith unto itself and will make internal requests to relational databases and external APIs with unpredictable
performance characteristics.&lt;&#x2F;p&gt;
&lt;p&gt;Timeouts are essential for achieving resiliency. When a timeout is reached, the client disconnects and potentially
tries again until it gives up. The absence of sensible timeouts results in resource consumption (e.g., network sockets,
memory, threads) and conditions resembling a traffic jam. In a healthy system both the client and server will monitor
connections and proactively timeout.&lt;&#x2F;p&gt;
&lt;p&gt;Constantly connecting and disconnecting, in the face of server instability, has a cost. On average, it takes longer to
establish a network connection, and negotiate a secure socket, than to issue requests and responses. An
alternative is for the client to respond to &lt;em&gt;backpressure&lt;&#x2F;em&gt; from the server by keeping the connection open and only
sending data when the server is ready to accept it. Instead of a chaotic traffic jam, the stream of messages is like a
cargo train, with slow-downs anticipated.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;backpressure&quot;&gt;Backpressure&lt;&#x2F;h2&gt;
&lt;p&gt;The Transmission Control Protocol (TCP) considers backpressure as part of the specification.
“&lt;a href=&quot;https:&#x2F;&#x2F;sumofbytes.com&#x2F;blog&#x2F;understanding-tcp-protocol-and-backpressure&#x2F;&quot;&gt;Understanding TCP Protocol and Backpressure&lt;&#x2F;a&gt;
”¹ does a nice job summarizing the key ideas.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;TCP implements flow control to ensure that the sender does not overwhelm the receiver with data. It uses a sliding
window mechanism to control the number of unacknowledged segments that can be sent at a time.&lt;&#x2F;li&gt;
&lt;li&gt;The receiver advertises its window size, indicating the amount of data it can currently accept.&lt;&#x2F;li&gt;
&lt;li&gt;The sender adjusts the rate of transmission based on the receiver’s window size, ensuring efficient data transfer.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;In practice, for backpressure to work effectively, both the client and the server should adhere to some specific design
principles:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Client &amp;amp; Server
&lt;ul&gt;
&lt;li&gt;Connection should be long-lived (e.g., HTTP keep-alive, websocket, etc.)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Client
&lt;ul&gt;
&lt;li&gt;Networking libraries should indicate when the socket is &lt;em&gt;writable&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Timeouts should be tuned to allow for backpressure&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Server
&lt;ul&gt;
&lt;li&gt;Separate thread-pools should handle,
&lt;ul&gt;
&lt;li&gt;Accepting network connections&lt;&#x2F;li&gt;
&lt;li&gt;Sending and receiving data over established connections&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Slow or idle clients should be detected and pruned&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Let us consider an asynchronous, event-driven application architecture. On the server a single thread can effectively
handle the job of accepting network connections. Once connected, another thread, or pool of threads, can read requests
and send responses. These &quot;worker threads&quot; must take care not block on I&#x2F;O or mutexes. We read the request data, make
asynchronous calls to internal services, and during those asynchronous calls our worker threads may service other
requests. Once our asynchronous work is complete, and if the client is still connected, we write a response. This
&lt;em&gt;could&lt;&#x2F;em&gt; be backpressure at work, but how can we know for certain? Unfortunately, most of us use software frameworks
that make it difficult to know what is going on beneath the surface.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;an-experiment&quot;&gt;An Experiment&lt;&#x2F;h1&gt;
&lt;p&gt;For this article we created a project at
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;travishaagen&#x2F;blog-backpressure&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;travishaagen&#x2F;blog-backpressure&lt;&#x2F;a&gt;. It&#x27;s only
dependency is &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;netty&#x2F;netty&quot;&gt;Netty&lt;&#x2F;a&gt;, which is an event-driven abstraction over Java&#x27;s internal
sockets and byte buffers. To prove to ourselves that backpressure is occurring, the application establishes a
single websocket connection. The client has a Netty event-loop with a single thread.
Likewise, the server has a single-threaded connection acceptor and a single threaded worker-pool, which attempts to
write to a bounded queue of size 1. A consumer thread reads from the bounded queue at a slow rate. When the queue
is full, we cannot write to it, so we stop reading data. When we stop reading, the client is informed that
the server cannot accept more data, which causes the client to stop writing. This is backpressure.&lt;&#x2F;p&gt;




&lt;img alt=&quot;Client-Server Diagram&quot; title=&quot;Client-Server Diagram&quot; src=&quot;https:&#x2F;&#x2F;travishaagen.github.io&#x2F;processed_images&#x2F;client_server_diagram.339956e9a780a34d.png&quot; srcset=&quot;https:&#x2F;&#x2F;travishaagen.github.io&#x2F;processed_images&#x2F;client_server_diagram.b7fdc2d9cd905bf0.png 512w, https:&#x2F;&#x2F;travishaagen.github.io&#x2F;processed_images&#x2F;client_server_diagram.339956e9a780a34d.png 1024w, https:&#x2F;&#x2F;travishaagen.github.io&#x2F;processed_images&#x2F;client_server_diagram.1b5220834e6f7005.png 2048w&quot; class=&quot;&quot; &#x2F;&gt;

&lt;p&gt;Every network connection establishes a
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;netty&#x2F;netty&#x2F;blob&#x2F;4.2&#x2F;transport&#x2F;src&#x2F;main&#x2F;java&#x2F;io&#x2F;netty&#x2F;channel&#x2F;Channel.java&quot;&gt;Channel&lt;&#x2F;a&gt;. A &lt;code&gt;Channel&lt;&#x2F;code&gt;
has a method called &lt;code&gt;isWritable()&lt;&#x2F;code&gt; with the following documentation,&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Returns &lt;code&gt;true&lt;&#x2F;code&gt; if and only if the I&#x2F;O thread will perform the requested write operation immediately. Any write
requests made when this method returns &lt;code&gt;false&lt;&#x2F;code&gt; are queued until the I&#x2F;O thread is ready to process the queued write
requests.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;netty&#x2F;netty&#x2F;blob&#x2F;4.2&#x2F;transport&#x2F;src&#x2F;main&#x2F;java&#x2F;io&#x2F;netty&#x2F;channel&#x2F;WriteBufferWaterMark.java&quot;&gt;WriteBufferWaterMark&lt;&#x2F;a&gt;
can be used to configure on which condition the write buffer would cause this channel to change writability.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;In our &lt;code&gt;WebSocketClient&lt;&#x2F;code&gt; you can see that, in a loop, we increment a 64-bit integer and only write it to the channel
when writable. The client is detecting and adapting to a full write buffer.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;text&quot; class=&quot;language-text z-code&quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;while (!group.isShuttingDown()) {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    &#x2F;&#x2F; will not write, when the write buffer watermark is full
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    if (ch.isWritable()) {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        var buf = allocator.buffer(Long.BYTES, Long.BYTES);
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        buf.writeLong(writeCounter++);
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        var frame = new BinaryWebSocketFrame(buf);
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        ch.writeAndFlush(frame);
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    } else {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        &#x2F;&#x2F; we&amp;#39;re in a spin-loop, so yield to other threads
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        Thread.yield();
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On the server, to control our experiment, we create a bounded queue of size 1.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;text&quot; class=&quot;language-text z-code&quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;var consumerQueue = new LinkedBlockingQueue&amp;lt;Long&amp;gt;(1);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We then pass the queue to a &quot;consumer thread&quot; which reads from it at a slow pace, to simulate a backlog
of work.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;text&quot; class=&quot;language-text z-code&quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;while (true) {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    var value = consumerQueue.take();
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    &#x2F;&#x2F; simulate consuming the queue more slowly than the incoming event rate
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    Thread.sleep(0, 250_000);
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We also pass the queue to our &lt;code&gt;WebSocketFrameHandler&lt;&#x2F;code&gt;. It reads from the &lt;code&gt;Channel&lt;&#x2F;code&gt; and will spin in a loop
until it can write to the queue. It does not perform any additional reads until the data is written, which causes
backpressure.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;text&quot; class=&quot;language-text z-code&quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;var msg = frame.content().readLong();
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;if (!consumerQueue.offer(msg)) {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    while (!consumerQueue.offer(msg)) {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        &#x2F;&#x2F; yield to other threads while we try to write to the bounded queue
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        Thread.yield();
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When we run the application we&#x27;ll see an output similar to the following. The &lt;code&gt;Wrote&lt;&#x2F;code&gt; lines show the number of messages
written to the socket and &lt;code&gt;Consumed&lt;&#x2F;code&gt; shows the count of messages read by the server&#x27;s &quot;consumer thread&quot;.
Note that, to save space, only the last consecutive &lt;code&gt;Wrote&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;Consumed&lt;&#x2F;code&gt; lines are shown below.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell z-code&quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;% .&#x2F;gradlew runApp
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;gt; Task :runApp
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Consumed:       0
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Wrote:          100000
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Consumed:       60000
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Wrote:          120000
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Consumed:       85000
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Wrote:          150000
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Consumed:       105000
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Wrote:          170000
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Consumed:       125000
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Wrote:          190000
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When we observe the &lt;code&gt;loopback&lt;&#x2F;code&gt; interface in &lt;a href=&quot;https:&#x2F;&#x2F;www.wireshark.org&quot;&gt;Wireshark&lt;&#x2F;a&gt; and set the filter to
&lt;code&gt;tcp.window_size == 0&lt;&#x2F;code&gt; we see that the TCP window drops to zero multiple times. This is what causes the client to stop
writing.&lt;&#x2F;p&gt;




&lt;img alt=&quot;Wireshark Screenshot&quot; title=&quot;Wireshark Screenshot&quot; src=&quot;https:&#x2F;&#x2F;travishaagen.github.io&#x2F;processed_images&#x2F;wireshark_tcp_window_size_zero.df35da8e7a9c83e9.jpg&quot; srcset=&quot;https:&#x2F;&#x2F;travishaagen.github.io&#x2F;processed_images&#x2F;wireshark_tcp_window_size_zero.3515e21f7a266d38.jpg 512w, https:&#x2F;&#x2F;travishaagen.github.io&#x2F;processed_images&#x2F;wireshark_tcp_window_size_zero.df35da8e7a9c83e9.jpg 1024w, https:&#x2F;&#x2F;travishaagen.github.io&#x2F;processed_images&#x2F;wireshark_tcp_window_size_zero.55e833d656a7b867.jpg 2048w&quot; class=&quot;&quot; &#x2F;&gt;

&lt;h2 id=&quot;final-thoughts&quot;&gt;Final Thoughts&lt;&#x2F;h2&gt;
&lt;p&gt;Backpressure is an elegant concept in computer networking. As the above experiment shows, both the client and
server need to actively control reading and writing socket data for it to work properly. Websockets seem particularly
well suited to applications that seek to control backpressure, because it&#x27;s easy to conceive of inbound messages
feeding into one queue and outbound messages into another. We hope that this discussion will assist developers in
thinking about backpressure and how well their libraries and frameworks support it.&lt;&#x2F;p&gt;
&lt;p&gt;For further reading we suggest
“&lt;a href=&quot;https:&#x2F;&#x2F;mechanical-sympathy.blogspot.com&#x2F;2012&#x2F;05&#x2F;apply-back-pressure-when-overloaded.html&quot;&gt;Applying Back Pressure When Overloaded&lt;&#x2F;a&gt;
”² by Martin Thompson.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;Kumar, A. (2023, August 6). Understanding TCP Protocol and Backpressure. Sum Of Bytes.
&lt;a href=&quot;https:&#x2F;&#x2F;sumofbytes.com&#x2F;blog&#x2F;understanding-tcp-protocol-and-backpressure&#x2F;&quot;&gt;https:&#x2F;&#x2F;sumofbytes.com&#x2F;blog&#x2F;understanding-tcp-protocol-and-backpressure&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Thompson, M. (2012, May 19). Applying Back Pressure When Overloaded. Mechanical Sympathy.
&lt;a href=&quot;https:&#x2F;&#x2F;mechanical-sympathy.blogspot.com&#x2F;2012&#x2F;05&#x2F;apply-back-pressure-when-overloaded.html&quot;&gt;https:&#x2F;&#x2F;mechanical-sympathy.blogspot.com&#x2F;2012&#x2F;05&#x2F;apply-back-pressure-when-overloaded.html&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Static Exceptions for Flow Control</title>
        <published>2026-01-02T00:00:00+00:00</published>
        <updated>2026-01-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://travishaagen.github.io/posts/static-exceptions-for-flow-control/"/>
        <id>https://travishaagen.github.io/posts/static-exceptions-for-flow-control/</id>
        
        <content type="html" xml:base="https://travishaagen.github.io/posts/static-exceptions-for-flow-control/">&lt;p&gt;Static Exceptions, when used for flow control, can dramatically reduce garbage generation and latency in Java and Kotlin
applications.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tl-dr&quot;&gt;TL;DR&lt;&#x2F;h2&gt;
&lt;p&gt;To create high performance exceptions for flow control in the JVM, simply extend the following &lt;code&gt;StaticException&lt;&#x2F;code&gt; class.
Then store the &lt;code&gt;Exception&lt;&#x2F;code&gt; instance in a &lt;code&gt;static final&lt;&#x2F;code&gt; field and throw it as needed. They&#x27;re fast, because the call
stack doesn&#x27;t need to be traversed and since we&#x27;re creating reusable objects, there&#x27;s less for the garbage collector
to do.&lt;&#x2F;p&gt;
&lt;p&gt;Java:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;java&quot; class=&quot;language-java z-code&quot;&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-java&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-java&quot;&gt;public&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-modifier z-java&quot;&gt;abstract&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-class z-identifier z-java&quot;&gt;&lt;span class=&quot;z-storage z-type z-java&quot;&gt;class&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-class z-java&quot;&gt;StaticException&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-class z-extends z-java&quot;&gt;&lt;span class=&quot;z-keyword z-declaration z-extends z-java&quot;&gt;extends&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-inherited-class z-java&quot;&gt;RuntimeException&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-class z-body z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-java&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-body z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-body z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    &lt;span class=&quot;z-storage z-modifier z-java&quot;&gt;private&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-modifier z-java&quot;&gt;static&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-modifier z-java&quot;&gt;final&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-class z-java&quot;&gt;StackTraceElement&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-array z-java&quot;&gt;[]&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-field z-java&quot;&gt;emptyStackTrace&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-assignment z-rhs z-java&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-java&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-instantiation z-java&quot;&gt;&lt;span class=&quot;z-keyword z-other z-storage z-new z-java&quot;&gt;new&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-class z-java&quot;&gt;StackTraceElement&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brackets z-array-initialization z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-brackets z-begin z-java&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-java&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-brackets z-end z-java&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-java&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-body z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-body z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    &lt;span class=&quot;z-storage z-modifier z-java&quot;&gt;public&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-method z-java&quot;&gt;&lt;span class=&quot;z-meta z-method z-identifier z-java&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-constructor z-java&quot;&gt;StaticException&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-method z-parameters z-java&quot;&gt;&lt;span class=&quot;z-meta z-parens z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-class z-java&quot;&gt;String&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-java&quot;&gt;message&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-method z-java&quot;&gt;&lt;span class=&quot;z-meta z-method z-body z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-java&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-method z-java&quot;&gt;&lt;span class=&quot;z-meta z-method z-body z-java&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-body z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-meta z-method z-java&quot;&gt;&lt;span class=&quot;z-meta z-method z-body z-java&quot;&gt;        &lt;span class=&quot;z-variable z-language z-java&quot;&gt;super&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-parens z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;message&lt;span class=&quot;z-punctuation z-separator z-comma z-java&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-java&quot;&gt;null&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-java&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-java&quot;&gt;false&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-java&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-java&quot;&gt;true&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-java&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-body z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-meta z-method z-java&quot;&gt;&lt;span class=&quot;z-meta z-method z-body z-java&quot;&gt;        &lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;setStackTrace&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;emptyStackTrace&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-java&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-body z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-meta z-method z-java&quot;&gt;&lt;span class=&quot;z-meta z-method z-body z-java&quot;&gt;    &lt;span class=&quot;z-punctuation z-section z-block z-end z-java&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-body z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-body z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    &lt;span class=&quot;z-meta z-annotation z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-annotation z-java&quot;&gt;@&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-annotation z-java&quot;&gt;&lt;span class=&quot;z-meta z-annotation z-identifier z-java&quot;&gt;&lt;span class=&quot;z-variable z-annotation z-java&quot;&gt;Override&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-body z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-meta z-annotation z-java&quot;&gt;&lt;span class=&quot;z-meta z-annotation z-identifier z-java&quot;&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-java&quot;&gt;public&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-modifier z-java&quot;&gt;synchronized&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-class z-java&quot;&gt;Throwable&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-method z-java&quot;&gt;&lt;span class=&quot;z-meta z-method z-identifier z-java&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-java&quot;&gt;fillInStackTrace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-method z-parameters z-java&quot;&gt;&lt;span class=&quot;z-meta z-parens z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-method z-java&quot;&gt;&lt;span class=&quot;z-meta z-method z-body z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-java&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-method z-java&quot;&gt;&lt;span class=&quot;z-meta z-method z-body z-java&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-body z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-meta z-method z-java&quot;&gt;&lt;span class=&quot;z-meta z-method z-body z-java&quot;&gt;        &lt;span class=&quot;z-keyword z-control z-flow z-return z-java&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-language z-java&quot;&gt;this&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-java&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-body z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-meta z-method z-java&quot;&gt;&lt;span class=&quot;z-meta z-method z-body z-java&quot;&gt;    &lt;span class=&quot;z-punctuation z-section z-block z-end z-java&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-body z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-java&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Kotlin:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;kotlin&quot; class=&quot;language-kotlin z-code&quot;&gt;&lt;code class=&quot;language-kotlin&quot; data-lang=&quot;kotlin&quot;&gt;&lt;span class=&quot;z-source z-Kotlin&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-kotlin&quot;&gt;abstract&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-modifier z-kotlin&quot;&gt;class&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-type z-class z-kotlin&quot;&gt;StaticException&lt;&#x2F;span&gt;(
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-Kotlin&quot;&gt;    &lt;span class=&quot;z-variable z-parameter z-function z-kotlin&quot;&gt;message&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-declaration z-kotlin&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-buildin z-kotlin&quot;&gt;String&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-Kotlin&quot;&gt;) &lt;span class=&quot;z-keyword z-operator z-declaration z-kotlin&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-inherited-class z-kotlin&quot;&gt;RuntimeException&lt;&#x2F;span&gt;(message, &lt;span class=&quot;z-constant z-language z-kotlin&quot;&gt;null&lt;&#x2F;span&gt;, &lt;span class=&quot;z-constant z-language z-kotlin&quot;&gt;false&lt;&#x2F;span&gt;, &lt;span class=&quot;z-constant z-language z-kotlin&quot;&gt;true&lt;&#x2F;span&gt;) {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-Kotlin&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-Kotlin&quot;&gt;    &lt;span class=&quot;z-storage z-modifier z-kotlin&quot;&gt;companion &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-kotlin&quot;&gt;object&lt;&#x2F;span&gt; {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-Kotlin&quot;&gt;        &lt;span class=&quot;z-storage z-modifier z-kotlin&quot;&gt;private&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-other z-kotlin&quot;&gt;val&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-variable z-kotlin&quot;&gt;emptyStackTrace&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-kotlin&quot;&gt;=&lt;&#x2F;span&gt; arrayOf&amp;lt;StackTraceElement&amp;gt;()
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-Kotlin&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-Kotlin&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-Kotlin&quot;&gt;    init {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-Kotlin&quot;&gt;        stackTrace &lt;span class=&quot;z-keyword z-operator z-assignment z-kotlin&quot;&gt;=&lt;&#x2F;span&gt; emptyStackTrace
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-Kotlin&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-Kotlin&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-Kotlin&quot;&gt;    &lt;span class=&quot;z-storage z-modifier z-kotlin&quot;&gt;override&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-other z-kotlin&quot;&gt;fun&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-function z-kotlin&quot;&gt;fillInStackTrace&lt;&#x2F;span&gt;()&lt;span class=&quot;z-keyword z-operator z-declaration z-kotlin&quot;&gt;:&lt;&#x2F;span&gt; Throwable {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-Kotlin&quot;&gt;        &lt;span class=&quot;z-keyword z-control z-kotlin&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-kotlin&quot;&gt;this&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-Kotlin&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-Kotlin&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;example-use-case&quot;&gt;Example Use Case&lt;&#x2F;h2&gt;
&lt;p&gt;In a web application, conditions that trigger HTTP error responses can happen anywhere in the call chain. For example,
the client&#x27;s bearer token has expired, so we return &lt;code&gt;401 Unauthorized&lt;&#x2F;code&gt;. A request is malformed, so validation
logic returns &lt;code&gt;400 Bad Request&lt;&#x2F;code&gt;. Likewise, deeper in the call chain, an asynchronous API call times out, so we return
&lt;code&gt;503 Service Unavailable&lt;&#x2F;code&gt;. None of these error conditions are particularly unexpected, and aside from the timeout,
may not even warrant logging.&lt;&#x2F;p&gt;
&lt;p&gt;For JVM applications it can be convenient to throw an exception that signifies &quot;respond with an error&quot;. When the
exception is caught, we build the appropriate HTTP response. An example response exception might be,&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;java&quot; class=&quot;language-java z-code&quot;&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-java&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-java&quot;&gt;public&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-class z-identifier z-java&quot;&gt;&lt;span class=&quot;z-storage z-type z-java&quot;&gt;class&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-class z-java&quot;&gt;ResponseException&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-class z-extends z-java&quot;&gt;&lt;span class=&quot;z-keyword z-declaration z-extends z-java&quot;&gt;extends&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-inherited-class z-java&quot;&gt;RuntimeException&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-class z-body z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-java&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-body z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-body z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    &lt;span class=&quot;z-storage z-modifier z-java&quot;&gt;public&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-modifier z-java&quot;&gt;final&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-primitive z-java&quot;&gt;int&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-field z-java&quot;&gt;statusCode&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-java&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-body z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-body z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    &lt;span class=&quot;z-storage z-modifier z-java&quot;&gt;public&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-method z-java&quot;&gt;&lt;span class=&quot;z-meta z-method z-identifier z-java&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-constructor z-java&quot;&gt;ResponseException&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-method z-parameters z-java&quot;&gt;&lt;span class=&quot;z-meta z-parens z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-class z-java&quot;&gt;String&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-java&quot;&gt;message&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-java&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-primitive z-java&quot;&gt;int&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-java&quot;&gt;statusCode&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-method z-java&quot;&gt;&lt;span class=&quot;z-meta z-method z-body z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-java&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-method z-java&quot;&gt;&lt;span class=&quot;z-meta z-method z-body z-java&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-body z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-meta z-method z-java&quot;&gt;&lt;span class=&quot;z-meta z-method z-body z-java&quot;&gt;        &lt;span class=&quot;z-variable z-language z-java&quot;&gt;super&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-parens z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;message&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-java&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-body z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-meta z-method z-java&quot;&gt;&lt;span class=&quot;z-meta z-method z-body z-java&quot;&gt;        &lt;span class=&quot;z-variable z-language z-java&quot;&gt;this&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;statusCode &lt;span class=&quot;z-meta z-assignment z-rhs z-java&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-java&quot;&gt;=&lt;&#x2F;span&gt; statusCode&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-java&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-body z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-meta z-method z-java&quot;&gt;&lt;span class=&quot;z-meta z-method z-body z-java&quot;&gt;    &lt;span class=&quot;z-punctuation z-section z-block z-end z-java&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-java&quot;&gt;&lt;span class=&quot;z-meta z-class z-body z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-java&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which could be caught in our web controller logic, or a framework mechanism such as a Spring
&lt;a href=&quot;https:&#x2F;&#x2F;docs.spring.io&#x2F;spring-framework&#x2F;reference&#x2F;web&#x2F;webmvc&#x2F;mvc-controller&#x2F;ann-exceptionhandler.html&quot;&gt;@ExceptionHandler&lt;&#x2F;a&gt;,
where the appropriate HTTP response status header and payload body would be constructed,&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;json&quot; class=&quot;language-json z-code&quot;&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-mapping z-begin z-json&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;  &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;code&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-json&quot;&gt;400&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-pair z-json&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;  &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;message&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Bad Request&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-mapping z-end z-json&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;discussion&quot;&gt;Discussion&lt;&#x2F;h2&gt;
&lt;p&gt;We&#x27;re using exceptions for &lt;em&gt;flow control&lt;&#x2F;em&gt;. Unfortunately, from a performance perspective, exceptions are expensive.
The bulk of the cost comes from &lt;code&gt;Throwable.fillInStackTrace()&lt;&#x2F;code&gt; which traverses the
&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Call_stack&quot;&gt;call stack&lt;&#x2F;a&gt;, and is exacerbated by &lt;strong&gt;massively&lt;&#x2F;strong&gt; long call stacks created by
libraries and frameworks that we use to make life easier.&lt;&#x2F;p&gt;
&lt;p&gt;Fortunately, there is a solution. We can preinitialize exceptions and either generate the call stack &lt;em&gt;once&lt;&#x2F;em&gt;, or
provide an empty stack. I first learned about this technique from Norman Maurer&#x27;s blog post
entitled “&lt;a href=&quot;http:&#x2F;&#x2F;normanmaurer.me&#x2F;blog&#x2F;2013&#x2F;11&#x2F;09&#x2F;The-hidden-performance-costs-of-instantiating-Throwables&#x2F;&quot;&gt;The hidden performance costs of instantiating Throwables&lt;&#x2F;a&gt;”¹.
Norman is one of the creators of &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;netty&#x2F;netty&quot;&gt;Netty&lt;&#x2F;a&gt; which is an abstraction over Java&#x27;s internal
sockets and byte buffers. It&#x27;s a technique that has been used sparingly in Netty itself.&lt;&#x2F;p&gt;
&lt;p&gt;However, if you do it wrong, it can lead to problems. Let&#x27;s look at this constructor for &lt;code&gt;Throwable&lt;&#x2F;code&gt;,&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;java&quot; class=&quot;language-java z-code&quot;&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-java&quot;&gt;protected&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;Throwable&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;    &lt;span class=&quot;z-support z-class z-java&quot;&gt;String&lt;&#x2F;span&gt; message&lt;span class=&quot;z-punctuation z-separator z-comma z-java&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;    &lt;span class=&quot;z-support z-class z-java&quot;&gt;Throwable&lt;&#x2F;span&gt; cause&lt;span class=&quot;z-punctuation z-separator z-comma z-java&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;mark&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;    &lt;span class=&quot;z-storage z-type z-primitive z-java&quot;&gt;boolean&lt;&#x2F;span&gt; enableSuppression&lt;span class=&quot;z-punctuation z-separator z-comma z-java&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;mark&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;    &lt;span class=&quot;z-storage z-type z-primitive z-java&quot;&gt;boolean&lt;&#x2F;span&gt; writableStackTrace
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-java&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-conditional z-if z-java&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-parens z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;writableStackTrace&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-java&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;        &lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;fillInStackTrace&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-java&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    &lt;span class=&quot;z-punctuation z-section z-block z-end z-java&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-conditional z-else z-java&quot;&gt;else&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-java&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;        stackTrace &lt;span class=&quot;z-meta z-assignment z-rhs z-java&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-java&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-java&quot;&gt;null&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-java&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    &lt;span class=&quot;z-punctuation z-section z-block z-end z-java&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    detailMessage &lt;span class=&quot;z-meta z-assignment z-rhs z-java&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-java&quot;&gt;=&lt;&#x2F;span&gt; message&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-java&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    &lt;span class=&quot;z-variable z-language z-java&quot;&gt;this&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;cause &lt;span class=&quot;z-meta z-assignment z-rhs z-java&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-java&quot;&gt;=&lt;&#x2F;span&gt; cause&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-java&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;mark&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-conditional z-if z-java&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-parens z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-java&quot;&gt;!&lt;&#x2F;span&gt;enableSuppression&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-java&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;mark&gt;&lt;mark&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;        suppressedExceptions &lt;span class=&quot;z-meta z-assignment z-rhs z-java&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-java&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-java&quot;&gt;null&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-java&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;mark&gt;&lt;mark&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    &lt;span class=&quot;z-punctuation z-section z-block z-end z-java&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;mark&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-conditional z-if z-java&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-parens z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;jfrTracing&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-java&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;        &lt;span class=&quot;z-support z-class z-java&quot;&gt;ThrowableTracer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;traceThrowable&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;getClass&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-java&quot;&gt;,&lt;&#x2F;span&gt; message&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-java&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    &lt;span class=&quot;z-punctuation z-section z-block z-end z-java&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-java&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It&#x27;s most essential that we set &lt;code&gt;enableSuppression&lt;&#x2F;code&gt; to &lt;code&gt;false&lt;&#x2F;code&gt;. Otherwise, our own code or magical side effects from
libraries could invoke the &lt;code&gt;addSuppressed&lt;&#x2F;code&gt; method, and potentially add objects to the &lt;code&gt;suppressedExceptions&lt;&#x2F;code&gt;
collection &lt;strong&gt;every time&lt;&#x2F;strong&gt; we throw the reusable exception. The collection would grow infinitely.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;java&quot; class=&quot;language-java z-code&quot;&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-java&quot;&gt;public&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-modifier z-java&quot;&gt;final&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-modifier z-java&quot;&gt;synchronized&lt;&#x2F;span&gt; void &lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;addSuppressed&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-class z-java&quot;&gt;Throwable&lt;&#x2F;span&gt; exception&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-java&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-conditional z-if z-java&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-parens z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;exception &lt;span class=&quot;z-keyword z-operator z-comparison z-java&quot;&gt;==&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-language z-java&quot;&gt;this&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;        &lt;span class=&quot;z-keyword z-control z-flow z-throw z-java&quot;&gt;throw&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-instantiation z-java&quot;&gt;&lt;span class=&quot;z-keyword z-other z-storage z-new z-java&quot;&gt;new&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-class z-java&quot;&gt;IllegalArgumentException&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-parens z-constructor-arguments z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-java&quot;&gt;SELF_SUPPRESSION_MESSAGE&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-java&quot;&gt;,&lt;&#x2F;span&gt; exception&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-java&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    &lt;span class=&quot;z-support z-class z-java&quot;&gt;Objects&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;requireNonNull&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;exception&lt;span class=&quot;z-punctuation z-separator z-comma z-java&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-other z-java&quot;&gt;NULL_CAUSE_MESSAGE&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-java&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;mark&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-conditional z-if z-java&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-parens z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;suppressedExceptions &lt;span class=&quot;z-keyword z-operator z-comparison z-java&quot;&gt;==&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-java&quot;&gt;null&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-comment z-line z-double-slash z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-java&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; Suppressed exceptions not recorded
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;mark&gt;&lt;mark&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;        &lt;span class=&quot;z-keyword z-control z-flow z-return z-java&quot;&gt;return&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-java&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;mark&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-conditional z-if z-java&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-parens z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;suppressedExceptions &lt;span class=&quot;z-keyword z-operator z-comparison z-java&quot;&gt;==&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-other z-java&quot;&gt;SUPPRESSED_SENTINEL&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;        suppressedExceptions &lt;span class=&quot;z-meta z-assignment z-rhs z-java&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-java&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-instantiation z-java&quot;&gt;&lt;span class=&quot;z-keyword z-other z-storage z-new z-java&quot;&gt;new&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-class z-java&quot;&gt;ArrayList&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-diamond z-java&quot;&gt;&amp;lt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-parens z-constructor-arguments z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-java&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-java&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;mark&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    suppressedExceptions&lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;add&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;exception&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-java&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;mark&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-java&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This happened to me (&lt;code&gt;:faceplant:&lt;&#x2F;code&gt;). It turns out that &lt;a href=&quot;https:&#x2F;&#x2F;projectreactor.io&#x2F;docs&quot;&gt;Project Reactor&lt;&#x2F;a&gt; invokes
&lt;code&gt;addSuppressed&lt;&#x2F;code&gt; in a class called
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;travishaagen&#x2F;reactor-core&#x2F;blob&#x2F;main&#x2F;reactor-core&#x2F;src&#x2F;main&#x2F;java&#x2F;reactor&#x2F;core&#x2F;publisher&#x2F;FluxOnAssembly.java#L588&quot;&gt;FluxOnAssembly&lt;&#x2F;a&gt;
every time an &lt;code&gt;Exception&lt;&#x2F;code&gt; passes through.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;benchmarks&quot;&gt;Benchmarks&lt;&#x2F;h2&gt;
&lt;p&gt;Norman included some &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;openjdk&#x2F;jmh&quot;&gt;Java Microbenchmark Harness (JMH)&lt;&#x2F;a&gt; results in the
beforementioned &lt;a href=&quot;http:&#x2F;&#x2F;normanmaurer.me&#x2F;blog&#x2F;2013&#x2F;11&#x2F;09&#x2F;The-hidden-performance-costs-of-instantiating-Throwables&#x2F;&quot;&gt;blog post&lt;&#x2F;a&gt;.
I also ran across
“&lt;a href=&quot;https:&#x2F;&#x2F;www.javaspring.net&#x2F;blog&#x2F;consuming-stack-traces-noticeably-slower-in-java-11-than-java-8&#x2F;&quot;&gt;Why Consuming Stack Traces is Noticeably Slower in Java 11 Compared to Java 8: JMH Benchmark Results.&lt;&#x2F;a&gt;”²
It makes some interesting points and I didn&#x27;t realize that Java 11 introduced a change that was meant to improve
average performance by lazily traversing the call stack for logging. Because of this lazy traversal, I included
some additional &lt;code&gt;*AndGetStacktrace&lt;&#x2F;code&gt; JMH benchmarks below.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;text&quot; class=&quot;language-text z-code&quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Benchmark                         Mode  Cnt           Score         Error  Units
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;staticException                  thrpt    5  1799330562.898 ± 3931377.639  ops&#x2F;s
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;staticExceptionAndGetStacktrace  thrpt    5   105525288.622 ±  404717.391  ops&#x2F;s
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;newException                     thrpt    5     1529637.197 ±    2700.762  ops&#x2F;s
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;newExceptionAndGetStacktrace     thrpt    5      328081.037 ±    1212.503  ops&#x2F;s
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To summarize,&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Throwing and catching a reusable &lt;code&gt;StaticException&lt;&#x2F;code&gt; reached 1,799,330,563 operations&#x2F;second&lt;&#x2F;li&gt;
&lt;li&gt;Reusable &lt;code&gt;StaticException&lt;&#x2F;code&gt; followed by a call to &lt;code&gt;e.getStackTrace()&lt;&#x2F;code&gt; was 105,525,289 operations&#x2F;second&lt;&#x2F;li&gt;
&lt;li&gt;Throwing a new &lt;code&gt;RuntimeException&lt;&#x2F;code&gt; every time was 1,529,637 operations&#x2F;second&lt;&#x2F;li&gt;
&lt;li&gt;And &lt;code&gt;RuntimeException&lt;&#x2F;code&gt; with &lt;code&gt;e.getStackTrace()&lt;&#x2F;code&gt; was 328,081 operations&#x2F;second&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Comparing the &lt;em&gt;flow control&lt;&#x2F;em&gt; &lt;code&gt;static&lt;&#x2F;code&gt; use case #1 with &lt;code&gt;new&lt;&#x2F;code&gt; #3 shows &lt;strong&gt;1000x better performance&lt;&#x2F;strong&gt; for
&lt;code&gt;StaticException&lt;&#x2F;code&gt;.
Both the &lt;code&gt;static&lt;&#x2F;code&gt; and &lt;code&gt;new&lt;&#x2F;code&gt; cases are seriously hampered whenever you choose to log the stacktrace.
The result for &lt;code&gt;staticExceptionAndGetStacktrace&lt;&#x2F;code&gt; is surprising, because the only additional operation is calling
&lt;code&gt;clone()&lt;&#x2F;code&gt;
on our empty &lt;code&gt;StackTraceElement[]&lt;&#x2F;code&gt; array. Long call stacks were not simulated with the benchmarks either.&lt;&#x2F;p&gt;
&lt;p&gt;Above benchmark code available at
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;travishaagen&#x2F;blog-static-exceptions-for-flow-control&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;travishaagen&#x2F;blog-static-exceptions-for-flow-control&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;final-thoughts&quot;&gt;Final Thoughts&lt;&#x2F;h2&gt;
&lt;p&gt;Throwing exceptions has a cost in the JVM. For optimal performance, exceptions should be thrown sparingly.
When a failure condition is not unexpected, your application&#x27;s latency and throughput can benefit
from static exceptions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;Maurer, N. (2013, November 9). The hidden performance costs of instantiating Throwables. The Thoughts of Norman
Maurer. &lt;a href=&quot;http:&#x2F;&#x2F;normanmaurer.me&#x2F;blog&#x2F;2013&#x2F;11&#x2F;09&#x2F;The-hidden-performance-costs-of-instantiating-Throwables&#x2F;&quot;&gt;http:&#x2F;&#x2F;normanmaurer.me&#x2F;blog&#x2F;2013&#x2F;11&#x2F;09&#x2F;The-hidden-performance-costs-of-instantiating-Throwables&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Why Consuming Stack Traces is Noticeably Slower in Java 11 Compared to Java 8: JMH Benchmark Results.
(2025, November 26). javaspring.net.
&lt;a href=&quot;https:&#x2F;&#x2F;www.javaspring.net&#x2F;blog&#x2F;consuming-stack-traces-noticeably-slower-in-java-11-than-java-8&#x2F;&quot;&gt;https:&#x2F;&#x2F;www.javaspring.net&#x2F;blog&#x2F;consuming-stack-traces-noticeably-slower-in-java-11-than-java-8&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
</content>
        
    </entry>
</feed>
