https://laurent-leturgez.com/2017/12/22/profiling-java-application-with-systemtap/

 
 

I’m not a JVM internals geek but I was sure there was a way to do the job without restarting the JVM, and I found some cool stuff with Systemtap.

To do this, you have to install two packages on your linux distribution: systemtap and systemtap-runtime-java (and configure correctly your user environment):

[root@spark ~]# yum install systemtap systemtap-runtime-java

Please note that I used a CentOS 7.4 distribution.

Then, and for the demo, I wrote a very small piece of Java that do these steps:

  1. Prints the JVM PID
  2. Wait for a key to be pressed. During this time, you will have to execute the systemtap script I will described later.
  3. Execute a loop ten times, each loop with print a message and wait one second, and this last step is executed in a method name “loop_and_wait”.

Here’s the sample code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.premiseo;
 
import java.lang.*;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
 
class Example {
   public static void loop_and_wait(int n) throws InterruptedException{
           System.out.println("Waiting "+n+"ms... Tick");
           Thread.sleep(n);
        }
 
   public static void main(String[] args) {
 
      System.out.println("PID = "+java.lang.management.ManagementFactory.getRuntimeMXBean().getName().split("@")[0]);
      System.out.println("Press any key when ready ...");
 
      try {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String next = in.readLine();
      }
      catch (IOException ioe) {
        ioe.printStackTrace();
      }
 
      try {
        for (int i=0;i<10;i++) {
           loop_and_wait(1000);
        }
      }
      catch (InterruptedException ie) {
        ie.printStackTrace();
      }
   }
}

Then, compile and execute … very basic I said

[spark@spark java]$ javac -cp $CLASSPATH:. com/premiseo/Example.java
[spark@spark java]$ java -cp $CLASSPATH:. com.premiseo.Example
PID = 9928
Press any key when ready ... Waiting 1000ms... Tick
Waiting 1000ms... Tick
Waiting 1000ms... Tick
Waiting 1000ms... Tick
Waiting 1000ms... Tick
Waiting 1000ms... Tick
Waiting 1000ms... Tick
Waiting 1000ms... Tick
Waiting 1000ms... Tick
Waiting 1000ms... Tick

Now, to answer to Tanel, I used a short systemtap script that will profile the program and specially the loop_and_wait method. I will count the number of times the loop_and_wait method has been called, and I will account the time spent in this method execution.

To do that, I had to write two probes related to:

  • the full name of the class, including the package name: com.premiseo.Example
  • the class name where the method is defined: Example
  • the method name I want to profile: loop_and_wait

The first one will be executed when the program will start to execute the targeted method (java(“com.premiseo.Example”).class(“Example”).method(“loop_and_wait”)), the second one will be executed when the method will return (java(“com.premiseo.Example”).class(“Example”).method(“loop_and_wait”).return)

The related systemtap script is given below:

#!/usr/bin/env stap

global counter,timespent,t

probe begin {
printf("Press Ctrl+C to stop profiling\n")
counter=0
timespent=0
} probe java("com.premiseo.Example").class("Example").method("loop_and_wait")
{
counter++
t=gettimeofday_ms()
} probe java("com.premiseo.Example").class("Example").method("loop_and_wait").return
{
timespent+=gettimeofday_ms()-t
} probe end {
printf("Number of calls for loop_and_wait method: %ld \n", counter)
printf("Time Spent in method loop_and_wait: %ld msecs \n", timespent)
}

Execution of this systemtap script gave the following result (click the image for full size):

Is it dynamic? Yes, no need to restart the running JVM process you want to target. If you want to target a specific JVM process id, you can use the stap’s “-x” option, add the modify your probe definition like this:

probe java("com.premiseo.Example").class("Example").method("loop_and_wait")
{
if (pid() == target())
counter++
t=gettimeofday_ms()
}

There’s a limitation, you cannot use wilcards in the java probe definition (java(“com.premiseo.Example”).class(“Example”).method(“loop*”) … for example). That would have been useful to profile a set of methods in the same class … but not possible currently.

If you want to read more about this kind of stuff, please read the following websites:

And … that’s all for today !!

Profiling Java Application with Systemtap的更多相关文章

  1. velocity模板引擎学习(4)-在standalone的java application中使用velocity及velocity-tools

    通常velocity是配合spring mvc之类的框架在web中使用,但velocity本身其实对运行环境没有过多的限制,在单独的java application中也可以独立使用,下面演示了利用ve ...

  2. maven: 打包可运行的jar包(java application)及依赖项处理

    IDE环境中,可以直接用exec-maven-plugin插件来运行java application,类似下面这样: <plugin> <groupId>org.codehau ...

  3. How to run a (Tomcat)Java application server on a Azure virtual machine

    http://www.windowsazure.com/en-us/documentation/articles/virtual-machines-java-run-tomcat-applicatio ...

  4. The differences between Java application and Java applet

    在Java语言中,能够独立运行的程序称为Java应用程序(Application).Java语言还有另外一种程序--Applet程序.Applet程序(也称Java小程序)是运行于各种网页文件中,用于 ...

  5. Java Applet与Java Application的区别

    转自:http://www.educity.cn/java/500609.html 在Java语言中,能够独立运行的程序称为Java应用程序(Application).Java语言还有另外一种程序-- ...

  6. How to deploy JAVA Application on Azure Service Fabric

    At this moment, Azure Service Fabric does not support JAVA application natively (but it's on the sup ...

  7. Java Applet与Java Application的特点

    java application是应用程序,用于桌面开发,java applet是小应用程序,一般嵌入到网页里运行.applet一般用于B/S页面上作为插件式的开发,而application主要是桌面 ...

  8. Debugging java application with netbean

    Debugging Java Applications with NetBeans    from:https://manikandanmv.wordpress.com/2009/09/24/debu ...

  9. 非web环境的注解配置的spring项目应用(non-web, Spring-data-jpa, JavaConfig, Java Application, Maven, AnnotationConfigApplicationContext)

    非web环境的spring应用 springframework提供的spring容器,非常适合应用于javaweb环境中. 同时,spring组件的低耦合性为普通java应用也提供了足够的支持. 以下 ...

随机推荐

  1. java.util.Map

    map时key/value形式存储信息的,键可以为对象null public static void main(String[] args) { Map<String, String> m ...

  2. tomcat8配置SSL

    参考网址:http://www.micmiu.com/enterprise-app/sso/sso-cas-sample/#viewSource 1.生成证书 keytool -genkey -ali ...

  3. ArrayList源码分析笔记(jdk1.8)

    1.特点: ArrayList 是一个动态数组,它是线程不安全的,允许元素为null 可重复,插入有序 读写快,增删慢 扩容:默认容量 10,默认扩容1.5倍 建议指定容量大小,减少扩容带来的性能消耗 ...

  4. win7 X64系统上 PL/SQL不能识别Oracle实例

    电脑系统为Win7 64位,安装的PLSql为64位,安装的Oracle客户端为运行时类型的,应该为32位客户端 电脑上之前安装的32位toad可以识别Oracle实例 在系统添加了oracle_ho ...

  5. C++ code:指针类型(pointer types)

    #include <iostream> using namespace std; int main() { float f = 34.5; int *ip = reinterpret_ca ...

  6. Luogu P4945 【最后的战役】

    本来以为做法一样,就是少带个$log$,结果发现看不懂出题人的题解(我好菜啊) 那就自己写一篇吧 比较简单的$DP$思路 状态定义: 前两个转移很好处理,第三个好像就不好办了 不妨暴力定义进状态里 设 ...

  7. python接口自动化测试二十一:类和方法

    # 类和方法 class Count(): def __init__(self, aaa, bbb): # 初始化 # 可以放公共的参数 print('实例化的时候,会执行init的内容') self ...

  8. day8--socketserver

    socketserver分类: 1.TCP协议 class socketserver.TCPServer(server_address,RequestHandlerClass,bind_and_act ...

  9. 使用sshtunnel实现python公网连接阿里云mongo服务器

    背景: 公司使用阿里云的云数据库MongoDB.基于安全原因考虑,阿里云MongoDB云数据库目前只支持从阿里云ECS上访问,无法通过公网直接访问,不方便用户在本地开发环境里直接进行测试. 阿里云官方 ...

  10. Linux useradd -M -s

    groupadd mysql #创建mysql分组 useradd -M(不创建主目录) -s(不允许登录) /sbin/nologin mysql -g(加入mysql组) mysql