<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: matin kaboli</title>
    <description>The latest articles on DEV Community by matin kaboli (@katin).</description>
    <link>https://dev.to/katin</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4204559%2F770b2a6b-8418-489b-b14c-f9eed65f16e2.jpeg</url>
      <title>DEV Community: matin kaboli</title>
      <link>https://dev.to/katin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/katin"/>
    <language>en</language>
    <item>
      <title>Debugging Java and Tomcat in Production: A Systematic Approach</title>
      <dc:creator>matin kaboli</dc:creator>
      <pubDate>Sat, 24 Oct 2026 11:34:15 +0000</pubDate>
      <link>https://dev.to/katin/debugging-java-and-tomcat-in-production-a-systematic-approach-m56</link>
      <guid>https://dev.to/katin/debugging-java-and-tomcat-in-production-a-systematic-approach-m56</guid>
      <description>&lt;p&gt;When a Java application running on Apache Tomcat becomes slow, starts returning errors, or stops responding, restarting the service is often the easiest option.&lt;/p&gt;

&lt;p&gt;But a restart doesn't explain what happened.&lt;/p&gt;

&lt;p&gt;The real challenge is identifying whether the problem comes from the JVM, the application, the operating system, the network, or an external dependency.&lt;/p&gt;

&lt;p&gt;In this article, we'll walk through a practical workflow for investigating Java and Tomcat issues on a Linux server.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Start with the Symptoms
&lt;/h2&gt;

&lt;p&gt;Before changing JVM options or restarting Tomcat, establish what is actually failing.&lt;/p&gt;

&lt;p&gt;Is the application completely unavailable, or are requests simply taking longer than usual? Are all endpoints affected, or only a specific operation? Did the problem begin after a deployment, configuration change, or traffic increase?&lt;/p&gt;

&lt;p&gt;Start by checking the service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl status tomcat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The service name may differ depending on the installation.&lt;/p&gt;

&lt;p&gt;Find the Java process:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pgrep &lt;span class="nt"&gt;-af&lt;/span&gt; &lt;span class="s1"&gt;'org.apache.catalina.startup.Bootstrap'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the latest service logs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;journalctl &lt;span class="nt"&gt;-u&lt;/span&gt; tomcat &lt;span class="nt"&gt;--since&lt;/span&gt; &lt;span class="s2"&gt;"30 minutes ago"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If Tomcat writes to files instead of the system journal, inspect the configured log directory, including &lt;code&gt;catalina.out&lt;/code&gt; where applicable.&lt;/p&gt;

&lt;p&gt;Look for exceptions, repeated errors, failed database connections, thread pool warnings, and messages around the time the problem started.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The goal is to establish a timeline before changing anything.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Check CPU, Memory, and Disk Pressure
&lt;/h2&gt;

&lt;p&gt;A Java process can be running while the application is effectively unavailable.&lt;/p&gt;

&lt;p&gt;Start with the host:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;uptime
&lt;/span&gt;free &lt;span class="nt"&gt;-h&lt;/span&gt;
&lt;span class="nb"&gt;df&lt;/span&gt; &lt;span class="nt"&gt;-h&lt;/span&gt;
&lt;span class="nb"&gt;df&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These commands help identify system load, memory pressure, full filesystems, and inode exhaustion.&lt;/p&gt;

&lt;p&gt;For process-level CPU and memory usage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;top &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;pgrep &lt;span class="nt"&gt;-fo&lt;/span&gt; &lt;span class="s1"&gt;'org.apache.catalina.startup.Bootstrap'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If multiple matching Java processes exist, verify the PID manually before using process-specific diagnostic commands.&lt;/p&gt;

&lt;p&gt;For disk I/O, if &lt;code&gt;sysstat&lt;/code&gt; is installed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;iostat &lt;span class="nt"&gt;-xz&lt;/span&gt; 1 5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;High CPU usage does not automatically mean the JVM needs more CPU. Likewise, low CPU usage does not rule out a serious application problem: threads may be blocked waiting for a database, a lock, or network I/O.&lt;/p&gt;

&lt;p&gt;Correlate these observations with application metrics and logs.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Inspect the JVM Before Changing Heap Settings
&lt;/h2&gt;

&lt;p&gt;Memory problems are often more complicated than simply increasing &lt;code&gt;-Xmx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Check the JVM version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;java &lt;span class="nt"&gt;-version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Identify the Java executable used by the running process, especially when multiple JDK installations exist:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;PID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;tomcat_java_pid&amp;gt;

&lt;span class="nb"&gt;readlink&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"/proc/&lt;/span&gt;&lt;span class="nv"&gt;$PID&lt;/span&gt;&lt;span class="s2"&gt;/exe"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inspect the JVM command line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="s1"&gt;'\0'&lt;/span&gt; &lt;span class="s1"&gt;' '&lt;/span&gt; &amp;lt; &lt;span class="s2"&gt;"/proc/&lt;/span&gt;&lt;span class="nv"&gt;$PID&lt;/span&gt;&lt;span class="s2"&gt;/cmdline"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the matching JDK tools are available and you have the necessary permissions, inspect the running JVM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;jcmd &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; VM.version
jcmd &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; VM.flags
jcmd &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; GC.heap_info
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tool availability and supported commands depend on the JDK version and installation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Heap usage is not the same as process memory
&lt;/h3&gt;

&lt;p&gt;Keep these measurements separate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Java heap:&lt;/strong&gt; Memory managed by the garbage collector.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Metaspace:&lt;/strong&gt; Memory used for class metadata on modern HotSpot JVMs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Native memory:&lt;/strong&gt; Memory used by the JVM, threads, direct buffers, native libraries, and other components.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RSS:&lt;/strong&gt; Physical memory currently resident for the process.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A process can consume substantial RAM even when its Java heap is not full.&lt;/p&gt;

&lt;p&gt;Before increasing &lt;code&gt;-Xmx&lt;/code&gt;, check the container or host memory limit, actual heap usage, garbage collection behavior, and native memory consumption.&lt;/p&gt;

&lt;p&gt;For a production system, don't generate a heap dump or a large diagnostic artifact without considering disk space, latency, and the sensitivity of the data it may contain.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Investigate Slow or Blocked Requests with Thread Dumps
&lt;/h2&gt;

&lt;p&gt;When Tomcat is running but requests are slow or stuck, thread dumps can help reveal what application threads are doing.&lt;/p&gt;

&lt;p&gt;Capture a thread dump using the matching JDK:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;jcmd &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; Thread.print &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /tmp/tomcat-threads.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repeat the capture after a short interval if needed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sleep &lt;/span&gt;10

jcmd &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; Thread.print &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /tmp/tomcat-threads-2.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compare the dumps rather than relying on a single snapshot.&lt;/p&gt;

&lt;p&gt;Look for patterns such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Many request threads waiting on database connections.&lt;/li&gt;
&lt;li&gt;Repeated stack traces pointing to the same slow operation.&lt;/li&gt;
&lt;li&gt;Threads blocked on Java monitors or locks.&lt;/li&gt;
&lt;li&gt;Long-running I/O operations.&lt;/li&gt;
&lt;li&gt;A large number of active threads with little progress.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A thread in &lt;code&gt;WAITING&lt;/code&gt; or &lt;code&gt;BLOCKED&lt;/code&gt; state is not automatically a problem. Interpret the state together with its stack trace, surrounding threads, and application behavior.&lt;/p&gt;

&lt;p&gt;Thread dumps can contain internal class names, SQL statements, URLs, or other sensitive information. Sanitize them before sharing.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Check Tomcat Connector and Thread Pool Saturation
&lt;/h2&gt;

&lt;p&gt;Tomcat's request-processing capacity depends on connector configuration and the work performed by each request.&lt;/p&gt;

&lt;p&gt;For a configured HTTP connector, inspect relevant settings such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;maxThreads&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;minSpareThreads&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;acceptCount&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Connection and request timeouts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The exact available settings depend on the connector and Tomcat version.&lt;/p&gt;

&lt;p&gt;Increasing &lt;code&gt;maxThreads&lt;/code&gt; is not automatically a fix. If requests are blocked waiting for a database connection, creating more request threads may increase contention and memory usage.&lt;/p&gt;

&lt;p&gt;Check whether the application is exhausting a JDBC connection pool or waiting on another constrained dependency.&lt;/p&gt;

&lt;p&gt;Useful evidence includes active and idle connection counts, request latency, queue depth, timeout rates, and thread pool utilization.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Treat Java Agents and Configuration Changes as Variables
&lt;/h2&gt;

&lt;p&gt;Monitoring agents, Java agents, instrumentation libraries, and JVM options can affect application startup and runtime behavior.&lt;/p&gt;

&lt;p&gt;If a problem begins after adding an agent or changing the Java runtime, establish exactly what changed.&lt;/p&gt;

&lt;p&gt;Record:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The previous and current JDK versions.&lt;/li&gt;
&lt;li&gt;The agent version and startup arguments.&lt;/li&gt;
&lt;li&gt;The relevant configuration changes.&lt;/li&gt;
&lt;li&gt;The startup logs and any JVM fatal error reports.&lt;/li&gt;
&lt;li&gt;Whether the problem can be reproduced in a controlled environment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, an application that fails immediately after a Java upgrade requires a different investigation from one that starts successfully but gradually becomes unresponsive.&lt;/p&gt;

&lt;p&gt;Avoid changing several variables simultaneously. Otherwise, it becomes difficult to identify which change caused or resolved the issue.&lt;/p&gt;

&lt;p&gt;If the JVM produces a fatal error report, inspect the report and associated crash logs. A native JVM crash is different from an ordinary Java exception and should not be diagnosed from application logs alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Verify the Hypothesis Before Calling It a Fix
&lt;/h2&gt;

&lt;p&gt;Once you have a plausible root cause, make the smallest safe change that tests it.&lt;/p&gt;

&lt;p&gt;Before applying a production change, consider its potential impact, rollback procedure, and whether a restart is required.&lt;/p&gt;

&lt;p&gt;Afterward, compare the same indicators you collected before the change:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Request latency and error rate.&lt;/li&gt;
&lt;li&gt;CPU and memory usage.&lt;/li&gt;
&lt;li&gt;Garbage collection behavior.&lt;/li&gt;
&lt;li&gt;Thread pool utilization.&lt;/li&gt;
&lt;li&gt;Database connection pool metrics.&lt;/li&gt;
&lt;li&gt;Relevant application logs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A successful restart is not proof that the root cause has been fixed. The issue may return under the same workload.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Practical Incident Checklist
&lt;/h2&gt;

&lt;p&gt;When a Tomcat application becomes slow or unavailable, I would organize the investigation around these questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What changed immediately before the incident?&lt;/li&gt;
&lt;li&gt;Is the issue at the host, JVM, Tomcat, application, or dependency layer?&lt;/li&gt;
&lt;li&gt;Are CPU, memory, disk, or network resources constrained?&lt;/li&gt;
&lt;li&gt;Are request threads progressing, blocked, or waiting?&lt;/li&gt;
&lt;li&gt;Is the JVM healthy, and is garbage collection behaving as expected?&lt;/li&gt;
&lt;li&gt;What evidence supports the suspected root cause?&lt;/li&gt;
&lt;li&gt;How will the fix be validated, and how can it be rolled back?&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Production debugging is not about collecting as many logs as possible or applying JVM tuning options until the symptoms disappear.&lt;/p&gt;

&lt;p&gt;It is about gathering evidence, narrowing the problem to the right layer, testing a hypothesis, and verifying the result.&lt;/p&gt;

&lt;p&gt;The most useful diagnostic command is the one that answers a specific question about the system—not necessarily the one with the most output.&lt;/p&gt;

&lt;p&gt;I'm interested in Linux infrastructure, JVM behavior, distributed systems, and the operational practices that make services more reliable. I'll continue sharing practical technical notes and investigation workflows as I work on these topics.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What do you usually investigate first when a Tomcat application becomes unresponsive: JVM metrics, thread dumps, application logs, or external dependencies?&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>debugging</category>
      <category>devops</category>
      <category>java</category>
      <category>performance</category>
    </item>
    <item>
      <title>What Working with Infrastructure Taught Me About Troubleshooting</title>
      <dc:creator>matin kaboli</dc:creator>
      <pubDate>Sat, 24 Oct 2026 11:29:55 +0000</pubDate>
      <link>https://dev.to/katin/what-working-with-infrastructure-taught-me-about-troubleshooting-1mah</link>
      <guid>https://dev.to/katin/what-working-with-infrastructure-taught-me-about-troubleshooting-1mah</guid>
      <description>&lt;p&gt;Working with infrastructure has taught me that fixing a problem is not just about finding the right command. It's about understanding what's happening underneath.&lt;/p&gt;

&lt;p&gt;When a service becomes slow or stops responding, there are usually several things worth investigating:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Logs:&lt;/strong&gt; What changed before the problem started?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resources:&lt;/strong&gt; Are CPU, memory, disk, or I/O under pressure?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dependencies:&lt;/strong&gt; Is the application waiting on a database or another service?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configuration:&lt;/strong&gt; Did a recent change introduce unexpected behavior?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Metrics:&lt;/strong&gt; Can we identify when the problem started and how it evolved?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I've learned to avoid jumping straight to a solution before understanding the symptoms. A quick fix might restore a service temporarily, but understanding the root cause helps prevent the same problem from happening again.&lt;/p&gt;

&lt;p&gt;I'm interested in Linux, distributed systems, databases, automation, and the practical challenges of operating reliable infrastructure.&lt;/p&gt;

&lt;p&gt;Through &lt;strong&gt;LoopX&lt;/strong&gt;, I'm also working on sharing practical technical knowledge and documenting lessons from infrastructure engineering.&lt;/p&gt;

&lt;p&gt;I'll be sharing more technical notes, troubleshooting approaches, and things I learn along the way.&lt;/p&gt;

&lt;p&gt;What is the first thing you usually check when a production service starts behaving unexpectedly?&lt;/p&gt;

&lt;h1&gt;
  
  
  devops #linux #infrastructure #sre
&lt;/h1&gt;

</description>
      <category>devops</category>
      <category>infrastructure</category>
      <category>monitoring</category>
      <category>sre</category>
    </item>
  </channel>
</rss>
