mtnr

A tech blog with fries on the side

Category: java

  • ๐Ÿ“Š Diagnosing Java Applications: Creating and Analyzing Thread & Heap Dumps

    When your Java application starts misbehaving – hanging, crashing, or consuming too much memory – thread and heap dumps are your go-to tools for root cause analysis. This post walks through how to create these dumps using the jstack, jmap, and jcmd tools, and suggests utilities for analyzing them effectively. Use jps to identify the process ID you’re interested in.


    ๐Ÿงต Thread Dumps: Capturing Thread States

    1. Using jstack

    jstack <PID> > threaddump.txt
    
    • Produces a snapshot of all thread states (blocked, runnable, waiting).
    • Great for diagnosing deadlocks, thread contention, and CPU spikes.

    2. Using jcmd

    jcmd <PID> Thread.print > threaddump.txt
    
    • More modern and flexible than jstack.
    • Lists thread locks and monitors.

    ๐Ÿง  Heap Dumps: Capturing Memory Snapshots

    1. Using jmap

    jmap -dump:live,format=b,file=heapdump.hprof <PID>
    
    • Dumps the live heap memory (excluding unreachable objects).
    • Useful for analyzing memory leaks and object retention.

    2. Using jcmd

    jcmd <PID> GC.heap_dump heapdump.hprof
    
    • Recommended over jmap for modern JVMs (especially with limited access).
    • Can work even when jmap fails due to permissions or restrictions.

    ๐Ÿงฐ Tools to Analyze Dumps

    ๐Ÿ” Thread Dump Analysis

    • jstack.review – Analyze java thread dumps from within the browser. No data will leave your computer when you click Analyze.
    • FastThread.io โ€“ Upload your dump and get a categorized summary.
    • TDA (Thread Dump Analyzer) โ€“ Desktop tool for visualizing thread interactions.

    ๐Ÿง  Heap Dump Analysis

    • Eclipse MAT (Memory Analyzer Tool) โ€“ Industry-standard tool for analyzing .hprof files.
    • VisualVM โ€“ Bundled with the JDK or available separately, it provides a GUI for live analysis and offline dump inspection.
    • YourKit โ€“ Commercial profiler with advanced heap analysis and leak detection.

    ๐Ÿ“ Final Thoughts

    Thread and heap dumps are crucial artifacts for JVM troubleshooting. While tools like jstack and jmap provide raw diagnostic data, leveraging jcmd offers greater flexibility and reliability on modern JVMs. Combined with powerful analysis tools, these techniques can help you uncover performance bottlenecks and memory issues before they escalate into outages.

    Happy debugging! ๐Ÿž

  • Install Java using Homebrew and jEnv on MacOS

    Sometimes it’s desirable to use different Java versions. Here’s one way how to do it on a Mac.

    Prerequisites

    If you haven’t already, install Homebrew as a first step.

    $ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

    Now, that Homebrew is installed, install jEnv, next. It’ll enable you to manage multiple Java installations and to switch easily amongst them.

    $ brew install jenv

    Follow the steps listed in the official jEnv documentation if you’re using a shell other than zsh to configure jEnv.

    You’ll find the steps necessary to configure zsh below.

    $ echo 'export PATH="$HOME/.jenv/bin:$PATH"' >> ~/.zshrc
    $ echo 'eval "$(jenv init -)"' >> ~/.zshrc

    Install JDKs

    Now, that all pieces are in place, let’s install a JDK. You may chose whichever version you need. There is a list of available JDKs under https://formulae.brew.sh/formula/openjdk.

    $ brew install openjdk@17

    Manage JDKs

    In order to manage the newly installed JDK with jEnv, let’s make jEnv aware of it.

    $ jenv add /opt/homebrew/opt/openjdk@17/libexec/openjdk.jdk/Contents/Home/

    You can chose to install additional JDKs now but we’ll check the available versions with jEnv, first.

    $ jenv versions
    * system (set by ~/.jenv/version)
      17
      17.0
      17.0.13
      openjdk64-17.0.13

    You can easily switch between versions using the following command.

    $ jenv global openjdk64-17.0.13

    This will enable the selected JDK on a global level. You may also chose to only enable it in a given directory by using the local instead of global command.

    You must restart you terminal for the changes to take effect.

    Happy coding!