Skip to main content
Redhat Developers  Logo
  • AI

    Get started with AI

    • Red Hat AI
      Accelerate the development and deployment of enterprise AI solutions.
    • AI learning hub
      Explore learning materials and tools, organized by task.
    • AI interactive demos
      Click through scenarios with Red Hat AI, including training LLMs and more.
    • AI/ML learning paths
      Expand your OpenShift AI knowledge using these learning resources.
    • AI quickstarts
      Focused AI use cases designed for fast deployment on Red Hat AI platforms.
    • No-cost AI training
      Foundational Red Hat AI training.

    Featured resources

    • OpenShift AI learning
    • Open source AI for developers
    • AI product application development
    • Open source-powered AI/ML for hybrid cloud
    • AI and Node.js cheat sheet

    Red Hat AI Factory with NVIDIA

    • Red Hat AI Factory with NVIDIA is a co-engineered, enterprise-grade AI solution for building, deploying, and managing AI at scale across hybrid cloud environments.
    • Explore the solution
  • Learn

    Self-guided

    • Documentation
      Find answers, get step-by-step guidance, and learn how to use Red Hat products.
    • Learning paths
      Explore curated walkthroughs for common development tasks.
    • See all learning

    Hands-on

    • Developer Sandbox
      Spin up Red Hat's products and technologies without setup or configuration.
    • Interactive labs
      Learn by doing in these hands-on, browser-based experiences.
    • Interactive demos
      Click through product features in these guided tours.

    Browse by topic

    • AI/ML
    • Automation
    • Java
    • Kubernetes
    • Linux
    • See all topics

    Training & certifications

    • Courses and exams
    • Certifications
    • Skills assessments
    • Red Hat Academy
    • Learning subscription
    • Explore training
  • Build

    Get started

    • Red Hat build of Podman Desktop
      A downloadable, local development hub to experiment with our products and builds.
    • Developer Sandbox
      Spin up Red Hat's products and technologies without setup or configuration.

    Download products

    • Access product downloads to start building and testing right away.
    • Red Hat Enterprise Linux
    • Red Hat AI
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform
    • See all products

    Featured

    • Red Hat build of OpenJDK
    • Red Hat JBoss Enterprise Application Platform
    • Red Hat OpenShift Dev Spaces
    • Red Hat Developer Toolset

    References

    • E-books
    • Documentation
    • Cheat sheets
    • Architecture center
  • Community

    Get involved

    • Events
    • Live AI events
    • Red Hat Summit
    • Red Hat Accelerators
    • Community discussions

    Follow along

    • Articles & blogs
    • Developer newsletter
    • Videos
    • Github

    Get help

    • Customer service
    • Customer support
    • Regional contacts
    • Find a partner

    Join the Red Hat Developer program

    • Download Red Hat products and project builds, access support documentation, learning content, and more.
    • Explore the benefits

Probing Java Methods With Systemtap Part 2

April 1, 2014
Lukas Berk
Related topics:
Linux
Related products:
Red Hat Enterprise Linux

    In Part 1 of Probe Java Methods with Systemtap, we took a look at the basics of pinpoint java probing.  Today we're going to take a look at a more involved example with a tool called Thermostat and components from RHSCL 1.1.

    Thermostat Example

    Note: This example requires further OSGi class loading work, please refer to
    the OSGi section in the tutorial.

    Thermostat is an Open Source Java Tooling project aimed to improve monitoring
    and instrumentation tooling. More information about the project can be found at
    http://icedtea.classpath.org/thermostat/.  Considering we're building thermostat from source, we need to ensure the build requirements have been installed.  This can be easily done via the yum-builddep command if the srpm is available (if not, I've compiled a list of packages that should be installed at the bottom of the article).

    root:]# yum-builddep thermostat1-thermostat

    Depending on your setup it may also be worthwhile to install the package to make sure all the runtime requirements are present.

    root:]# yum install thermostat1-thermostat

    Next we also need to make sure we're explicitly installing mongodb (from RHSCL-1.1) as this database interaction is the area we'll be inspecting and thermostat uses mongodb for storage purposes.  Be sure to enable the scl shell after installing mongodb.

    root:]# yum install mongodb24-mongodb-server mongodb24-mongo-java-driver mongodb24-mongo-java-driver-bson
    lberk:]$ scl enable mongodb24 bash

    In order to make the necessary OSGi class visibility changes, we're going to clone
    thermostat, checkout the 0.15-branchpoint and build with the altered export and imported package lists.

    lberk:]$ hg clone http://icedtea.classpath.org/hg/thermostat && cd thermostat
    lberk:]$ hg checkout 0.15-branchpoint
    < make required modifications >
    lberk:]$ mvn -D=skipTests=True clean install

    In this example we're interested in Thermostat's ability to inspect java threads
    and their current state (ie, blocked, waiting, runnable, etc), and the effect
    it has (if any) on recording information to storage. To do this we need to identify
    the method used to write to the mongoDB, as well as the mechanism used to
    trigger/enable the thread recording. In this case, it means placing method entry
    and return probe points on addImpl and replaceImp, as well as recording the time
    spent in both recording thread state and 'normal' operation by
    placing a probe point on the GUI's getToggleButton method in the ThreadMainPanel class.

    We launch thermostat by executing

    lberk:]$ distribution/target/image/bin/thermostat service

    and in a separate terminal running (make sure you've enabled the scl shell here too)

    lberk:]$ distribution/target/image/bin/thermostat gui

    Once the two thermostat services are running, we can run our script in a third terminal
    and toggle the thread recording switch in the Thermostat gui (under the 'thread' tab), and exit the script with a ctrl-C

    stap thermostat.stp
    ------

    #!/usr/bin/env stap
    global mongo, mongoreturn
    global recording = 0
    global timeinaddimpl, timeinreplace, t1, t2, threadtimestart = 0, threadtimeend = 0, nothreadstart = 0, nothreadend = 0
    
    probe java("Thermostat").class("com.redhat.thermostat.storage.mongodb.internal.MongoStorage").method("addImpl")
    {
      t1 = gettimeofday_us()
      if(recording==0)
        mongo["non-threading"]<<<1
      else
      mongo["threading"]<<<1
    }
    probe java("Thermostat").class("com.redhat.thermostat.storage.mongodb.internal.MongoStorage").method("addImpl").return
    {
      timeinaddimpl<<<(gettimeofday_us() - t1)
      if(recording==0)
        mongoreturn["non-threading"]<<<1
      else
        mongoreturn["threading"]<<<1
    }
    probe java("Thermostat").class("com.redhat.thermostat.storage.mongodb.internal.MongoStorage").method("replaceImpl")
    {
      t2 = gettimeofday_us()
      if(recording==0)
        mongo["non-threading"]<<<1
      else
        mongo["threading"]<<<1
    }
    probe java("Thermostat").class("com.redhat.thermostat.storage.mongodb.internal.MongoStorage").method("replaceImpl").return
    {
      timeinreplace<<<(gettimeofday_us() - t2)
      if(recording==0)
        mongoreturn["non-threading"]<<<1
      else
        mongoreturn["threading"]<<<1
    }
    
    probe java("Thermostat").class("com.redhat.thermostat.thread.client.swing.impl.ThreadMainPanel").method("getToggleButton")
    {
      if( recording == 0){
        threadtimestart = gettimeofday_s()
        if (nothreadstart == 0){
          nothreadend = 0}
        else{
          nothreadend = nothreadend + (gettimeofday_s() - nothreadstart)
        }
        printf("Thread recording has been enabled.n")
        recording = 1
      }
      else{
        nothreadstart = gettimeofday_s()
        threadtimeend = threadtimeend + (gettimeofday_s() - threadtimestart)
        printf("Thread recording has been disabled.n")
        recording = 0 //recording is already 1, set to 0
      }
    }
    probe end
    {
      printf("n")
      printf("Time in AddImpl (uS)n")
      print(@hist_log(timeinaddimpl))
      printf("Time in ReplaceImpl (uS)n")
      print(@hist_log(timeinreplace))
    }

    While toggling the 'Monitor Thread' option a few times, the script output should look something similar to;

    Thread recording has been enabled.
    Thread recording has been disabled.
    Thread recording has been enabled.
    Thread recording has been disabled.
    Thread recording has been enabled.
    Thread recording has been disabled.
    ^C
    Time in AddImpl (uS)
    value |-------------------------------------------------- count
       16 |                                                     0
       32 |                                                     0
       64 |@@@@@@@@@@@@@@@@@@@@@@@@@                          305
      128 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@              452
      256 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@    575
      512 |@@@@@@@@@@@                                        135
     1024 |@                                                   13
     2048 |                                                     2
     4096 |                                                     2
     8192 |                                                     2
    16384 |                                                     0
    32768 |                                                     0
    
    Time in ReplaceImpl (uS)
    value |-------------------------------------------------- count
       16 |                                                    0
       32 |                                                    0
       64 |@@@@@                                              10
      128 |@@                                                  5
      256 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@              75
      512 |@@                                                  4
     1024 |                                                    1
     2048 |                                                    1
     4096 |                                                    0
     8192 |                                                    0
    
    mongo["threading"] @count=1419 @min=1 @max=1 @sum=1419 @avg=1
    mongo["non-threading"] @count=163 @min=1 @max=1 @sum=163 @avg=1
    mongoreturn["threading"] @count=1419 @min=1 @max=1 @sum=1419 @avg=1
    mongoreturn["non-threading"] @count=163 @min=1 @max=1 @sum=163 @avg=1

    Looking at the @count aggregates and comparing the 'threading' and 'non-threading' cases, we can clearly tell database transactions have increased while thread inspection recording was activated.

     

    OSGi Note

    Due to module class loaders and class visibility restrictions under OSGi,
    a few further steps must be taken to properly probe java methods. The
    specific instructions can vary widely from application to application,
    however this overview should give the knowledge to make educated decisions
    to implement class loading visibility to the bundles systemtap requires.

    There are two aspects to address in working with OSGi applications, importing
    the helper jars to each specific bundle, and making the OSGi application aware of our
    helper jar's existence (ie, adding the required changes to the framework classpath).

    First, to add the bundles to the framework classpath, we must create a new
    framework instance and list the classes we'd like to make available to the
    program, the basic functionality of this class must include;

    Map<String, String> jarsWereAdding = new HashMap<String, String>();
    jarsWereAdding.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, jarList);
    factories.next().newFramework(jarsWereAdding);

    Where jarList is a file containing the following bundles (in the case of thermostat we can just add this list to distribution/config/osgi-export.properties and be on our way)

    org.jboss.byteman.rule
    org.jboss.byteman.rule.exception
    org.jboss.byteman.rule.exception.EarlyReturnException
    org.jboss.byteman.rule.helper
    org.systemtap.byteman.helper

    The second portion is adding the import clause to the specific MANIFEST.MF of the
    class you're looking to probe. This is a standard import clause which should resemble:

    Import Package: org.jboss.byteman.rule, org.jboss.byteman.rule.exception, org.jboss.byteman.rule.helper

    This may also be added to the respective pom.xml if you're using a build system such as maven (in our case we've just added it to thermostat's root pom.xml):

    <Import-Package>
    org.jboss.byteman.rule,org.jboss.byteman.rule.exception,org.jboss.byteman.rule.helper,org.systemtap.byteman.helper,*
    </Import-Package>

    Please take note of the additional '*' appended to the clause. This explicit import is required as previously '*' was considered implied.
    NOTE: If you'd like to modify the root pom.xml with a <Import-Package> statement, be sure to place it under the maven-plugin-bundle artifactId.

    Build Require Package List

    In the case thermostat's srpm is not immediately available, below is a list of packages that should allow for thermostat to be built.

    java-devel
    jpackage-utils
    maven-local
    xmvn
    maven-dependency-plugin
    maven-surefire-plugin
    maven-surefire-provider-junit4
    maven-war-plugin
    maven-clean-plugin
    maven-assembly-plugin
    maven-plugin-bundle
    maven-javadoc-plugin
    libgnome-keyring-devel
    felix-framework
    fusesource-pom
    gtk2-devel
    tomcat-servlet-3.0-api
    apache-commons-cli
    jansi
    apache-commons-logging
    apache-commons-beanutils
    apache-commons-codec
    httpcomponents-core
    httpcomponents-client

    Editor's note:  Thermostat is now available with Red Hat Software Collections 1.1 (beta).

    Last updated: November 2, 2023

    Recent Posts

    • Federated identity across the hybrid cloud using zero trust workload identity manager

    • Confidential virtual machine storage attack scenarios

    • Introducing virtualization platform autopilot

    • Integrate zero trust workload identity manager with Red Hat OpenShift GitOps

    • Best Practice Configuration and Tuning for Linux and Windows VMs

    Red Hat Developers logo LinkedIn YouTube Twitter Facebook

    Platforms

    • Red Hat AI
    • Red Hat Enterprise Linux
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform
    • See all products

    Build

    • Developer Sandbox
    • Developer tools
    • Interactive tutorials
    • API catalog

    Quicklinks

    • Learning resources
    • E-books
    • Cheat sheets
    • Blog
    • Events
    • Newsletter

    Communicate

    • About us
    • Contact sales
    • Find a partner
    • Report a website issue
    • Site status dashboard
    • Report a security problem

    RED HAT DEVELOPER

    Build here. Go anywhere.

    We serve the builders. The problem solvers who create careers with code.

    Join us if you’re a developer, software engineer, web designer, front-end designer, UX designer, computer scientist, architect, tester, product manager, project manager or team lead.

    Sign me up

    Red Hat legal and privacy links

    • About Red Hat
    • Jobs
    • Events
    • Locations
    • Contact Red Hat
    • Red Hat Blog
    • Inclusion at Red Hat
    • Cool Stuff Store
    • Red Hat Summit
    © 2026 Red Hat

    Red Hat legal and privacy links

    • Privacy statement
    • Terms of use
    • All policies and guidelines
    • Digital accessibility

    Chat Support

    Please log in with your Red Hat account to access chat support.