GVKun编程网logo

java自带的工具Jstack截取进程中的堆栈信息(java获取堆栈命令)

16

如果您想了解java自带的工具Jstack截取进程中的堆栈信息和java获取堆栈命令的知识,那么本篇文章将是您的不二之选。我们将深入剖析java自带的工具Jstack截取进程中的堆栈信息的各个方面,并

如果您想了解java自带的工具Jstack截取进程中的堆栈信息java获取堆栈命令的知识,那么本篇文章将是您的不二之选。我们将深入剖析java自带的工具Jstack截取进程中的堆栈信息的各个方面,并为您解答java获取堆栈命令的疑在这篇文章中,我们将为您介绍java自带的工具Jstack截取进程中的堆栈信息的相关知识,同时也会详细的解释java获取堆栈命令的运用方法,并给出实际的案例分析,希望能帮助到您!

本文目录一览:

java自带的工具Jstack截取进程中的堆栈信息(java获取堆栈命令)

java自带的工具Jstack截取进程中的堆栈信息(java获取堆栈命令)

  在Java软件的使用过程中,有时会莫名的出现奇怪的问题。而这些问题常常无法使用日志信息定位,这时我们就需要通过查看进程内部线程的堆栈调用关系来分析问题出在哪里。

  举个例子,当我们在做某个操作时,莫名的会弹出多个警告框,其中有些信息是正常的,有些则不是。对于这些错误的警告信息,我们该如何定位是哪个位置的代码出现了错误弹出的框呢? 我们就需要在弹框以后,去查看软件的各个线程,去查找究竟是哪个线程导致了该问题。可是有时因为环境、时间等问题,我们根本不能拿着IDE去调试, 只能通过工具软件拍下内存快照,然后分析内存信息。

今天介绍一款常用的工具:Jstack

Jstack 是JDK自带的工具,同时也是在JVM性能调优种出镜率非常高的一款软件。所以掌握它是非常有必要的。

Jstack可以生成JVM当前时间点的线程快照。

线程快照就是当前JVM内每一条线程正在执行的方法堆栈的集合。而生成线程快照的主要原因:

1、通过线程快照定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待

2、通过线程快照分析当前执行方法的调用关系来确定异常信息的源头。

它的使用非常简单:

(ps:前提是你已经装有带有Jstack的JDK。同时最好已经设置了环境变量。)

第一步: 通过Windows的任务管理器查看进程的PID

这里简单说下什么是PID:PID就是各进程的身份标识,他是在软件启动后,由操作系统分配的唯一的、用来标识进程身份的一个标识

如图

在进程页签下,查看 > 选择列

勾选PID 然后确定

切到应用程序页签,选择要快照内存的程序。图片中选择的是Android Studio。点击右键转到进程。

这里就查看到 Android Studio对应的PID是 9952

第二步 打开命令行,执行Jstack程序

注意,如果没有成功添加环境变量,那么这里只能在Jstack的路径下执行,否则操作系统无法识别。

如图,这里一般有两个运行参数,用来拍取内存快照,

他们的含义如下:

-l long listings,会打印出额外的锁信息,在发生死锁时可以用jstack -l pid来观察锁持有情况

-m mixed mode,不仅会输出Java堆栈信息,还会输出C/C++堆栈信息(比如Native方法)

我们一般使用-l参数就可以满足需要

格式如下 Jstack -l PID >> 123.txt

ps 这里注意下 >>是重定向的意思,也就是将拍取到的快照定向输出到987.txt中。>> 的两次最好保持空格

这样我们就会在命令行路径下生成一个987.txt文件,同时将内存快照写入到这个文本中

如下图:

C# 编程中的堆栈(Stack)和队列(Queue)

C# 编程中的堆栈(Stack)和队列(Queue)

原文: C# 编程中的堆栈(Stack)和队列(Queue)

一、什么是堆?(Heap)

     堆是无序的,是一片不连续的内存域,由用户自己来控制和释放,如果用户自己不释放的话,当内存达到一定的特定值时,通过垃圾回收器(GC)来回收。

     是程序运行期间动态分配的内存空间,你可以根据程序的运行情况确定要分配的堆内存的大小。

二、什么是栈?(Stack)

     栈是有顺序的,是一片连续的内存域,保持着先进后出的原则,由系统自动分配和维护。

     是编译期间就分配好的内存空间,因此代码中必须就栈的大小有明确的定义。

     表尾允许进行插入删除操作,称为栈顶(Top,另一端是固定的,称为栈底(Bottom

     PS:

     线性表(Linear List)是具有相同特性的数据元素的一个有限序列。

     堆栈(Stack) 是一种特殊的线性表,是一种操作只允许在尾端进行插入或删除等操作的线性表。

     顺序栈(Sequence Stack)是用一片连续的存储空间来存储栈中的数据元素。

     链栈(Linked Stack)是用链式存储结构来存储的栈,链栈通常用单链表来表示。

三、什么是堆栈?

     由堆和栈的概念,可以清晰的知道,堆栈是一种数据项按序排列的数据结构,只能在一端称为栈顶(top)对数据项进行插入和删除。

     最后一个放入堆栈中的物体总是被最先拿出来,这个特性通常称为后进先出(LIFO队列。

     堆栈中定义了一些操作,两个最重要的是 PUSH 和 POP。PUSH 操作在堆栈的顶部加入一个元素,POP 操作相反,在堆栈顶部移去一个元素, 并将堆栈的大小减一。

     PS:通常所说的堆栈,实际上更偏向于指栈。

四、什么是队列?(Queue)

     队列是一种特殊的线性表,它只允许在表的前端(Front)进行删除操作,而在表的后端(Rear)进行插入操作。

     进行插入操作的表尾称为队尾(Rear),把进行其他操作的头部称为队头(Front)

     队列中没有元素时,称为空队列,队列具有先进先出(FIFO)的特点。

     PS:

     队列(Queue)是插入操作限定在表的尾部而其他操作限定在表的头部进行的线性表。

     顺序队列(Sequence Queue)用一片连续的存储空间来存储队列中的数据元素,类似于顺序表,用一维数组来存放队列中的数据元素。

     循环顺序队列(Circular sequence Queue)解决顺序队列的假溢出的方法是将顺序队列看成是首位相接的循环结构。

     链队列(Linked Queue)队列的另外一种存储方式是链式存储,通常用单链表表示。

五、堆、栈之间的区别是?

     堆实际上指的就是(满足堆性质的)优先队列的一种数据结构,第一个元素有最高的优先权

     栈实际上就是满足先进后出的性质的数学或数据结构。

     1、堆栈空间分配

     栈(操作系统):由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。

     堆(操作系统):一般由程序员分配释放, 若程序员不释放,程序结束时可能由 OS 回收,分配方式倒是类似于链表。

     2、堆栈缓存方式

     栈使用的是一级缓存, 他们通常都是被调用时处于存储空间中,调用完毕立即释放。

     堆则是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定(并不是一旦成为孤儿对象就能被回收)。所以调用这些对象的速度要相对来得低一些。

     3、堆栈数据结构区别

     堆(数据结构):堆可以被看成是一棵树,如:堆排序。

     栈(数据结构):一种先进后出的数据结构。

     特性: 最后一个放入堆栈中的物体总是被最先拿出来, 这个特性通常称为后进先出 (LIFO) 队列。

六、堆、栈、队列之间的区别是?

     是在程序运行时,而不是在程序编译时,申请某个大小的内存空间。即动态分配内存,对其访问和对一般内存的访问没有区别。

     就是一个桶,后放进去的先拿出来,它下面本来有的东西要等它出来之后才能出来。(先进后出 or 后进先出)

     队列只能在队头做删除操作,在队尾做插入操作。而栈只能在栈顶做插入和删除操作。(先进先出)

 

优秀是一种习惯,欢迎大家关注学习

Java 实例 - 获取异常的堆栈信息

Java 实例 - 获取异常的堆栈信息

以下实例演示了使用异常类的 printstack() 方法来获取堆栈信息:

/*
 author by w3cschool.cc
 Main.java
 */public class Main{
   public static void main (String args[]){
      int array[]={20,20,40};
      int num1=15,num2=10;
      int result=10;
      try{
         result = num1/num2;
         System.out.println("The result is" +result);
         for(int i =5;i *gt;=0; i--) {
            System.out.println("The value of array is" 
            +array[i]);
         }
      }
      catch (Exception e) {
         e.printStackTrace();
      }
   }}
登录后复制

以上代码运行输出结果为:

The result is1
java.lang.ArrayIndexOutOfBoundsException: 5
        at testapp.Main.main(Main.java:28)
登录后复制

以上就是Java 实例 - 获取异常的堆栈信息的内容。

Java 自带的性能监测工具之 jstat

Java 自带的性能监测工具之 jstat

本文使用 jstat 命令工具~

jstat 简介

 jstat (Java Virtual Machine Statistics Monitoring Tool) 是一个可以用于观察 Java 应用程序运行时信息的工具,主要利用 JVM 内建的指令对 Java 应用程序的资源和性能进行实时的命令行的监控,包括了对 Heap size 和垃圾回收状况的监控。

jstat 基本语法

使用 jstat -help 查看 jstat 基本语法以及基本的参数说明等~

[root@dev18 ~]# jstat -helpUsage: jstat -help|-options jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
Definitions: <option> An option reported by the -options option <vmid> Virtual Machine Identifier. A vmid takes the following form: <lvmid>[@<hostname>[:<port>]] Where <lvmid> is the local vm identifier for the target Java virtual machine, typically a process id; <hostname> is the name of the host running the target Java virtual machine; and <port> is the port number for the rmiregistry on the target host. See the jvmstat documentation for a more complete description of the Virtual Machine Identifier. <lines> Number of samples between header lines. <interval> Sampling interval. The following forms are allowed: <n>["ms"|"s"] Where <n> is an integer and the suffix specifies the units as milliseconds("ms") or seconds("s"). The default units are "ms". <count> Number of samples to take before terminating. -J<flag> Pass <flag> directly to the runtime system.[root@dev18 ~]#

jstat 可选项及其说明

使用 jstat -options 可以查看可使用的选择项,如 - class,-compiler 等

[root@dev18 ~]# jstat -options
-class
-compiler
-gc
-gccapacity
-gccause
-gcnew
-gcnewcapacity
-gcold
-gcoldcapacity
-gcpermcapacity
-gcutil
-printcompilation
[root@dev18 ~]#

options 说明~

-class                       显示class loader的信息 ,例如当前总共加载了多少个类

-compile 显示HotSpot Just-in-Time compiler的信息

-gc 显示jdk gcheap信息

-gccapacity 显示不同的generations相应的heap容量情况

-gccause 显示gc的情况,(同-gcutil)和引起gc的事件

-gcnew 显示gc时,新生代的情况

-gcnewcapacity 显示gc时,新生代heap容量

-gcold 显示gc时,老年区的情况

-gcoldcapacity 显示gc时,老年区heap容量

-gcpermcapacity 显示gc时,permanentheap容量

-gcutil 显示垃圾收集信息

-printcompilation 输出JIT编译的方法信息

 

    -gc 综合了 -gcnew、-gcold 的输出;

    -gccapacity 综合了 -gcnewcapacity、-gcoldcapacity、-gcpermcapacity 的输出

jstat 示例

显示 Java 进程的 ClassLoader 信息

输出 Java 进程(PID 为 12905)的 Class Loader 信息,每隔 2 秒执行一下,一共输出 5 次~

[root@dev18 ~]# jstat -class 12905 2000 5Loaded Bytes Unloaded Bytes Time 1515 2875.1 0 0.0 0.57 1515 2875.1 0 0.0 0.57 1515 2875.1 0 0.0 0.57 1515 2875.1 0 0.0 0.57 1515 2875.1 0 0.0 0.57[root@dev18 ~]#

其中,Loaded 表示载入了类的数量,Bytes 表示载入类的合计大小。

显示 JVM gc 信息

如下示例说明

[root@dev18 ~]# jstat -gc 12905 2000 5 S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT 512.0 512.0 0.0 64.0 14848.0 6236.9 40448.0 3532.2 21504.0 8729.3 91 0.172 0 0.000 0.172512.0 512.0 0.0 64.0 14848.0 6236.9 40448.0 3532.2 21504.0 8729.3 91 0.172 0 0.000 0.172512.0 512.0 0.0 64.0 14848.0 6236.9 40448.0 3532.2 21504.0 8729.3 91 0.172 0 0.000 0.172512.0 512.0 0.0 64.0 14848.0 6236.9 40448.0 3532.2 21504.0 8729.3 91 0.172 0 0.000 0.172512.0 512.0 0.0 64.0 14848.0 6236.9 40448.0 3532.2 21504.0 8729.3 91 0.172 0 0.000 0.172[root@dev18 ~]#

参数说明:

S0C     当前survivor space 0 的总容量 (KB).

S1C 当前survivor space 1 的总容量 (KB).

S0U 当前survivor space 0 已使用的容量 (KB).

S1U 当前survivor space 1 已使用的容量 (KB).

EC 当前 eden space 总容量 (KB).

EU 当前eden space已经使用的容量 (KB).

OC 当前 old space 总容量 (KB).

OU 当前old space 已使用容量(KB).

PC 当前 permanent space 总容量(KB).

PU 当前 permanent space 已使用容量 (KB).

YGC 从应用启动时到现在,年轻代young generation 发生GC Events的总次数.

YGCT 从应用启动时到现在, 年轻代Young generation 垃圾回收的总耗时.

FGC 从应用启动时到现在, full GC事件总次数.

FGCT 从应用启动时到现在, Full sc总耗时.

GCT 从应用启动时到现在, 垃圾回收总时间. GCT=YGCT+FGCT

查看 JIT 编译的信息

[root@dev18 ~]# jstat -compiler 12905Compiled Failed Invalid Time FailedType FailedMethod 263 0 0 2.92 0

显示垃圾收集信息

如:

[root@dev18 ~]# jstat -gcutil  12905
S0 S1 E O P YGC YGCT FGC FGCT GCT
0.00 12.50 48.01 8.73 40.59 91 0.172 0 0.000 0.172
[root@dev18 ~]#

 

[root@dev18 ~]# jstat -gcnew  12905
S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT
512.0 512.0 0.0 64.0 1 15 512.0 14848.0 7128.3 91 0.172
[root@dev18 ~]#

 

root@dev18 ~]# jstat -gcold  12905
PC PU OC OU YGC FGC FGCT GCT
21504.0 8729.3 40448.0 3532.2 91 0 0.000 0.172
[root@dev18 ~]#

还有很多示例,这里就不一一列举了~ 


本文分享自微信公众号 - 孟君的编程札记(gh_0f0f5e0ae1de)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与 “OSC 源创计划”,欢迎正在阅读的你也加入,一起分享。

Java内存泄漏分析系列之一:使用jstack定位线程堆栈信息

Java内存泄漏分析系列之一:使用jstack定位线程堆栈信息

原文地址:http://www.javatang.com

前一段时间上线的系统升级之后,出现了严重的高cpu的问题,于是开始了一系列的优化处理之中,现在将这个过程做成一个系列的文章。

基本概念

在对Java内存泄漏进行分析的时候,需要对jvm运行期间的内存占用、线程执行等情况进行记录的dump文件,常用的主要有thread dump和heap dump。

  • thread dump 主要记录JVM在某一时刻各个线程执行的情况,以栈的形式显示,是一个文本文件。通过对thread dump文件可以分析出程序的问题出现在什么地方,从而定位具体的代码然后进行修正。thread dump需要结合占用系统资源的线程id进行分析才有意义。
  • heap dump 主要记录了在某一时刻JVM堆中对象使用的情况,即某个时刻JVM堆的快照,是一个二进制文件,主要用于分析哪些对象占用了太对的堆空间,从而发现导致内存泄漏的对象。

上面两种dump文件都具有实时性,因此需要在服务器出现问题的时候生成,并且多生成几个文件,方便进行对比分析。下面我们先来说一下如何生成 thread dump。

使用jstack生成thread dump

当服务器出现高cpu的时候,首先执行 top -c 命令动态显示进程及占用资源的排行,如下图:


top后面的参数-c可以显示进程详细的信息。top命令执行的时候还可以执行一些快捷键:

  • 1 对于多核服务器,可以显示各个cpu占用资源的情况
  • shift+h 显示所有的线程信息
  • shift+w 将当前 top 命令的设置保存到 ~/.toprc 文件中,这样不用每次都执行快捷键了

以上图为例,pid为1503的进程占用了大量的cpu资源,接下来需要将占用cpu最高进程中的线程打印出来,可以用 top -bn1 -H -p <pid> 命令,执行结果如下:


上面 -bn1 参数的含义是只输出一次结果,而不是显示一个动态的结果。

我个人请喜欢用 ps -mp <pid> -o THREAD,tid,time | sort -k2r 命令查看,后面的sort参数根据线程占用的cpu比例进行排序,结果如下:

接下来我们清楚今天的主角 jstack,这是一个在JDK5开始提供的内置工具,可以打印指定进程中线程运行的状态,包括线程数量、是否存在死锁、资源竞争情况和线程的状态等等。有下面的几个常用的参数:

  • -l 长列表,打印关于锁的附加信息
  • -m 打印java和jni框架的所有栈信息

因为thread id在栈信息中是以十六进制的形式显示的,因此需要使用 printf "%x \n" <tid> 命令将现场id转成十六进制的值,然后执行 jstack -l <pid> | grep <thread-hex-id> -A 10 命令显示出错的堆栈信息,如下图:


上面命令中 -A 10 参数用来指定显示行数,否则只会显示一行信息。

这样通过上图,可以很快地定位到程序问题的代码,然后对代码进行分析和改进即可。注意:需要在多个时间段提出多个 Thread Dump信息,然后综合进行对比分析,单独分析一个文件是没有意义的。

生成shell文件

上面讲述了整个的分析过程,不过所有的命令就是实时的,所以最好创建一个shell脚本瞬间执行完成,下面对 当CPU飙高时,它在做什么 这篇文章中所提供的shell进行了改进如下:

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

37

38

39

40

41

#!/bin/bash

if [ $# -ne 1 ]; then

    echo "usage: $0 <pid> [line-number]"

    exit 1

fi

 

# java home

if test -z $JAVA_HOME

then

    JAVA_HOME='/usr/local/jdk'

fi

 

#pid

pid=$1

# checking pid

if test -z "$($JAVA_HOME/bin/jps -l | cut -d '' -f 1 | grep $pid)"

then

    echo "process of $pid is not exists"

    exit

fi

 

#line number

if test -z $linenum

then

    linenum=10

fi

 

stackfile=stack$pid.dump

threadsfile=threads$pid.dump

 

# generate java stack

$JAVA_HOME/bin/jstack -l $pid >> $stackfile

ps -mp $pid -o THREAD,time sort -k2r | awk '{if ($1 !="USER" && $2 != "0.0" && $8 !="-") print $8;}' xargs printf "%x\n" >> $threadsfile

tids="$(cat $threadsfile)"

for tid in $tids

do

    echo "------------------------------ ThreadId ($tid) ------------------------------"

    cat $stackfile | grep 0x$tid -A $linenum

done

 

rm -f $stackfile $threadsfile

关于java自带的工具Jstack截取进程中的堆栈信息java获取堆栈命令的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于C# 编程中的堆栈(Stack)和队列(Queue)、Java 实例 - 获取异常的堆栈信息、Java 自带的性能监测工具之 jstat、Java内存泄漏分析系列之一:使用jstack定位线程堆栈信息的相关信息,请在本站寻找。

本文标签:

上一篇使用Jackson来实现Java对象与JSON的相互转换的教程(jackson的json和java的转换)

下一篇JSP实现屏蔽浏览器缓存的方法(jsp实现屏蔽浏览器缓存的方法是)