← Back to list

I Used Five Command Line Java Tools This Week and I Feel Good

The tools: jps, jmap, jshell, jdeps, jdeprscan

Donald Raab · 2026-04-25 00:48 · 43 claps · 6.4 min read
#jdeps #jdeprscan #jshell #jmap #java
Open on Medium ↗
Wiki topics: 🥊 · Combat Sports

I Used Five Command Line Java Tools This Week and I Feel Good

The tools: [jps](https://docs.oracle.com/en/java/javase/25/docs/specs/man/jps.html), [jmap](https://docs.oracle.com/en/java/javase/25/docs/specs/man/jmap.html), [jshell](https://docs.oracle.com/en/java/javase/25/docs/specs/man/jshell.html), [jdeps](https://docs.oracle.com/en/java/javase/25/docs/specs/man/jdeps.html), [jdeprscan](https://docs.oracle.com/en/java/javase/25/docs/specs/man/jdeprscan.html)

Photo by Fotis Nakos on Unsplash

Photo by Fotis Nakos on Unsplash

I spend most of my time working in the IntelliJ IDEA IDE. This week I took a break from my IDE and spent some time working with [jps](https://docs.oracle.com/en/java/javase/25/docs/specs/man/jps.html), [jmap](https://docs.oracle.com/en/java/javase/25/docs/specs/man/jmap.html), [jshell](https://docs.oracle.com/en/java/javase/25/docs/specs/man/jshell.html), [jdeps](https://docs.oracle.com/en/java/javase/25/docs/specs/man/jdeps.html), and [jdeprscan](https://docs.oracle.com/en/java/javase/25/docs/specs/man/jdeprscan.html) on the command line.

If you don’t know what they are useful for, then click the links I’ve provided to each tool. I will be continuing to update this blog with examples for each command, but wanted to get you started with some useful info. Stay tuned!

See examples for each of the commands in the following sections.

1. jps

Shows you all the Java processes running with their process ids. I was running IntelliJ IDEA (1642 Main) and JShell (1821 and 1822) when I executed the command.

$ jps
1825 Jps
1642 Main
1821 jdk.internal.jshell.tool.JShellToolProvider
1822 RemoteExecutionControl

2. jmap

You can use this to get a Java heap dump or a histogram of a Java heap with classes, memory in bytes, and number of instances for each type. I use this tool as an x-ray for Java heaps that have memory challenges. I have been using jmap for 22 years. It’s a simple tool, but very effective. Also, because it is command line, you can use it easily with GenAI tools.

$ jmap -histo 1642 | head -n 12
 num     #instances         #bytes  class name (module)
-------------------------------------------------------
   1:       2694831      200036600  [B (java.base@21.0.8)
   2:       9119099      145905584  java.lang.Integer (java.base@21.0.8)
   3:       3770944      120845536  [Ljava.lang.Object; (java.base@21.0.8)
   4:       4536329      108871896  kotlin.Pair
   5:       2234397       53625528  java.lang.String (java.base@21.0.8)
   6:        343200       44834360  [I (java.base@21.0.8)
   7:         11400       40318360  [Ljdk.internal.vm.FillerElement; (java.base@21.0.8)
   8:         65054       26567248  [J (java.base@21.0.8)
   9:       1220235       19523760  com.intellij.platform.workspace.jps.entities.SdkDependency
  10:        739476       17747424  com.intellij.core.rwmutex.ReadPermitImpl

One thing that jumps out at me here is the number on Integer wrapper instances and kotlin.Pair instances. Looking at the instance counts, I would guess that these are Pair<Integer, Integer> because there are 2x more Integer instances than Pair. If this is the case, I would use an IntIntPair object from a library like Eclipse Collections.

3. jshell

You can use jshell as a REPL to execute arbitrary Java code. You can add third-party libraries to the classpath. Use the --class-path parameter to add them. On Mac/Linux, separate jar files with a “:” (colon). On Windows, separate them with a “;” (semi-colon).

The following will run jshell with the complete Eclipse Collections library (api and impl) to the class-path.

$ jshell --class-path 
~/.m2/repository/org/eclipse/collections/eclipse-collections/13.0.0/eclipse-collections-13.0.0.jar
:~/.m2/repository/org/eclipse/collections/eclipse-collections-api/13.0.0/eclipse-collections-api-13.0.0.jar
|  Welcome to JShell -- Version 25.0.1
|  For an introduction type: /help intro

jshell> import org.eclipse.collections.impl.factory.*

jshell> import org.eclipse.collections.api.list.*

jshell> List<Integer> list = Lists.mutable.with(1, 2, 3, 4, 5)
list ==> [1, 2, 3, 4, 5]

jshell> List<Integer> evensStream = list.stream().filter(each -> each % 2 == 0).toList()
evensStream ==> [2, 4]

jshell> MutableList<Integer> mutableList = Lists.mutable.with(1, 2, 3, 4, 5)
mutableList ==> [1, 2, 3, 4, 5]

jshell> MutableList<Integer> evens = mutableList.select(each -> each % 2 ==0)
evens ==> [2, 4]

jshell> ImmutableList<Integer> immutableList = Lists.immutable.with(1, 2, 3, 4, 5)
immutableList ==> [1, 2, 3, 4, 5]

jshell> ImmutableList<Integer> odds = immutableList.reject(each -> each % 2 == 0)
odds ==> [1, 3, 5]

jshell> List<Integer> oddsStream = list.stream().filter(each -> each % 2 != 0).toList()
oddsStream ==> [1, 3, 5]

jshell>

If you want to use jshell with Eclipse Collections, you might find this blog helpful, which has the entire package hierarchy for Eclipse Collections in mind map visualizations. This was very helpful for me this week, as there is a bug in jshell that has been apparently fixed in Java 26, for tab completion of imports in third-party jars.

[embed]Mind Maps Didn't Make Me Scroll Mind Maps Didn't Make Me Scroll. How to view complete Java library package structures without scrolling.donraab.medium.com

Tab Completion for Third Party Jar imports

I discovered that tab completion doesn’t work in jshell using Java 25 for importing classes using tab completion, and that’s why the mind map visualizations for Eclipse Collections came in handy. It looks like this bug which was reported in Java 11 has finally been fixed in Java 26. Please comment on this blog if you can confirm.

[embed]Loading... In 9b136, it works well like: $ ~/bin/jdk9b136/bin/jshell --class-path…bugs.openjdk.org

Passing JVM Runtime Parameters to JShell

I learned this week there are two processes started for JShell, and there are two flags you can use to pass JVM runtime parameters to each of them separately. There is a -Jflag and -Rflag. The -R one is useful if you want to the see the effect in the code you write. It took me a while to figure this out. Look at the jshell command options here.

The option I wanted to try was setting Compact Object Headers on since it is still an optional JVM parameter. I will show you how to run JShell with this option on, and also how to run it with Java Object Layout (JOL) on your classpath so you can write code to see the impact.

a. Using JShell w/ JOL on classpath w/ no settings

$ jshell 
--class-path ~/.m2/repository/org/openjdk/jol/jol-core/0.17/jol-core-0.17.jar
|  Welcome to JShell -- Version 25.0.1
|  For an introduction type: /help intro

jshell> import org.openjdk.jol.info.*

jshell> System.out.println(
    GraphLayout.parseInstance(List.of().stream().filter(each -> true))
        .toFootprint())
# WARNING: Unable to get Instrumentation. Dynamic Attach failed. You may add this JAR as -javaagent manually, or supply -Djdk.attach.allowAttachSelf
# WARNING: Unable to attach Serviceability Agent. You can try again with escalated privileges. Two options: a) use -Djol.tryWithSudo=true to try with sudo; b) echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
java.util.stream.ReferencePipeline$2@41cf53f9d footprint:
     COUNT       AVG       SUM   DESCRIPTION
         1        16        16   REPL.$JShell$3$$Lambda/0x00000ffc01048000
         1        16        16   [Ljava.lang.Object;
         1        32        32   java.util.AbstractList$RandomAccessSpliterator
         1        24        24   java.util.ImmutableCollections$ListN
         1        56        56   java.util.stream.ReferencePipeline$2
         1        56        56   java.util.stream.ReferencePipeline$Head
         6                 200   (total)

b. Using JShell w/ JOL on classpath w/ Compact Object Headers enabled

$ jshell 
--class-path ~/.m2/repository/org/openjdk/jol/jol-core/0.17/jol-core-0.17.jar 
-R-XX:+UseCompactObjectHeaders
|  Welcome to JShell -- Version 25.0.1
|  For an introduction type: /help intro

jshell> import org.openjdk.jol.info.*

jshell> System.out.println(
    GraphLayout.parseInstance(List.of().stream().filter(each -> true))
        .toFootprint())
# WARNING: Unable to get Instrumentation. Dynamic Attach failed. You may add this JAR as -javaagent manually, or supply -Djdk.attach.allowAttachSelf
# WARNING: Unable to attach Serviceability Agent. You can try again with escalated privileges. Two options: a) use -Djol.tryWithSudo=true to try with sudo; b) echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
java.util.stream.ReferencePipeline$2@5a10411d footprint:
     COUNT       AVG       SUM   DESCRIPTION
         1         8         8   REPL.$JShell$3$$Lambda/0x00000fc001049400
         1        16        16   [Ljava.lang.Object;
         1        32        32   java.util.AbstractList$RandomAccessSpliterator
         1        16        16   java.util.ImmutableCollections$ListN
         1        56        56   java.util.stream.ReferencePipeline$2
         1        48        48   java.util.stream.ReferencePipeline$Head
         6                 176   (total)

4. jdeps

Analyzes and reports on dependencies on classes. Using the -s parameter gives a high-level summary as seen below

$ jdeps -s ~/.m2/repository/org/openjdk/jol/jol-core/0.17/jol-core-0.17.jar

# I abbreviated JDK info and replaced with <JDK Version>
jol-core-0.17.jar -> ~<JDK Version>/Contents/Home/jre/lib/rt.jar

Using jdeps with no parameters and just a target .jar file will show package dependencies.

$ jdeps ~/.m2/repository/org/openjdk/jol/jol-core/0.17/jol-core-0.17.jar

# I abbreviated JDK info and replaced with <JDK Version>
jol-core-0.17.jar -> ~<JDK Version>/Contents/Home/jre/lib/rt.jar
   org.openjdk.jol.datamodel (jol-core-0.17.jar)
      -> java.lang                                          
      -> java.util                                          
      -> org.openjdk.jol.vm                                 jol-core-0.17.jar
   org.openjdk.jol.heap (jol-core-0.17.jar)
      -> java.io                                            
      -> java.lang                                          
      -> java.nio                                           
      -> java.util                                          
      -> java.util.zip                                      
      -> org.openjdk.jol.info                               jol-core-0.17.jar
      -> org.openjdk.jol.util                               jol-core-0.17.jar
   org.openjdk.jol.info (jol-core-0.17.jar)
      -> java.awt                                           
      -> java.awt.geom                                      
      -> java.awt.image                                     
      -> java.io                                            
      -> java.lang                                          
      -> java.lang.invoke                                   
      -> java.lang.ref                                      
      -> java.lang.reflect                                  
      -> java.util                                          
      -> java.util.function                                 
      -> javax.imageio                                      
      -> org.openjdk.jol.datamodel                          jol-core-0.17.jar
      -> org.openjdk.jol.layouters                          jol-core-0.17.jar
      -> org.openjdk.jol.util                               jol-core-0.17.jar
      -> org.openjdk.jol.vm                                 jol-core-0.17.jar
   org.openjdk.jol.layouters (jol-core-0.17.jar)
      -> java.lang                                          
      -> java.lang.reflect                                  
      -> java.util                                          
      -> org.openjdk.jol.datamodel                          jol-core-0.17.jar
      -> org.openjdk.jol.info                               jol-core-0.17.jar
      -> org.openjdk.jol.util                               jol-core-0.17.jar
      -> org.openjdk.jol.vm                                 jol-core-0.17.jar
   org.openjdk.jol.util (jol-core-0.17.jar)
      -> java.io                                            
      -> java.lang                                          
      -> java.lang.reflect                                  
      -> java.net                                           
      -> java.util                                          
      -> org.openjdk.jol.vm                                 jol-core-0.17.jar
   org.openjdk.jol.vm (jol-core-0.17.jar)
      -> java.io                                            
      -> java.lang                                          
      -> java.lang.annotation                               
      -> java.lang.instrument                               
      -> java.lang.invoke                                   
      -> java.lang.management                               
      -> java.lang.reflect                                  
      -> java.net                                           
      -> java.security                                      
      -> java.util                                          
      -> java.util.function                                 
      -> java.util.jar                                      
      -> java.util.zip                                      
      -> javax.management                                   
      -> javax.management.openmbean                         
      -> org.openjdk.jol.info                               jol-core-0.17.jar
      -> org.openjdk.jol.layouters                          jol-core-0.17.jar
      -> org.openjdk.jol.util                               jol-core-0.17.jar
      -> org.openjdk.jol.vm.sa                              jol-core-0.17.jar
      -> sun.misc                                           JDK internal API (rt.jar)
   org.openjdk.jol.vm.sa (jol-core-0.17.jar)
      -> java.io                                            
      -> java.lang                                          
      -> java.lang.invoke                                   
      -> java.lang.management                               
      -> java.lang.reflect                                  
      -> java.util                                          
      -> java.util.concurrent                               
      -> org.openjdk.jol.util                               jol-core-0.17.jar
      -> sun.management                                     JDK internal API (rt.jar)

Using the -v option gives a verbose class level dependency report which may be voluminous.

$ jdeps -v ~/.m2/repository/org/openjdk/jol/jol-core/0.17/jol-core-0.17.jar

# I abbreviated JDK info and replaced with <JDK Version>
jol-core-0.17.jar -> ~<JDK Version>/Contents/Home/jre/lib/rt.jar
   org.openjdk.jol.datamodel.DataModel                -> java.lang.Object                                   
   org.openjdk.jol.datamodel.DataModel                -> java.lang.String                                   
   org.openjdk.jol.datamodel.Model32                  -> java.lang.Class                                    
   org.openjdk.jol.datamodel.Model32                  -> java.lang.Integer                                  
   org.openjdk.jol.datamodel.Model32                  -> java.lang.Object                                   
   org.openjdk.jol.datamodel.Model32                  -> java.lang.String                                   
   org.openjdk.jol.datamodel.Model32                  -> java.lang.StringBuilder                            
   org.openjdk.jol.datamodel.Model32                  -> java.util.Objects                                  
   org.openjdk.jol.datamodel.Model32                  -> org.openjdk.jol.datamodel.DataModel                jol-core-0.17.jar
   org.openjdk.jol.datamodel.Model64                  -> java.lang.Class                                    
   org.openjdk.jol.datamodel.Model64                  -> java.lang.Integer                                  
   org.openjdk.jol.datamodel.Model64                  -> java.lang.Object                                   
   org.openjdk.jol.datamodel.Model64                  -> java.lang.String                                   
   org.openjdk.jol.datamodel.Model64                  -> java.lang.StringBuilder                            
   org.openjdk.jol.datamodel.Model64                  -> java.util.Objects                                  
   org.openjdk.jol.datamodel.Model64                  -> org.openjdk.jol.datamodel.DataModel                jol-core-0.17.jar
   org.openjdk.jol.datamodel.Model64_Lilliput         -> java.lang.Class                                    
   org.openjdk.jol.datamodel.Model64_Lilliput         -> java.lang.Object                                   
   org.openjdk.jol.datamodel.Model64_Lilliput         -> java.lang.String                                   
   org.openjdk.jol.datamodel.Model64_Lilliput         -> java.lang.StringBuilder                            
   org.openjdk.jol.datamodel.Model64_Lilliput         -> org.openjdk.jol.datamodel.DataModel                jol-core-0.17.jar
   org.openjdk.jol.datamodel.ModelVM                  -> java.lang.Class                                    
   org.openjdk.jol.datamodel.ModelVM                  -> java.lang.Object                                   
   org.openjdk.jol.datamodel.ModelVM                  -> java.lang.String                                   
   org.openjdk.jol.datamodel.ModelVM                  -> org.openjdk.jol.datamodel.DataModel                jol-core-0.17.jar
   org.openjdk.jol.datamodel.ModelVM                  -> org.openjdk.jol.vm.VM                              jol-core-0.17.jar
   org.openjdk.jol.datamodel.ModelVM                  -> org.openjdk.jol.vm.VirtualMachine                  jol-core-0.17.jar
   org.openjdk.jol.heap.HeapDumpException             -> java.lang.Exception                                
   org.openjdk.jol.heap.HeapDumpException             -> java.lang.String                                   
   org.openjdk.jol.heap.HeapDumpReader                -> java.io.BufferedInputStream                        
   org.openjdk.jol.heap.HeapDumpReader                -> java.io.ByteArrayOutputStream                      
   org.openjdk.jol.heap.HeapDumpReader                -> java.io.File                                       
   org.openjdk.jol.heap.HeapDumpReader                -> java.io.FileInputStream                            
   org.openjdk.jol.heap.HeapDumpReader                -> java.io.IOException                                
   org.openjdk.jol.heap.HeapDumpReader                -> java.io.InputStream                                
   org.openjdk.jol.heap.HeapDumpReader                -> java.lang.Integer                                  
   org.openjdk.jol.heap.HeapDumpReader                -> java.lang.Long                                     
   org.openjdk.jol.heap.HeapDumpReader                -> java.lang.Math                                     
   org.openjdk.jol.heap.HeapDumpReader                -> java.lang.Object                                   
   org.openjdk.jol.heap.HeapDumpReader                -> java.lang.String 

.... abbreviated for readability.                              

5. jdeprscan

Scans a directory, jar file, or class for usage of deprecated APIs.

$ jdeprscan ~/.m2/repository/org/openjdk/jol/jol-core/0.17/jol-core-0.17.jar

Jar file /Users/donaldraab/.m2/repository/org/openjdk/jol/jol-core/0.17/jol-core-0.17.jar:
class org/openjdk/jol/vm/VM uses deprecated class java/security/AccessController (forRemoval=true)

Thanks for reading!

I am the creator of and committer for the Eclipse Collections OSS project, which is managed at the Eclipse Foundation. Eclipse Collections is open for contributions. I am the author of the book, Eclipse Collections Categorically: Level up your programming game.


메타데이터
post_id
a07531fefb02
slug
i-used-five-command-line-java-tools-this-week-and-i-feel-good-a07531fefb02
url
https://medium.com/@donraab/i-used-five-command-line-java-tools-this-week-and-i-feel-good-a07531fefb02
canonical_url
https://medium.com/@donraab/i-used-five-command-line-java-tools-this-week-and-i-feel-good-a07531fefb02
author_url
https://medium.com/@donraab
status
ok
fetched_at
2026-07-11 01:01:15