通过 Javacore 了解线程运行状况

  Javacore 是一个当前 JVM 运行状态的快照。通过对Javacore 的分析,可以了解在 JVM 中运行的应用程序的当前状态,比如是否“卡”在某一点上,或在某些代码上运行时间太长。

Javacore 的基本内容

  Javacore,也可以称为“threaddump”或是“javadump”,它是 Java 提供的一种诊断特性,能够提供一份可读的当前运行的 JVM 中线程使用情况的快照。即在某个特定时刻,JVM 中有哪些线程在运行,每个线程执行到哪一个类,哪一个方法。

应用程序如果出现不可恢复的错误或是内存泄露,就会自动触发 Javacore 的生成。而为了性能问题诊断的需要,我们也会主动触发生成 Javacore。在 AIX、Linux、Solaris 环境中,我们通常使用 kill -3 <PID> 产生该进程的 Javacore。

  对于IBM JVM,AIX 平台上的 Javacore 会被写到 javacore.<date>.<time>.<PID>.<sequence>.txt 中。对于Oracle JVM,Javacore 被附加到native_stdout.txt。

    虽然不同版本的 JVM 所产生的 Javacore 的格式会稍有不同,但基本都包含下面几个内容:

  TITLE 信息块:描述 Javacore 产生的原因,时间以及文件的路径。最常见的有下面三种:

  1. user:SIGQUIT 信号
  2. gpf:程序一般保护性错误导致系统崩溃
  3. systhrow:JVM 内部抛出的异常

  GPINFO 信息块:GPF(一般保护性错误)信息

  ENVINFO 信息块:系统运行时的环境和 JVM 参数

  MEMINFO 信息块:内存使用情况和垃圾回收情况

  LOCKS 信息块:用户监视器(monitor)和系统监视器(monitor)情况

  THREADS 信息块:所有 java 线程的状态信息和执行堆栈

  CLASSES 信息块:类加载信息

  Javacore 中的线程可分为以下几种状态:

  • 死锁(Deadlock)【重点关注】:一般指多个线程调用间,进入相互资源占用,导致一直等待无法释放的情况。
  • 执行中(Runnable)【重点关注】:一般指该线程正在执行状态中,该线程占用了资源,正在处理某个请求,有可能在对某个文件操作,有可能进行数据类型等转换等。
  • 等待资源(Waiting on condition)【重点关注】:等待资源,如果堆栈信息明确是应用代码,则证明该线程正在等待资源,一般是大量读取某资源、且该资源采用了资源锁的情况下,线程进入等待状态。又或者,正在等待其他线程的执行等。
  • 等待监控器检查资源(Waiting on monitor)
  • 暂停(Suspended)
  • 对象等待中(Object.wait())
  • 阻塞(Blocked)【重点关注】:指当前线程执行过程中,所需要的资源长时间等待却一直未能获取到,被容器的线程管理器标识为阻塞状态,可以理解为等待资源超时的线程。这种情况在应用的日志中,一般可以看到 CPU 饥渴,或者某线程已执行了较长时间的信息。
  • 停止(Parked)

  通过对 Javacore 数据的分析经验,结合对具体应用代码逻辑的理解,有经验的工程师可以直接通过文本编辑器查看原始 Javacore 文件来分析当前应用程序的运行状态。一般初学者则需要通过一些工具进行更直观的分析。图形化分析工具 TMDA

  

WC 线程执行堆栈分析

  不论是否利用 TMDA 工具进行分析,对 Javacore 的分析最终都会落实在具体线程的执行堆栈上。如果对具体应用的代码不熟悉,那么看着一个个长长的执行堆栈,可能会觉得无从下手。本部分介绍 WC 线程执行堆栈的常见代码和对应的功能模块。初学者可以根据这些示例推测某个线程的当前运行状态。需要注意的是,WC 的不同版本,同样的功能模块的具体代码可能会发生变化,经过用户定制的代码就更是千差万别。本部分提供的只是依据 WC FEP7 版本代码的一些示例,读者需要根据自己所处理的系统的实际代码情况灵活掌握,不可拘泥。

  通常一个 Javacore 里面会有上百个线程,这些线程的地位并不一样。有些线程是系统运行的“入口线程”,而其他一些线程只是由这些线程派生出来的辅助线程。所以 Javacore 分析过程中一定要抓住这些主要线程。

  WC 的核心是一个 Web 应用,所以大部分 WC 的 Javacore 以应用服务器的 Web 容器为入口。用来处理前台商店或后台管理端的 JVM 基本类似,但专门运行定时任务的 JVM 会有所区别。下图 2 所示为以 Web 容器为入口线程的一般调用结构:

  从 Web 容器入口开始,一般会进入 Servlet 执行。如果有缓存而且命中的话,则会进入 DynaCache 的相关代码。如果无缓存或缓存不命中,如果是 JSP 页面,则会执行 JSP 的相关代码,否则会执行相应的逻辑。代码逻辑处理过程中,经常会访问到数据库(通过 DSL 或 EJB)或 Solr 搜索(通过 BOD 或 REST),还有可能访问到外部系统集成接口(通过 HTTP 同步调用或消息队列)。如果数据库服务器 / 搜索服务器 / 系统集成服务器分布在其他节点上,那么这些调用最终都会转化为网络访问。

以下为一个正在处理 JSP 页面中的数据库请求的执行堆栈示例,如图 3、4、5:

图 3. 堆栈实例(1)

图 4. 堆栈实例(2)

自下而上的关键代码:

  1. Web 容器处理请求:Package 名 / 类名 . 方法名:com.ibm.ws.webcontainer/WebContainer.handleRequest
  2. RuntimeFilter:Package 名 / 类名 . 方法名:com.ibm.commerce.webcontroller/RuntimeServletFilter.doFilterAction
  3. Servlet 处理:Package 名 / 类名 . 方法名:com.ibm.commerce.struts/ECActionServlet.doGet 或者 Package 名 / 类名 . 方法名:com.ibm.commerce.struts/ECActionServlet.doPost
  4. JSP 处理Package 名 / 类名 . 方法名:com.ibm._jsp/_(JSP 文件名 )._jspService
  5. Command 执行(图例为 BOD command):Package 名 / 类名 . 方法名:com.ibm.commerce.*/Abstract(*)CmdImpl.performExecute
  6. DSL:Package 名 / 类名 . 方法名:com.ibm.commerce.foundation.server.services.dataaccess/AbstractDataServiceFacade.*
  7. JDBC:

    查询 :Package 名 / 类名 . 方法名:com.ibm.ws.rsadapter.jdbc/WSJdbcPreparedStatement.executeQuery 或 Package 名 / 类名 . 方法名:com.ibm.ws.rsadapter.cci/WSResourceAdapterBase.executeQuery 
    
    更新:Package 名 / 类名 . 方法名:com.ibm.ws.rsadapter.jdbc/WSJdbcPreparedStatement.executeUpdate 或 Package 名 / 类名 . 方法名:com.ibm.ws.rsadapter.cci/WSResourceAdapterBase.executeUpdate
  8. 数据库驱动代码:DB2 Package 名:com.ibm.db2.* 或 Oracle Package 名 / 类名 . 方法名:oracle.jdbc.driver/OraclePreparedStatement.executeInternal
  9. 外部网络访问

    (网络读)Package 名 / 类名 . 方法名:java.net/SocketInputStream.socketRead0
    
    (网络写)Package 名 / 类名 . 方法名:java.net/SocketOutputStream.socketWrite0

  其他常见的执行堆栈举例:

  • 空闲(Idle

    这样的堆栈表示当前线程处于空闲状态(对于 Web 容器而言,即当前线程没有接收到 Web 请求)。其调用栈为:
    
    Package 名 / 类名 . 方法名:java.lang/Object/wait
    
    …
    
    Package 名 / 类名 . 方法名:com.ibm.ws.util/ThreadPool$Worker. run
    
    或者
    
    Package 名 / 类名 . 方法名:com.ibm.io.async/AsyncLibrary. aio_getioev*
    
    …
    
    Package 名 / 类名 . 方法名:com.ibm.ws.util/ThreadPool$Worker. run
  • 事务(Transaction)处理

    提交(Commit)
    
    Package 名 / 类名 . 方法名:com.ibm.commerce.server/TransactionManager.commit
    
    回滚(Rollback)
    
    Package 名 / 类名 . 方法名:com.ibm.commerce.server/TransactionManager.rollback
  • 缓存(DynaCache)读取

    Package 名 / 类名 . 方法名:com.ibm.ws.cache/Cache.getEntry(或 getCacheEntry)
    
    基于 WXS 的缓存则为
    
    Package 名 / 类名 . 方法名:com.ibm.ws.objectgrid.dynacache/RemoteCoreCacheImpl.get
  • MultiClick 处理:Package 名 / 类名 . 方法名:com.ibm.commerce.webcontroller.doubleclick/MultiClickRequestHandler. waitForResponse
  • 消息处理(MQ):Package 名 / 类名 . 方法名:com.ibm.mq.jmqi.remote.internal/RemoteRcvThread.run
  • 搜索(Solr)处理:Package 名 / 类名 . 方法名:org.apache.solr.client.solrj/SolrServer.query
  • REST 处理:Package 名 / 类名 . 方法名:com.ibm.commerce.foundation.internal.client.util/RESTHandler.execute

-----整理自:http://www.kankanews.com/ICkengine/archives/156577.shtml

时间: 2024-10-10 02:53:07

通过 Javacore 了解线程运行状况的相关文章

Linux Shell常用技巧(八) 系统运行状况

Linux Shell常用技巧(八) 系统运行状况 十八.  和系统运行状况相关的Shell命令:    1.  Linux的实时监测命令(watch):     watch   是一个非常实用的命令,可以帮你实时监测一个命令的运行结果,省得一遍又一遍的手动运行.该命令最为常用的两个选项是-d和-n,其中-n表示间隔多少秒 执行一次"command",-d表示高亮发生变化的位置.下面列举几个在watch中常用的实时监视命令:    /> watch -d -n 1 'who'  

多个线程运行MR程序时hadoop出现的问题

夜间多个任务同时并行,总有几个随机性有任务失败,查看日志: cat -n ads_channel.log |grep "Caused by" 7732 Caused by: java.util.concurrent.ExecutionException: java.io.IOException: Rename cannot overwrite non empty destination directory /tmp/hadoop-hdfs/mapred/local/1576781334

C#主线程等待子线程运行结束

佐左佑右 原文 C#主线程等待子线程运行结束 由于主程序中调用matlab的dll文件进行计算要用较长的时间,主界面会有很长时间的卡顿,造成的用户感受十分不好,因此我想在调用时,将调用放入子线程中,然后在主线程中弹出一个提示框,显示数据正在加载,等子线程运行结束后,主线程继续工作. 使用的是http://hi.baidu.com/oktell/item/5527f51d93abb4a5feded5a8中所提到的方法,用了这篇文章中的第一个方式,即不带参数的. 之后在其中加入了显示和关闭提示框的代

java线程中断和终止线程运行

ava中启动一个线程很容易,通常情况下我们都是等到任务运行结束后让线程自行停止.但有时需要在任务正在运行时取消他们,使得线程快速结束.对此Java并没有提供任何机制.但是我们可以通过Java提供的线程中断机制来实现. 首先来看Thread类三个和中断有关的方法: public class Thread { // 发出一个中断请求,把标志位设定为中断状态,不会终止线程运行. // 其他线程试图调用该方法,会检测是否有权限中断该线程(正常情况 // 下不会存在权限问题,这里可以忽略) public

监控 SQL Server (2005/2008) 的运行状况--来自微软TetchNet

原文地址:http://technet.microsoft.com/zh-cn/library/bb838723.aspx Microsoft SQL Server 2005 提供了一些工具来监控数据库.方法之一是动态管理视图.动态管理视图 (DMV) 和动态管理函数 (DMF) 返回的服务器状态信息可用于监控服务器实例的运行状况.诊断问题和优化性能. 常规服务器动态管理对象包括: dm_db_*:数据库和数据库对象 dm_exec_*:执行用户代码和关联的连接 dm_os_*:内存.锁定和时间

Python监控网站运行状况

利用python便捷的类库,可以方便快速实现对网站运行状况的监控,主要包括对80端口(即网站运行端口),其它tcp服务等端口的监控就可以了解服务器大概的一个运行状况,使用的库主要为urllib2及socket. 1.监控80端口或者其它网站运行端口,如tomcat ,nginx,iis等其它.监控这个比较简单,直接通过urllib2访问网站便可以了解网站的情况,如果不正常返回则会返回false.如下: def http_monitor(server_info): try: data = urll

线程运行机制

进程是指运行中的应用程序,每一个进程都有自己独立的内存空间.一个应用程序可以同时启动多个进程.每次执行JDK的java.exe程序,就启动一个独立的java虚拟机进程,该进程的任务是解析并执行java程序代码. 线程是指进程中的一个执行流程,同时也称为执行情景.一个进程可以由多个线程组成,即在一个进程中可以同时运行多个不同的线程,它们分别执行不同的任务.当进程内的多个线程同时运行,这种运行方式称为并发运行.许多服务器程序,如数据库服务器和Web服务器,都支持并发运行,这些服务器能同时响应来自不同

使用VisualVM分析tomcat运行状况(1)

VisualVM是一款java程序性能分析与调优工具,而且还是jdk中自带的工具之一. tomcat也是一个java程序,自然也可以用它来进行监控.不过这里还是会有些问题,tomcat有两种常用的期待方式,一种是通过startup.bat来启动:另一种是通过配置服务来启动. 如果使用stratup.bat启动,那么打开visualvm后会自动找到该tomcat程序:而如果使用服务期待tomcat的话,打开visualvm是无法自动找到该程序的,你需要再加一些配置. 在tomcat的/bin目录下

Linux 进程、线程运行在指定CPU核上

/******************************************************************************** * Linux 进程.线程运行在指定CPU核上 * 说明: * affinity参数决定了进程.线程是否可在CPU多核之间切换,当然,并不是说就不进行 * 线程切换. * * 2017-9-22 深圳 龙华樟坑村 曾剑锋 *********************************************************