CN102222037A - 用于定位java程序的瓶颈的方法和设备 - Google Patents

用于定位java程序的瓶颈的方法和设备 Download PDF

Info

Publication number
CN102222037A
CN102222037A CN2010101501108A CN201010150110A CN102222037A CN 102222037 A CN102222037 A CN 102222037A CN 2010101501108 A CN2010101501108 A CN 2010101501108A CN 201010150110 A CN201010150110 A CN 201010150110A CN 102222037 A CN102222037 A CN 102222037A
Authority
CN
China
Prior art keywords
java
thread
operating system
worker thread
task
Prior art date
Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
Granted
Application number
CN2010101501108A
Other languages
English (en)
Other versions
CN102222037B (zh
Inventor
王海川
钟虓
滕启明
李影
Current Assignee (The listed assignees may be inaccurate. Google has not performed a legal analysis and makes no representation or warranty as to the accuracy of the list.)
IBM China Co Ltd
Original Assignee
International Business Machines Corp
Priority date (The priority date is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the date listed.)
Filing date
Publication date
Application filed by International Business Machines Corp filed Critical International Business Machines Corp
Priority to CN201010150110.8A priority Critical patent/CN102222037B/zh
Priority to US13/086,609 priority patent/US20110258608A1/en
Publication of CN102222037A publication Critical patent/CN102222037A/zh
Application granted granted Critical
Publication of CN102222037B publication Critical patent/CN102222037B/zh
Expired - Fee Related legal-status Critical Current
Anticipated expiration legal-status Critical

Links

Images

Classifications

    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F11/00Error detection; Error correction; Monitoring
    • G06F11/36Preventing errors by testing or debugging software
    • G06F11/362Software debugging
    • G06F11/3644Software debugging by instrumenting at runtime
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F11/00Error detection; Error correction; Monitoring
    • G06F11/30Monitoring
    • G06F11/3003Monitoring arrangements specially adapted to the computing system or computing system component being monitored
    • G06F11/302Monitoring arrangements specially adapted to the computing system or computing system component being monitored where the computing system component is a software system
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F11/00Error detection; Error correction; Monitoring
    • G06F11/30Monitoring
    • G06F11/3089Monitoring arrangements determined by the means or processing involved in sensing the monitored data, e.g. interfaces, connectors, sensors, probes, agents

Landscapes

  • Engineering & Computer Science (AREA)
  • Theoretical Computer Science (AREA)
  • Computer Hardware Design (AREA)
  • Quality & Reliability (AREA)
  • Physics & Mathematics (AREA)
  • General Engineering & Computer Science (AREA)
  • General Physics & Mathematics (AREA)
  • Stored Programmes (AREA)
  • Debugging And Monitoring (AREA)

Abstract

本发明涉及用于定位Java程序的瓶颈的方法和设备。提供了一种用于定位Java程序的瓶颈的方法,包括以下步骤:在对应于所述Java程序的Java进程中创建辅助线程,并将所述辅助线程挂接到在该Java进程中创建的Java虚拟机;在操作系统内核中插入探测器;所述探测器监视所述Java进程中的Java线程在操作系统内核中的状态并且响应于检测到Java线程被阻塞而向所述辅助线程发送信号;以及所述辅助线程响应于接收到来自操作系统内核的所述信号,从所述JVM中取回调用栈信息,并利用所取回的调用栈信息定位到所述Java程序的源代码中的引起所述阻塞位置。

Description

用于定位JAVA程序的瓶颈的方法和设备
技术领域
本发明一般涉及计算机领域。更具体地说,本发明涉及一种用于检测并定位Java程序的瓶颈的方法和设备。
背景技术
Java语言是是一种可以编写跨平台应用软件的面向对象的程序设计语言。Java不同于一般的编译执行计算机语言(诸如C语言)和解释执行计算机语言(诸如HTML)。它首先将源代码编译成字节码(bytecode),然后依赖各种不同平台上的Java虚拟机(JVM)来解释执行字节码,从而实现了“一次编译、到处执行”的跨平台特性。
如今,Java已经成为企业应用程序的主流开发语言,理解Java线程如何工作是非常重要的。尤其当一个企业应用程序无法良好地利用下层的硬件服务器时,就需要找出在CPU利用率低的情况下一些应用程序线程仍然被阻塞的原因。不过,Java应用程序具有如下性质:在硬件和应用程序代码之间存在许多层,这些层包括但不限于硬件层、操作系统层(也称作本地层)、Java虚拟机层、中间件层以及应用程序层。
由于上述的原因,如果发现CPU的利用率低,难以在Java源代码中找到问题所在。但是应用程序开发者恰恰需要定位Java源代码中的问题从而能够解决该问题。
例如,图1A示出了JVM层的线程状态,我们发现很多应用程序线程在Java虚拟机层是可运行的,并且在Java虚拟机层不存在明显的问题。但是,图1B示出了本地层中的、与JVM层的线程对应的线程的状态,如图1B所示,存在许多的线程阻塞。因此,Java应用程序开发者需要弄清楚在CPU利用率低的情况下线程为什么被阻塞以及源代码中的哪个地方导致了发生该问题。
在现有技术中,已经存在很多监视及瓶颈分析工具。下面举例说明现有技术中存在的各种工具。
例如,存在一种本地瓶颈分析工具,该瓶颈分析工具查看执行栈中的一层以定位瓶颈。这种本地层瓶颈分析工具例如包括LockStat,该LockStat提供针对锁的统计结果。这种瓶颈分析工具的缺点在于:对于例如锁的每种资源,均需要一种专用的工具,这导致对于本地层的多种资源,需要很多的专用工具对每种资源进行监视和分析。此外,这种瓶颈分析工具只能在本地层即操作系统层中进行监视,而无法将在本地层中发生的事件与Java源代码的相应部分联系起来。
此外,存在一种筛选工具,该筛选工具跨越多层架构的各层进行查找以定位可疑的瓶颈。这种筛选工具主要用于多层架构的Web开发框架,其示例为哥伦比亚大学Watson实验室的WAIT。所述多层架构典型地包括:Web层、应用层以及数据库层。这种筛选工具仅能在该多层框架结构中识别引起可以瓶颈的节点(即硬件服务器)。因此,这种筛选工具识别的是包含多个节点的系统中导致瓶颈的节点,但是并不能在源代码中定位瓶颈。
此外,目前还存在Java运行时监视工具,诸如jstack和JFluid。该jstack工具可以进行运行时栈分析,但是这种工具具有显著的性能开销,甚至会干扰应用程序的行为。而JFluid工具监控与特定资源相关的所有函数调用,这种工具同样具有显著的性能开销,因为即使有些函数调用与线程阻塞并无关联,JFluid仍会记录所有的函数调用。此外,jstack和JFluid属于JVM层的监控工具,它们对JVM层中的瓶颈进行监视,但是无法监视位于JVM层之下的本地层中的线程状态。
发明内容
现有技术的各种工具都不能实现根据本地层中的瓶颈找出Java源代码中引起该瓶颈的精确位置的功能。
因此,需要提供一种能够将本地层中的瓶颈链接回Java源代码的有效方法。
为了解决上述问题,本发明的主要目的是提供一种用于检测并定位Java程序的瓶颈的方法和设备。该方法和设备能够将本地层中的瓶颈链接回Java源代码。此外,该方法和设备没有明显的性能开销,不会对目标应用程序的正常运行产生不利影响。
根据本发明的一方面,提供了一种用于定位Java程序的瓶颈的方法,包括以下步骤:在对应于所述Java程序的Java进程中创建辅助线程,并将所述辅助线程挂接到在该Java进程中创建的Java虚拟机;在操作系统内核中插入探测器;所述探测器监视所述Java进程中的Java线程在操作系统内核中的状态并且响应于检测到Java线程被阻塞而向所述辅助线程发送信号;以及所述辅助线程响应于接收到来自操作系统内核的所述信号,从所述JVM中取回调用栈信息,并利用所取回的调用栈信息定位到所述Java程序的源代码中的引起所述阻塞位置。
根据本发明的另一方面,提供了一种用于定位Java程序的瓶颈的设备,包括:用于在对应于所述Java程序的Java进程中创建辅助线程,并将所述辅助线程挂接到在该Java进程中创建的Java虚拟机的装置;用于在操作系统内核中插入探测器的装置;用于由所述探测器监视所述Java进程中的Java线程在操作系统内核中的状态并且响应于检测到Java线程被阻塞而向所述辅助线程发送信号的装置;以及用于在所述辅助线程响应于接收到来自操作系统内核的所述信号从所述JVM中取回调用栈信息,并利用所取回的调用栈信息定位到所述Java程序的源代码中的引起所述阻塞的位置的装置。
采用本发明的上述设备和方法,能够将本地层中的瓶颈准确地链接回Java源代码,即找到引起所述本地层中的瓶颈的Java源代码的相应位置。因此,上述设备和方法能够在JVM层中没有任何指示的情况下,找到Java线程状态改变的原因。此外,上述方法是独立且自足的方法,不需要其它的监视器或工具的帮助。另外,上述设备和方法没有明显的性能开销,不会对目标应用程序的正常运行产生不利影响。
附图说明
以下通过结合附图阅读参考下述对说明性实施例的详细描述,将更好地理解本发明本身、实施方式、其它目的及其优点。在附图中:
图1A和图1B示出了JVM层的线程状态和本地层的线程状态之间的差别;
图2是示出本发明的总体发明构思的示意图;
图3示出了根据本发明的一个实施例的方法流程;
图4是示出了用户空间中的Java线程和内核空间中的本地任务之间的关系的示意图;
图5是示出了图3中的步骤320的处理的一个示例的示意图;
图6是示出了图3中的步骤340的处理的一个示例的示意图;以及
图7是示出了在四核处理器的情况下的辅助线程示例的示意图。
现在参照附图描述优选方法和系统,其中,在附图中相同的附图标号用来指相同的部件。在下面的描述中,为了解释的目的,阐述大量特定的细节,以便帮助完全了解系统及方法等。在其它的例子中,为了简化描述,以框图的形式示出常用的结构和装置。对于本领域技术人员来说,可以想到很多修改和其它实施例,同时拥有在说明书和附图中所教导的益处。因此,应该理解,本发明不局限于所公开的特定实施例,另外可选的实施例应当包含在本发明的范围和范例发明构思内。虽然本文采用了一些特定术语,但是仅仅为了一般的描述意义而非限制目的使用它们。
具体实施方式
以下将参照附图对本发明的具体实施方式进行详细说明。在以下的说明中,术语“内核空间”和“用户空间”是针对操作系统的内核而言的。在本发明中,操作系统可以是诸如Unix、Linux以及Windows的各种操作系统。为了简单起见,在本发明中,仅以Linux作为操作系统的示例。但是本领域的技术人员应该明白,本发明的方法和设备同样适用于其它操作系统。
Linux的虚拟地址空间为0至4G。Linux内核将这4G字节的空间分为两部分。将最高的1G字节(从虚拟地址0xC0000000到0xFFFFFFFF)供内核使用,称为“内核空间”。而将较低的3G字节(从虚拟地址0x00000000到0xBFFFFFFF)供各个进程使用,称为“用户空间”。因为每个进程可以通过系统调度进入内核,因此,Linux内核由系统内的所有进程共享。内核空间中存放的是内核代码和数据,而进程的用户空间中存放的是用户程序的代码和数据。
图2是示出本发明的总体发明构思的示意图。在本发明中,在作为监视目标的Java进程中创建辅助线程,并且在操作系统的调度器中插入探测器。当该探测器检测到该Java进程中的线程被阻塞时,向所述辅助线程发送用户定义的信号,接收到该用户定义的信号的辅助线程到JVM的栈中取回此时的调用栈信息,从而可以定位到Java源代码中的精确位置。这样就实现了将本地层中的瓶颈准确地链接回Java源代码。
参照图3,本发明提供了一种用于检测并定位Java程序的瓶颈的方法。图3示出了根据本发明的一个实施例的方法流程300,包括如下步骤:
步骤310:创建辅助线程,并将其挂接到JVM。
步骤320:在操作系统内核中插入探测器。
步骤330:探测器监视Java线程并且在Java线程被阻塞时向辅助线程发送信号。
步骤340:辅助线程接收信号,从JVM中取回调用栈信息并利用该信息定位到Java源代码中的对应位置。
这里需要说明的是,Java程序在被运行时表现为用户空间中的进程。JVM对应于一个独立运行的Java程序,即对应于一个Java进程。当启动一个Java程序时,一个JVM实例就被启动起来了,任何一个拥有public static void main(String[]args)函数的类都可以作为Java程序运行的起点在JVM上运行。
下面详细描述本发明的方法流程300中的各个步骤。
步骤310:创建辅助线程,并将其挂接到JVM
在步骤310中,在对应于所述Java程序的Java进程中创建辅助线程,并将所述辅助线程挂接到在该Java进程中创建的Java虚拟机。
例如,可以通过Java虚拟机工具接口(JVMTI)提供的回调机制来创建辅助线程,并且通过Java本地接口(JNI)提供的方法将创建的辅助线程挂接到JVM上。JVMTI可以用来监控JVM的一些行为。JNI是为了扩展Java标准类库以使之支持依赖于平台的特性而提供的接口。JNI接口允许以较低级的语言实现代码的一部分,然后令Java应用程序来调用这些以较低级语言编写的函数。
具体地说,在JVM启动初始化完成的位置设置回调函数。例如,利用JVMTI,通过以下代码来启动响应虚拟机初始化事件的回调函数机制。
jvmtiEventCallbacks callbacks;//声明
memset(&callbacks,0,sizeof(callbacks));//初始化
callbacks.VMInit=&vmInit;//编写的回调函数的入口
jvmti->SetEventCallbacks(&callbacks,sizeof(callbacks));//完成设置
jvmti->SetEventNotificationMode(JVMTI_ENABLE,JVMTI_EVENT_VM_INIT,NULL);//启用对虚拟机初始化事件的通知
上述代码的功能是把程序员自己编写的回调函数vmInit()的地址赋值给jvmtiEventCallbacks类型的callbacks结构的变量VMInit,该变量表示在虚拟机初始化事件发生时调用的回调函数的入口。通过调用SetEventCallbacks()方法完成设置,并且通过调用SetEventNotificationMode()方法启动对虚拟机初始化事件的通知,完成了回调函数vmInit()的设置。这样,当虚拟机初始化时,回调函数vmInit()就会被执行。要注意的是,为了便于说明,在本文中,不对公知方法或函数的参数进行描述,例如只简单将其表示为function()。而对于用户自定义的函数,由于其参数可以由用户任意定义,因此也省略对这种函数的参数的定义和描述。本领域技术人员通过这种描述完全能够知道如何实现本发明的方法。
在回调函数vmInit()中,调用JVMTI的RunAgentThread()方法创建新的辅助线程。
这里,需要说明的是,在一个创建了JVM的进程中,并不是所有线程都能够直接使用JVM。为了区别于创建的辅助线程,Java进程中的对应于Java应用程序的线程在本文中被称为“Java应用线程”,而Java应用线程和辅助线程统称为Java线程。Java应用线程能够直接访问JVM,而辅助线程不能直接访问JVM。这就需要通过JNI接口提供的AttachCurrentThread()方法将当前的辅助线程挂接(attach)到JVM环境上。进行上述挂接的目的是为了使辅助线程能够实现对JVM中的栈的访问。为了使辅助线程能够对线程阻塞事件进行快速反应,需要将辅助线程设置为高的调度优先级。
在描述步骤320之前,需要对用户空间中的Java线程和内核空间中的对应线程(这里称为本地任务(native task))之间的关系进行描述。Java线程的调用栈位于用户空间中的JVM内,而本地任务的调用栈位于内核空间中。当一个Java进程通过系统调度进入内核时,其Java线程在内核中对应于一个本地任务,该本地任务被内核的调度器调度进入处理器而执行。
当一个Java进程存在多个Java应用线程时,这些Java应用线程分别对应于内核中的一个本地任务,并且在上述的步骤310中创建的辅助线程同样对应于内核中的一个本地任务。如图4所示。图4是示出了用户空间中的Java线程和内核空间中的本地任务之间的关系的示意图。在图4中,示例性地示出了三个Java应用线程以及创建的辅助线程。Java应用线程1至Java应用线程1分别对应于本地任务1至本地任务3,辅助线程对应于本地任务4。Java线程在用户空间中通过Java线程ID进行识别,但是本地任务在内核空间中通过本地任务ID进行识别。此外,在JVM中有每个Java线程的对应栈。当在内核空间中检测到一个本地任务(例如本地任务2)被阻塞时,需要知道在用户空间中与之对应的Java线程(例如Java应用线程2),从而能够访问该Java线程的在JVM中的调用栈。
为了实现上述目的,可以在每个Java线程启动时,通过回调函数建立该Java线程和操作系统内核中的对应于该Java线程的本地任务之间的映射关系。具体地说,与步骤310类似,在JVM启动时设置回调函数。例如,利用JVMTI,通过以下代码来启动响应线程启动事件的回调函数机制。
jvmtiEventCallbacks callbacks;//声明
memset(&callbacks,0,sizeof(callbacks));//初始化
callbacks.ThreadStart=&threadStart;//编写的回调函数的入口
jvmti->SetEventCallbacks(&callbacks,sizeof(callbacks));//完成设置
jvmti->SetEventNotificationMode(JVMTI_ENABLE,JVMTI_EVENT_THREAD_START,NULL);//启用对线程启动事件的通知
上述代码的功能是把程序员自己编写的回调函数threadStart()的地址赋值给jvmtiEventCallbacks类型的callbacks结构的变量ThreadStart,该变量表示在线程启动事件发生时调用的回调函数的入口。通过调用SetEventCallbacks()方法完成设置,并且通过调用SetEventNotificationMode()方法启动对线程启动事件的通知,完成了回调函数threadStart()的设置。这样,当Java线程启动时,回调函数threadStart()就会被执行。
在回调函数threadStart()中,首先调用操作系统内核提供的系统调用函数,例如gettid(),获得当前Java线程的在内核空间中对应的本地任务的ID,即本地任务ID。然后,再调用JNI提供的机制,获得当前线程在JVM中的ID,即Java线程ID。然后,将获得的本地任务ID和Java线程ID相关联地存储到如图4所示的映射数据库中。通过上述方式,每当有线程启动时,该线程都会调用回调函数threadStart()将其在用户空间的Java线程ID与其在内核空间的本地任务ID之间的映射关系存储起来。下面的表1示出了在图4的情况下建立的映射关系的可能的例子。
表1
  本地任务ID   Java线程ID  图4中的对应线程
  5893   1   应用线程1
  5901   2   应用线程2
  5925   3   应用线程3
  6012   21   辅助线程
这里需要说明的是,在映射数据库中实际只存储表1中的“本地任务ID”和“Java线程ID”这两栏,最后一栏是为了参照图4进行说明从而更好地理解本发明而加入的。此外,需要说明的是,在Java程序是多线程程序时才需要如上所述建立映射数据库。也就是说,当Java程序只有以main()作为起点的一个主线程时,可以省略上述的建立映射数据库的步骤。为了更好地描述本发明,下面以多线程程序的情况(即,建立了映射数据库的情况)作为示例,继续对方法流程300的其余步骤进行说明。
步骤320:在操作系统内核中插入探测器
首先,说明何为探测器。操作系统提供了事件回调机制以用于系统调试和扩展。例如,在Linux系统中,就提供了Kprobe/Jprobe机制。该机制允许在内核的特定代码处插入用户自定义的函数,这种函数被称为“Prober(探测器)”。
可以通过多种手段在操作系统内核中插入探测器。例如,可以由辅助线程通过JNI接口调用以内核的编程语言编写的函数而直接在内核调度器中插入作为探测器的相应函数。但是,为了更快速更高效地实现上述目的,可以利用操作系统提供的动态加载模块的机制,这种机制的好处在于可以让核心保持很小的尺寸同时非常灵活。这种机制允许将用户编写的模块加载到内核中与内核一起工作。为了实现在操作系统内核中插入探测器,还可以采用以下方式:预先编写一个内核监视模块;将该内核监视模块加载到内核中工作;由辅助线程向该内核监视模块传递参数并控制该内核监视模块来插入探测器。通过这样做,与由辅助线程直接插入探测器的方式相比,简化了辅助线程的工作,并且利用内核级的模块来实现探测器的插入,实现了更快的速度,使本发明的性能开销更小。
具体地说,例如,在Linux系统中,执行insmod命令来显式加载内核模块。根据本发明的一个实施例的内核监视模块就是通过执行insmod命令被加载到内核中的。该内核监视模块在被加载到内核中后,除非执行rmmod命令,否则将一直在内核中工作。
图5是示出了步骤320的处理的一个示例的示意图。在该实施例中,探测器是被加载到操作系统内核中的用户定义的模块(即上述的内核监视模块)插入到操作系统的调度器中的。辅助线程在被创建后,向该已加载的内核监视模块登记作为监视目标的Java进程的内核ID以及对辅助线程对应的本地任务ID。然后,内核监视模块将根据所登记的进程ID和辅助线程ID编写的回调函数插入到调度器中。
具体地,例如在Linux系统中,通过下述代码完成探测器的插入:
jprobe.kp.symbol_name=_switch_to;
jprobe.entry=j_switch_to;
其中,第一行语句指定要插入的内核代码位置,第二行语句指定了用户自定义的回调函数j_switch_to。这样就实现了在_switch_to这个内核函数中插入我们自定义的回调函数j_switch_to。即,每当内核函数_switch_to被调用时,就会调用j_switch_to。本领域技术人员公知的是,_switch_to函数每次在发生任务上下文切换时被调用,也就是说,同样地,被插入的探测器j_switch_to每当发生任务上下文切换时执行操作。
步骤330:探测器监视Java线程并且在Java线程被阻塞时向辅 助线程发送信号
在步骤330中,探测器监视所述Java进程中的Java线程在操作系统内核中的状态并且响应于检测到Java线程被阻塞而向所述辅助线程发送信号。
由于探测器j_switch_to被插入在_switch_to函数中,所以它可以获得_switch_to的全部参数,从而可以知道从处理器中调出而触发了任务上下文切换事件的本地任务的状态以及该本地任务属于哪个进程。也就是说,我们可以在自定义函数j_switch_to中定义探测器的行为来实现步骤330的处理。
探测器在步骤320中例如从内核监视模块获得了两个参数:JAVA进程的内核ID(PID)以及对应于辅助线程的本地任务的ID(HTID)。这两个参数是由辅助线程向内核监视模块登记的。在探测器中实现如下的判断逻辑:如果在处理器执行任务上下文切换时从处理器调出的本地任务对应于所述Java进程中的Java线程并且该本地任务处于阻塞状态,则由所述探测器向所述辅助线程发送信号。即,在同时满足(1)调出的本地任务属于PID指示的进程以及(2)调出的本地任务处于阻塞状态这两个条件的情况下,才向HTID指示的线程发送信号。
需要说明的是,一个本地任务从处理器调出可能有多种原因,其可能因为处于阻塞状态,也可能是因为分配的时间片届满而被调出处理器。在这些情况下都会调用探测器。因为必须满足条件(2)才发送信号,所以仅仅因为分配的时间片届满而被调出处理器的本地任务并不会触发向辅助线程发送信号,从而大大减小了性能开销。
所述发送信号可以采用多种方式进行。在一个实施例中,例如在Linux系统中,可以采用系统函数send_signal向辅助线程发送预先指定的信号。辅助线程一直等待在该信号上,辅助线程在信号被发出后被唤醒并接收该信号。在另一个实施例中,可以在用户空间和内核空间之间建立通信通道,并且当同时满足上述的条件(1)和(2)时,探测器通过该通信通道与辅助线程通信以通知检测到阻塞。不论采用哪种方式,向辅助线程发送的信号包含被阻塞的本地任务的ID。
步骤340:辅助线程接收信号,从JVM中取回调用栈信息并利用 该信息定位到Java源代码中的对应位置
在步骤340中,辅助线程响应于接收到来自操作系统内核的信号从所述JVM中取回调用栈信息,并利用所取回的调用栈信息定位到所述Java程序的源代码中的对应位置。其中从所述JVM中取回调用栈信息的步骤包括:根据本地任务的ID和映射关系从所述JVM中取回与该本地任务对应的Java线程的调用栈信息。
图6是示出了步骤340的处理的一个示例的示意图。图6的处理对应于在多线程程序下在线程启动时建立了映射数据库的情况。首先,在步骤1中,辅助线程接收到来自内核的信号,该信号包含被阻塞的本地任务的ID。为了便于理解,以图4的示例进行说明,这里假定接收到的本地任务ID是5901。然后,在步骤2中,辅助线程查询预先建立的映射数据库,例如表1所示的数据结构。在本地任务ID是5901的情况下,从映射数据库中查到对应的Java线程ID(在表1的情况下为2)。也就是说,辅助线程得到内核的通知:Java应用线程2在内核中被阻塞。然后,在步骤3中,辅助线程根据查到的Java线程ID(即2),从JVM中的与Java应用线程2对应的栈取回调用栈信息。
具体地,可以利用JVMTI提供的GetFrameLocation()方法获得指定线程的栈的当前执行到的方法的方法名和位置。然后,利用获得的方法名调用JVMTI提供的GetLineNumberTable()方法,获得当前执行到的方法的位置和行号的对应表。通过该表可以查出现在该线程运行到所述方法的哪一行,从而实现了定位到Java源代码中的对应位置。所述对应位置可以被显示给调试人员,也可以被保存起来以供以后进行瓶颈分析。
最后,描述一种特殊情况的处理。本领域技术人员了解,与普通的Java应用线程一样,在本发明中创建的辅助线程同样是Java线程,并且Java应用线程和辅助线程位于同一进程内,例如,如图4的情况所示。此外,辅助线程同样对应于内核空间中的一个本地任务。另一方面,在步骤330中,在探测器即j_switch_to函数中进行监视的目标是进程,即监视被调出的本地任务是否属于作为监视目标的进程。如上所述,这是通过检查是否满足条件(1)而实现的。因此,当辅助线程自身被阻塞时,由于在探测器中会检测到同时满足了条件(1)以及条件(2),所以在这种情况下探测器也会向辅助线程发送信号。但是,这种信号是无用的,与我们想要监视的Java程序的源代码本身涉及到瓶颈的部分没有关系,需要忽略这种信号。
可以采用多种方式来忽略由辅助线程本身被阻塞而引发的信号。例如,至少可以采用以下两种方法。
第一种方法是在探测器中进行额外的判断。除了条件(1)调出的本地任务属于PID指示的进程以及(2)调出的本地任务处于阻塞状态这两个条件之外,进一步设置条件(3):调出的本地任务的ID与对应于辅助线程的本地任务的ID不同,即,被调出的本地任务不对应用户空间的辅助线程。然后,在同时满足这三个条件的情况下,才向辅助线程发送信号。
第二种方法是在辅助线程中进行判断。当辅助线程从操作系统内核接收到包含被阻塞的本地任务的本地任务ID时(图6中的步骤1),辅助线程查询预先建立的映射数据库(图6中的步骤2),例如表1所示的数据结构。在假定本地任务ID是6012的情况下,从映射数据库中查到对应的Java线程ID(在表1的情况下为21)。辅助线程将获得的Java线程ID与自身的Java线程ID进行比较,当这两者匹配时,即表示辅助线程自身在内核中被阻塞。此时,辅助线程忽略该信号,跳过图6中的步骤3的执行。
在上文中,详细描述了根据本发明的实施例的方法流程300。方法流程300适用于单核处理器的情况。
本发明的用于检测并定位JAVA程序的瓶颈的方法同样适用于多核处理器的情况。在执行Java程序的处理器是多核处理器的情况下,创建多个辅助线程。图7是示出了在四核处理器的情况下的辅助线程示例的示意图。在图7中,创建的辅助线程的数目与多核处理器的核数目相同。即,在四核处理器的情况下,创建了四个辅助线程1至4。然后,将这四个辅助线程中的每一个分别绑定到多核处理器的一个核。即,将辅助线程1绑定到处理器核1,将辅助线程2绑定到处理器核2,将辅助线程3绑定到处理器核3,并且将辅助线程4绑定到处理器核4。
实现上述功能,需要对方法流程中的步骤310进行如下修改。
在回调函数vmInit()中,根据处理器核的数目,调用JVMTI的RunAgentThread()方法创建相等的数目的辅助线程。然后,通过JNI接口提供的AttachCurrentThread()方法将每个运行的当前辅助线程挂接到JVM上,让其可以访问JVM的堆栈信息。将这些辅助线程设置为较高的调度优先级。然后,调用系统调用函数sched_setaffinity(),将每个线程绑定到一个处理器核上。这样,四个辅助线程被一一对应地绑定到四个处理器核上,从而可以按照与单核处理器上的单个辅助线程相似的方式执行处理。
需要注意的是,四核处理器仅仅是一个示例。本发明同样适用于双核处理器、八核处理器以及具有更多核的处理器。
采用本发明的上述方法,能够将本地层中的瓶颈准确地链接回Java源代码,即找到引起所述本地层中的瓶颈的Java源代码的相应位置。因此,上述方法能够在JVM层中没有任何指示的情况下,找到Java线程状态改变的原因。此外,上述方法是独立且自足的方法,不需要其它的监视器或工具的帮助。另外,上述方法由于采用信号机制,不会在每次方法被调用时都记录栈信息,所以没有明显的性能开销,不会对目标应用程序的正常运行产生不利影响。
本领域技术人员会认识到,可以以方法、系统或计算机程序产品的形式提供本发明的实施例。因此,本发明可采取全硬件实施例、全软件实施例,或者组合软件和硬件的实施例的形式。硬件和软件的典型的结合可以是带有计算机程序的通用计算机系统,当程序被加载并被执行时,控制计算机系统,从而可以执行上述的方法。
本发明可以嵌入在计算机程序产品中,它包括使此处描述的方法得以实施的所有特征。所述计算机程序产品被包含在一个或多个计算机可读存储介质(包括,但不限于,磁盘存储器、CD-ROM、光学存储器等)中,所述计算机可读存储介质具有包含于其中的计算机可读程序代码。
已参考根据本发明的方法、系统及计算机程序产品的流程图和/或方框图说明了本发明。流程图和/或方框图中的每个方框,以及流程图和/或方框图中的方框的组合显然可由计算机程序指令实现。这些计算机程序指令可被提供给通用计算机、专用计算机、嵌入式处理器或者其他可编程的数据处理设备的处理器,以产生一台机器,从而指令(所述指令通过计算机或者其他可编程数据处理设备的处理器)产生用于实现在流程图和/或方框图的一个或多个方框中规定的功能的装置。
这些计算机程序指令也可保存在一个或多个计算机的读存储器中,每个这种存储器能够指挥计算机或者其他可编程数据处理设备按照特定的方式发挥作用,从而保存在计算机可读存储器中的指令产生一种制造产品,所述制造产品包括实现在流程图和/或方框图的一个或多个方框中规定的功能的指令装置。
计算机程序指令也可被加载到一个或多个计算机或者其他可编程数据处理设备上,使得在所述计算机或者其他可编程数据处理设备上执行一系列的操作步骤,从而在每个这样的设备上产生计算机实现的过程,以致在该设备上执行的指令提供用于实现在流程图和/或方框图的一个或多个方框中规定的步骤。
以上结合本发明的实施方式对本发明的原理进行了说明,但这些说明只是示例性的,不应理解为对本发明的任何限制。本领域技术人员可以对本发明进行各种改变和变形,而不会背离由随附权利要求所限定的本发明的精神和范围。

Claims (18)

1.一种用于定位Java程序的瓶颈的方法,包括以下步骤:
在对应于所述Java程序的Java进程中创建辅助线程,并将所述辅助线程挂接到在该Java进程中创建的Java虚拟机JVM;
在操作系统内核中插入探测器;
所述探测器监视所述Java进程中的Java线程在操作系统内核中的状态并且响应于检测到Java线程被阻塞而向所述辅助线程发送信号;以及
所述辅助线程响应于接收到来自操作系统内核的所述信号,从所述JVM中取回调用栈信息,并利用所取回的调用栈信息定位到所述Java程序的源代码中的引起所述阻塞的位置。
2.根据权利要求1所述的方法,其中,在执行所述Java程序的处理器是多核处理器的情况下,创建多个所述辅助线程。
3.根据权利要求2所述的方法,其中,创建的多个所述辅助线程的数目与多核处理器的核数目相同。
4.根据权利要求3所述的方法,其中,创建的多个所述辅助线程中的每一个被分别绑定到多核处理器的一个核。
5.根据权利要求1所述的方法,还包括:响应于每个Java线程的启动,通过回调函数建立该Java线程和操作系统内核中的对应于该Java线程的本地任务之间的映射关系。
6.根据权利要求5所述的方法,其中,所述信号包含被阻塞的本地任务的ID,并且其中,从所述JVM中取回调用栈信息包括:根据本地任务的ID和所述映射关系,从所述JVM中取回与该本地任务对应的Java线程的调用栈信息。
7.根据权利要求1所述的方法,其中,所述探测器被插入在操作系统的调度器中并且在发生任务上下文切换的情况下执行操作。
8.根据权利要求7所述的方法,其中,所述探测器是被加载到操作系统内核中的用户自定义的模块插入到所述调度器中的。
9.根据权利要求7或8所述的方法,其中,响应于检测到Java线程被阻塞而向所述辅助线程发送信号包括:如果在处理器执行任务上下文切换的情况下从处理器调出的本地任务对应于所述Java进程中的Java线程并且该本地任务处于阻塞状态,则由所述探测器向所述辅助线程发送信号。
10.一种用于定位Java程序的瓶颈的设备,包括:
用于在对应于所述Java程序的Java进程中创建辅助线程,并将所述辅助线程挂接到在该Java进程中创建的Java虚拟机JVM的装置;
用于在操作系统内核中插入探测器的装置;
用于由所述探测器监视所述Java进程中的Java线程在操作系统内核中的状态并且响应于检测到Java线程被阻塞而向所述辅助线程发送信号的装置;以及
用于在所述辅助线程响应于接收到来自操作系统内核的所述信号从所述JVM中取回调用栈信息,并利用所取回的调用栈信息定位到所述Java程序的源代码中的引起所述阻塞的位置的装置。
11.根据权利要求10所述的设备,其中,在执行所述Java程序的处理器是多核处理器的情况下,所述用于在对应于所述Java程序的Java进程中创建辅助线程,并将所述辅助线程挂接到在该Java进程中创建的Java虚拟机JVM的装置创建多个所述辅助线程。
12.根据权利要求11所述的设备,其中,创建的多个所述辅助线程的数目与多核处理器的核数目相同。
13.根据权利要求12所述的设备,其中,创建的多个所述辅助线程中的每一个被分别绑定到多核处理器的一个核。
14.根据权利要求10所述的设备,还包括:用于响应于每个Java线程的启动,通过回调函数建立该Java线程和操作系统内核中的对应于该Java线程的本地任务之间的映射关系的装置。
15.根据权利要求14所述的设备,其中,所述信号包含被阻塞的本地任务的ID,并且其中,所述用于在所述辅助线程响应于接收到来自操作系统内核的所述信号从所述JVM中取回调用栈信息,并利用所取回的调用栈信息定位到所述Java程序的源代码中的引起所述阻塞的位置的装置包括:用于根据本地任务的ID和所述映射关系,从所述JVM中取回与该本地任务对应的Java线程的调用栈信息的装置。
16.根据权利要求10所述的设备,其中,所述探测器被插入在操作系统的调度器中并且在发生任务上下文切换的情况下执行操作。
17.根据权利要求16所述的设备,其中,所述探测器是被加载到操作系统内核中的用户自定义的模块插入到所述调度器中的。
18.根据权利要求16或17所述的设备,其中,所述用于由所述探测器监视所述Java进程中的Java线程在操作系统内核中的状态并且响应于检测到Java线程被阻塞而向所述辅助线程发送信号的装置包括:用于在处理器执行任务上下文切换的情况下从处理器调出的本地任务对应于所述Java进程中的Java线程并且该本地任务处于阻塞状态的情况下向所述辅助线程发送信号的装置。
CN201010150110.8A 2010-04-15 2010-04-15 用于定位java程序的瓶颈的方法和设备 Expired - Fee Related CN102222037B (zh)

Priority Applications (2)

Application Number Priority Date Filing Date Title
CN201010150110.8A CN102222037B (zh) 2010-04-15 2010-04-15 用于定位java程序的瓶颈的方法和设备
US13/086,609 US20110258608A1 (en) 2010-04-15 2011-04-14 Method and apparatus to locate bottleneck of java program

Applications Claiming Priority (1)

Application Number Priority Date Filing Date Title
CN201010150110.8A CN102222037B (zh) 2010-04-15 2010-04-15 用于定位java程序的瓶颈的方法和设备

Publications (2)

Publication Number Publication Date
CN102222037A true CN102222037A (zh) 2011-10-19
CN102222037B CN102222037B (zh) 2014-04-02

Family

ID=44778593

Family Applications (1)

Application Number Title Priority Date Filing Date
CN201010150110.8A Expired - Fee Related CN102222037B (zh) 2010-04-15 2010-04-15 用于定位java程序的瓶颈的方法和设备

Country Status (2)

Country Link
US (1) US20110258608A1 (zh)
CN (1) CN102222037B (zh)

Cited By (5)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN106371900A (zh) * 2015-07-23 2017-02-01 腾讯科技(深圳)有限公司 一种实现异步调用的数据处理方法及装置
CN107861878A (zh) * 2017-11-22 2018-03-30 泰康保险集团股份有限公司 Java应用程序性能问题定位的方法、装置和设备
CN109117144A (zh) * 2018-07-10 2019-01-01 北京小米移动软件有限公司 页面处理方法、装置、终端及存储介质
CN110865919A (zh) * 2019-11-04 2020-03-06 苏宁云计算有限公司 基于java进程的监控方法、装置和计算机设备
CN113377614A (zh) * 2021-06-08 2021-09-10 北京百度网讯科技有限公司 调用链信息的生成方法、装置、电子设备及存储介质

Families Citing this family (26)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US8499287B2 (en) * 2008-06-23 2013-07-30 Microsoft Corporation Analysis of thread synchronization events
US8893134B2 (en) * 2011-04-13 2014-11-18 International Business Machines Corporation Locating bottleneck threads in multi-thread applications
EP2642387B1 (en) * 2011-08-31 2015-07-15 Huawei Technologies Co., Ltd. Method, memory management unit and computer system for managing memory of computer system
US9703950B2 (en) 2012-03-30 2017-07-11 Irdeto B.V. Method and system for preventing and detecting security threats
CN103365707B (zh) * 2012-03-30 2016-08-03 国际商业机器公司 控制异步调用的返回的方法和装置
CN102768629B (zh) * 2012-04-16 2017-02-08 中兴通讯股份有限公司 基于调度层实现虚拟机间通讯的方法和装置
CN102768643B (zh) * 2012-06-27 2015-04-01 河海大学常州校区 一种使用多函数契约测试JavaScript函数正确性的方法
US8954546B2 (en) 2013-01-25 2015-02-10 Concurix Corporation Tracing with a workload distributor
US8997063B2 (en) 2013-02-12 2015-03-31 Concurix Corporation Periodicity optimization in an automated tracing system
US8924941B2 (en) 2013-02-12 2014-12-30 Concurix Corporation Optimization analysis using similar frequencies
US20130283281A1 (en) 2013-02-12 2013-10-24 Concurix Corporation Deploying Trace Objectives using Cost Analyses
US9092564B2 (en) * 2013-02-15 2015-07-28 Microsoft Technology Licensing, Llc Call stacks for asynchronous programs
US20130227529A1 (en) 2013-03-15 2013-08-29 Concurix Corporation Runtime Memory Settings Derived from Trace Data
US9575874B2 (en) 2013-04-20 2017-02-21 Microsoft Technology Licensing, Llc Error list and bug report analysis for configuring an application tracer
US9292415B2 (en) 2013-09-04 2016-03-22 Microsoft Technology Licensing, Llc Module specific tracing in a shared module environment
US9772927B2 (en) 2013-11-13 2017-09-26 Microsoft Technology Licensing, Llc User interface for selecting tracing origins for aggregating classes of trace data
CN103810099B (zh) * 2013-11-21 2017-05-24 北京奇虎科技有限公司 代码跟踪方法及其系统
US9582312B1 (en) * 2015-02-04 2017-02-28 Amazon Technologies, Inc. Execution context trace for asynchronous tasks
US9471367B1 (en) * 2015-12-08 2016-10-18 International Business Machines Corporation Virtual machine usage data collection using securely loaded virtual firmware
WO2017155523A1 (en) * 2016-03-09 2017-09-14 Hewlett Packard Enterprise Development Lp Server virtual address space
US10970055B2 (en) * 2018-08-21 2021-04-06 International Business Machines Corporation Identifying software and hardware bottlenecks
CN109117260B (zh) * 2018-08-30 2021-01-01 百度在线网络技术(北京)有限公司 一种任务调度方法、装置、设备和介质
CN110414218B (zh) * 2018-11-13 2022-09-09 腾讯科技(深圳)有限公司 内核检测方法、装置、电子设备及存储介质
CN110162477B (zh) * 2019-05-28 2022-11-22 山东财经大学 一种第三方库版本升级的异常自动调试系统及方法
CN111679984B (zh) * 2020-06-08 2023-09-19 中国银行股份有限公司 一种性能分析方法和装置
CN115629992B (zh) * 2022-12-16 2023-04-07 云筑信息科技(成都)有限公司 一种对使用Spring技术栈构建的应用系统进行调试的方法

Citations (6)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN1790270A (zh) * 2005-12-14 2006-06-21 浙江大学 支持多进程的Java虚拟机实现方法
US20060143608A1 (en) * 2004-12-28 2006-06-29 Jan Dostert Thread monitoring using shared memory
US20070220515A1 (en) * 2006-01-19 2007-09-20 Dewitt Jimmie E Jr Method and Apparatus for Analyzing Wait States in a Data Processing System
CN101192169A (zh) * 2006-11-30 2008-06-04 国际商业机器公司 系统资源的优化利用的方法
US20080148241A1 (en) * 2006-10-11 2008-06-19 Scott Thomas Jones Method and apparatus for profiling heap objects
US7496918B1 (en) * 2004-06-01 2009-02-24 Sun Microsystems, Inc. System and methods for deadlock detection

Family Cites Families (4)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US7472228B2 (en) * 2004-10-27 2008-12-30 International Business Machines Corporation Read-copy update method
US8572581B2 (en) * 2009-03-26 2013-10-29 Microsoft Corporation Measurement and reporting of performance event rates
US20130125133A1 (en) * 2009-05-29 2013-05-16 Michael D. Schuster System and Method for Load Balancing of Fully Strict Thread-Level Parallel Programs
US8634302B2 (en) * 2010-07-30 2014-01-21 Alcatel Lucent Apparatus for multi-cell support in a network

Patent Citations (6)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US7496918B1 (en) * 2004-06-01 2009-02-24 Sun Microsystems, Inc. System and methods for deadlock detection
US20060143608A1 (en) * 2004-12-28 2006-06-29 Jan Dostert Thread monitoring using shared memory
CN1790270A (zh) * 2005-12-14 2006-06-21 浙江大学 支持多进程的Java虚拟机实现方法
US20070220515A1 (en) * 2006-01-19 2007-09-20 Dewitt Jimmie E Jr Method and Apparatus for Analyzing Wait States in a Data Processing System
US20080148241A1 (en) * 2006-10-11 2008-06-19 Scott Thomas Jones Method and apparatus for profiling heap objects
CN101192169A (zh) * 2006-11-30 2008-06-04 国际商业机器公司 系统资源的优化利用的方法

Non-Patent Citations (1)

* Cited by examiner, † Cited by third party
Title
CONTRIBUTED BY SUDHANSHU GOSWAMI: "An introduction to KProbes", 《LWN.NET》 *

Cited By (8)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN106371900A (zh) * 2015-07-23 2017-02-01 腾讯科技(深圳)有限公司 一种实现异步调用的数据处理方法及装置
CN107861878A (zh) * 2017-11-22 2018-03-30 泰康保险集团股份有限公司 Java应用程序性能问题定位的方法、装置和设备
CN109117144A (zh) * 2018-07-10 2019-01-01 北京小米移动软件有限公司 页面处理方法、装置、终端及存储介质
CN109117144B (zh) * 2018-07-10 2022-01-18 北京小米移动软件有限公司 页面处理方法、装置、终端及存储介质
CN110865919A (zh) * 2019-11-04 2020-03-06 苏宁云计算有限公司 基于java进程的监控方法、装置和计算机设备
CN110865919B (zh) * 2019-11-04 2023-11-28 苏宁云计算有限公司 基于java进程的监控方法、装置和计算机设备
CN113377614A (zh) * 2021-06-08 2021-09-10 北京百度网讯科技有限公司 调用链信息的生成方法、装置、电子设备及存储介质
CN113377614B (zh) * 2021-06-08 2023-07-25 北京百度网讯科技有限公司 调用链信息的生成方法、装置、电子设备及存储介质

Also Published As

Publication number Publication date
CN102222037B (zh) 2014-04-02
US20110258608A1 (en) 2011-10-20

Similar Documents

Publication Publication Date Title
CN102222037B (zh) 用于定位java程序的瓶颈的方法和设备
JP4888272B2 (ja) ソフトウェアのシミュレーション方法、ソフトウェアのシミュレーションのためのプログラム、及びソフトウェアのシミュレーション装置
CN101553769B (zh) 用于跟踪并监控计算机应用的系统和方法
CN100570565C (zh) 在管理程序中提供基于策略的操作系统服务的方法和系统
US8661450B2 (en) Deadlock detection for parallel programs
US10360141B2 (en) Automated application test system
CN100533393C (zh) 用于在多处理器环境中管理对共享资源的存取的方法
WO2018072493A1 (zh) 编译方法和编译系统
CN103620561B (zh) 用于n路运行时互操作调试的方法和系统
CN106201878B (zh) 测试程序的执行方法和装置
US9600411B2 (en) System and method for determining an object's lifetime in an object oriented environment
US20030023656A1 (en) Method and system for deadlock detection and avoidance
CN100349131C (zh) 一种应用程序故障的定位方法
CN101403979A (zh) 一种自旋锁的加锁方法及计算机系统
CN103559431A (zh) 安卓系统用户权限的检测方法、装置和系统
JP2016511484A (ja) コントラクトのためのオペレーティングシステムサポート
US20090319662A1 (en) Process Migration Based on Exception Handling in a Multi-Node Environment
US20080141213A1 (en) Flexible interconnection system
US8615760B2 (en) Facilitating memory analysis
Haque Concurrent deadlock detection in parallel programs
CN115237728B (zh) 一种实时操作系统运行状态的可视化监视方法
CN110941503A (zh) 故障处理方法、装置及电子设备
CN100481784C (zh) 网格系统性能检测方法及网格系统性能检测控制装置
US6173309B1 (en) Null thread library and thread abstraction interface
CN101158920A (zh) 一种检测操作系统故障的方法和装置

Legal Events

Date Code Title Description
C06 Publication
PB01 Publication
C10 Entry into substantive examination
SE01 Entry into force of request for substantive examination
C14 Grant of patent or utility model
GR01 Patent grant
ASS Succession or assignment of patent right

Owner name: IBM (CHINA) CO., LTD.

Free format text: FORMER OWNER: INTERNATIONAL BUSINESS MACHINES CORPORATION

Effective date: 20150731

C41 Transfer of patent application or patent right or utility model
TR01 Transfer of patent right

Effective date of registration: 20150731

Address after: 201203 Shanghai city Pudong New Area Keyuan Road No. 399 Zhang Jiang Zhang Jiang high tech Park Innovation Park 10 Building 7 layer

Patentee after: International Business Machines (China) Co., Ltd.

Address before: American New York

Patentee before: International Business Machines Corp.

CF01 Termination of patent right due to non-payment of annual fee
CF01 Termination of patent right due to non-payment of annual fee

Granted publication date: 20140402

Termination date: 20190415