<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[JTop-Gun]]></title><description><![CDATA[I feel the need
The need for speed]]></description><link>https://jtop-gun.com</link><generator>RSS for Node</generator><lastBuildDate>Fri, 17 Apr 2026 09:50:13 GMT</lastBuildDate><atom:link href="https://jtop-gun.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Mission 2 - JDK scouting]]></title><description><![CDATA[During this mission we will scout all executables which are located in JDK bin\ folder. Let's turn and burn!
First let's launch some simple Java app, which will be doing some dummy job, but stay always running, so we have material to work with.
packa...]]></description><link>https://jtop-gun.com/mission-2-jdk-scouting</link><guid isPermaLink="true">https://jtop-gun.com/mission-2-jdk-scouting</guid><dc:creator><![CDATA[Ivan Zvieriev]]></dc:creator><pubDate>Tue, 21 Feb 2023 10:14:31 GMT</pubDate><content:encoded><![CDATA[<p>During this mission we will scout all executables which are located in JDK bin\ folder. Let's turn and burn!</p>
<p>First let's launch some simple Java app, which will be doing some dummy job, but stay always running, so we have material to work with.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> org.jtopgun;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Main</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> InterruptedException </span>{
       Thread newThread = <span class="hljs-keyword">new</span> Thread(() -&gt; {
            <span class="hljs-keyword">while</span> (<span class="hljs-keyword">true</span>) {
                ClassWithoutFinalizer fast = <span class="hljs-keyword">new</span> ClassWithoutFinalizer();
                System.out.println(fast.hashCode());
            }
        });
        newThread.start();
    }
}
</code></pre>
<p>Now let's start with commands</p>
<h1 id="heading-jinfo">JINFO</h1>
<pre><code class="lang-bash"><span class="hljs-comment">#First let's find our process</span>
./jps
</code></pre>
<p>My Main process have id 25368. Further all examples will be with this id, use your own. Let's get system properties of our JVM.</p>
<pre><code class="lang-bash">./jinfo 25368
<span class="hljs-comment">#to print only jvm flags</span>
./jinfo -flags 25368
<span class="hljs-comment">#to print only jvm system properties</span>
./jinfo -sysprops 25368
<span class="hljs-comment">#to print only one flag</span>
./jinfo -flag UseG1GC 25368
</code></pre>
<p>With jinfo we can also enable or disable a flag, or set up a value.</p>
<p>The trick is that not all flags can be dynamically set or enabled/disabled after JVM has started. Some of them are set during the initialization of JVM and cannot be changed. Let's see how to define if we can change the value of the flag. For this let's use java command.</p>
<pre><code class="lang-bash">java -XX:+PrintFlagsFinal -version
</code></pre>
<p>Now you will see the full list of JVM flags available for your version of JVM. First column is type of the flag (int, bool etc.), then name and value of the flag. Last column says if this flag has default value, or it is calculated ergonomically. The column which contains "product" (same for all platforms), "pd product" (default value is platform dependent), "C2 diagnostic" (provides diagnostic output). And the last value here is "manageable" - this is exactly the flags which could be changed during runtime. Let's try to change some manageable and product flags</p>
<pre><code class="lang-bash"><span class="hljs-comment">#first let's switch some manageable flag</span>
<span class="hljs-comment">#display value</span>
$ ./jinfo -flag ShowCodeDetailsInExceptionMessages 25368
-XX:+ShowCodeDetailsInExceptionMessages
<span class="hljs-comment">#now switch</span>
./jinfo -flag -ShowCodeDetailsInExceptionMessages 25368
<span class="hljs-comment">#display again</span>
$ ./jinfo -flag ShowCodeDetailsInExceptionMessages 25368
-XX:-ShowCodeDetailsInExceptionMessages
<span class="hljs-comment">#the value was switched successfully</span>

<span class="hljs-comment">#now let's try to switch some not manageable flag and see the result</span>
$ ./jinfo -flag -UseTLAB 25368
Exception <span class="hljs-keyword">in</span> thread <span class="hljs-string">"main"</span> com.sun.tools.attach.AttachOperationFailedException: flag <span class="hljs-string">'UseTLAB'</span> cannot be changed
        at jdk.attach/sun.tools.attach.VirtualMachineImpl.execute(VirtualMachineImpl.java:128)
        at jdk.attach/sun.tools.attach.HotSpotVirtualMachine.executeCommand(HotSpotVirtualMachine.java:313)
        at jdk.attach/sun.tools.attach.HotSpotVirtualMachine.setFlag(HotSpotVirtualMachine.java:286)
        at jdk.jcmd/sun.tools.jinfo.JInfo.flag(JInfo.java:156)
        at jdk.jcmd/sun.tools.jinfo.JInfo.main(JInfo.java:127)
</code></pre>
<h1 id="heading-jstat">JSTAT</h1>
<p>jstat provides information about class loading activities and GC. The official documentation is here: <a target="_blank" href="https://docs.oracle.com/javase/9/tools/jstat.htm#JSWOR734">https://docs.oracle.com/javase/9/tools/jstat.htm#JSWOR734</a></p>
<pre><code class="lang-bash"><span class="hljs-comment">#getting all available options</span>
./jstat -options
<span class="hljs-comment">#information about JIT tasks</span>
./jstat -compiler 25368
<span class="hljs-comment">#information about GC and memory status</span>
./jstat -gc 25368
<span class="hljs-comment">#information about memory pool generation and space capacities</span>
./jstat -gccapacity 25368
<span class="hljs-comment">#information about GC</span>
./jstat -gcutil 25368
./jstat -gccause 25368
</code></pre>
<h1 id="heading-jcmd">JCMD</h1>
<p>The jcmd utility is used to send diagnostic command requests to the JVM</p>
<p><a target="_blank" href="https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr006.html">https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr006.html</a></p>
<p>Let's see what we could do with it:</p>
<pre><code class="lang-bash">./jcmd 25368 <span class="hljs-built_in">command</span>
</code></pre>
<p>This will list all available commands for your running JVM. Now let's experiment with them.</p>
<pre><code class="lang-bash"><span class="hljs-comment">#start JFR recording</span>
./jcmd 25368 JFR.start
<span class="hljs-comment">#check the status of the recording</span>
./jcmd 25368 JFR.check
<span class="hljs-comment">#dump recording to file</span>
./jcmd 25368 JFR.dump
<span class="hljs-comment">#the output will show you the name of the file and path to it</span>
<span class="hljs-comment">#stop the recording</span>
./jcmd 25368 JFR.stop name=1
</code></pre>
<h1 id="heading-jstack">JSTACK</h1>
<p>JStack allows to take thread dump of your running JVM</p>
<p>./jstack 25368</p>
<h1 id="heading-jmap">JMAP</h1>
<p>JMap is needed for taking thread dumps of the application</p>
<pre><code class="lang-bash"> ./jmap -histo:all,file=/c/Soft/histo.data 32716
</code></pre>
<p>There are a lot of options to the command, try to play with this command and see what information you could extract using different options</p>
<h1 id="heading-other-jdk-utilities">OTHER JDK UTILITIES</h1>
<p>The other jdk utilities are not that important, so we will give just brief description here.</p>
<p>jabswitch - to enable or disable Java Access Bridge in order to work with java acceessibility API <a target="_blank" href="https://docs.oracle.com/javase/7/docs/technotes/guides/access/jaapi.html">https://docs.oracle.com/javase/7/docs/technotes/guides/access/jaapi.html</a></p>
<p>jaccessinspector - You use the javaaccessinspector accessibility evaluation tool for the Java Accessibility Utilities API to examine accessible information about the objects in the Java Virtual Machine.</p>
<p>jar - for manipulating jar archives</p>
<p>jarsigner - for signing jar archives and for verification of jar archives signatures</p>
<p>java - for starting new virtual machine</p>
<p>javac - for compilation of source code into bytecode</p>
<p>javadoc - for generating documentation</p>
<p>javap - for viewing bytecode of .class files. With -c option the output is more detailed</p>
<p>javaw - (<em>Java windowed</em>) application executor not associated with console. So no display of output/errors. It can be used to silently push the output/errors to text files. It is mostly used to launch GUI-based applications.</p>
<p>jdb - simple debugger</p>
<p>jdeprscan - You use the jdeprscan tool as a static analysis tool that scans a jar file (or some other aggregation of class files) for uses of deprecated API elements.</p>
<p>jdeps - class dependency analyzer</p>
<p>and others</p>
<p><a target="_blank" href="https://jdk.java.net/jmc/8/">https://jdk.java.net/jmc/8/</a></p>
<p><a target="_blank" href="https://visualvm.github.io/download.html">https://visualvm.github.io/download.html</a></p>
<p>https://techcrunch.com/2023/01/25/atomicjar-opens-public-beta-of-testcontainers-cloud-cloud-version-of-open-source-testing-tool/</p>
]]></content:encoded></item><item><title><![CDATA[Mission 1 - JVM scouting]]></title><description><![CDATA[This is text version for the first stream of JTop-Gun channel. The link to the video recording:
<link here>
Let's turn and burn...
Getting basic information about JVM
And we start with "Hello world" and put it into sleep :)
package org.jtopgun;

publ...]]></description><link>https://jtop-gun.com/mission-1-jvm-scouting</link><guid isPermaLink="true">https://jtop-gun.com/mission-1-jvm-scouting</guid><category><![CDATA[jconsole]]></category><category><![CDATA[jtop-gun]]></category><category><![CDATA[jstack]]></category><category><![CDATA[jcmd]]></category><category><![CDATA[jps]]></category><dc:creator><![CDATA[Ivan Zvieriev]]></dc:creator><pubDate>Fri, 20 Jan 2023 05:00:42 GMT</pubDate><content:encoded><![CDATA[<p>This is text version for the first stream of JTop-Gun channel. The link to the video recording:</p>
<p>&lt;link here&gt;</p>
<p>Let's turn and burn...</p>
<h1 id="heading-getting-basic-information-about-jvm">Getting basic information about JVM</h1>
<p>And we start with "Hello world" and put it into sleep :)</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> org.jtopgun;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Main</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> InterruptedException </span>{
        Thread.sleep(<span class="hljs-number">1_000_000_000</span>);
        System.out.println(<span class="hljs-string">"Hello world!"</span>);
    }
}
</code></pre>
<p>Questions: how many threads are running right now? How much memory does our "Hello world" occupy? What version of JVM is it running? What GC?</p>
<h3 id="heading-jconsole">JCONSOLE</h3>
<p>JDK gives tools to answer all these questions. And basic tool from JDK to get quite a lot of info is</p>
<pre><code class="lang-bash">./jconsole
</code></pre>
<h3 id="heading-jps-jcmd">JPS / JCMD</h3>
<p>If we don't have graphical interface, let's see at command line tools which are available.</p>
<p>First let's identify PID for our program. Run</p>
<pre><code class="lang-bash">./jps
</code></pre>
<p>You will see all JVM running on your machine. JPS stands for JVM process state.</p>
<p>And now let's try</p>
<pre><code class="lang-bash">./jcmd
</code></pre>
<p>You will see a lot of available commands and can play with them using</p>
<pre><code class="lang-bash">./jcmd &lt;pid&gt; &lt;<span class="hljs-built_in">command</span>&gt;
</code></pre>
<h3 id="heading-getting-thread-dump">GETTING THREAD DUMP</h3>
<p>Now let's see current stack trace of our sleeping beauty. Here are our command line options:</p>
<pre><code class="lang-bash">./jstack &lt;pid&gt;
./jcmd 10364 Thread.print
</code></pre>
<p>Or you could use jconsole and you will see something like</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674136927321/2e873139-b8e5-4dac-bff4-50d9afd539ca.png" alt class="image--center mx-auto" /></p>
<p>I have 16 threads, but depending on your Java version, JVM vendor, machine, it can be very different.</p>
<p>There will be a different article describing all of them, today we focus on Reference Handler and Finalizer. Why they are needed? Peter Lawrey gives very good answer for that here <a target="_blank" href="https://stackoverflow.com/questions/7658670/understanding-the-reference-handler-thread">https://stackoverflow.com/questions/7658670/understanding-the-reference-handler-thread</a></p>
<p>But in short, GC is creating linked list of references ready to be removed. Reference Handler will put them in appropriate queue, and Finalizer thread will execute code which is in finalize() method.</p>
<h3 id="heading-why-you-must-not-use-finalize">WHY YOU MUST NOT USE FINALIZE()</h3>
<p>Now, let's update our hello world app like that:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> org.jtopgun;

<span class="hljs-keyword">import</span> java.util.ArrayList;
<span class="hljs-keyword">import</span> java.util.List;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Main</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> InterruptedException </span>{
        Thread newThread = <span class="hljs-keyword">new</span> Thread(() -&gt; {
            <span class="hljs-keyword">while</span> (<span class="hljs-keyword">true</span>) {
                List arrayList = <span class="hljs-keyword">new</span> ArrayList();
                System.out.println(arrayList.size());
            }
        });
        newThread.start();
        Thread.sleep(<span class="hljs-number">1_000_000_000</span>);
    }
}
</code></pre>
<p>Basically we start creating garbage in second thread quickly and indefinitely, then memory graph will look approximately like that:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674146354194/58e19986-23f3-4d18-95a2-17deced7f607.png" alt class="image--center mx-auto" /></p>
<p>Very much expected - garbage is being created and normally removed. Now let's add another class:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> org.jtopgun;

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

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">finalize</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> InterruptedException </span>{
        Thread.sleep(<span class="hljs-number">1</span>);<span class="hljs-comment">//1 milisecond finalize method</span>
    }
}
</code></pre>
<p>And rerun the application</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674147931558/26823cad-f23f-4e8a-ad50-2b5e98f390cb.png" alt class="image--center mx-auto" /></p>
<p>We see a stable heap growth. Outcome - never use finalize() method :)</p>
]]></content:encoded></item></channel></rss>