JProfiler的内部机制

 虽然不必了解分析的内部工作原理,也可以分析用户的应用,但是了解一些内部机制可帮助用户更好理解JProfiler所生成的数据,可灵活配置应用服务器和远程应用,以及分析问题。VM 参数。请查询在启动脚本中所执行的Java调用,并添加VM参数。

时间,内存和线程分析

一个分析器有三个基本方面:“时间分析”测量用户应用在方法层次上的执行路径,而“内存分析”向用户展现了堆的变化情况,例如哪些方法分配了过多的内存。大多数应用都是多线程的,“线程分析”分析线程的同步问题。

由于经常需要比较和关联分析这三种数据,JProfiler将时间,内存和线程分析器合并为一个应用。大多数分歧都是事后分析,分析代理根据指令或当被分析的应用退出时将数据输出到一个快照文件中。JProfiler也支持该项功能,同时JProfiler也是一个交互型分析器,即在采集数据时也同时展示这些数据。

探针(Probes)

有时,JVM的一些基本运行信息还不足以解决问题。由于经常需要比较和关联分析这三种数据,JProfiler将时间,内存和线程分析器合并为一个应用。

有时只有JVM的基础信息是不足以解决问题的,需要更高层次的分析。通过“探针”,可以简洁实用地展现JVM的一些专门子系统数据,如文件I/O,网络I/O,或JDBC,JMS或JNDI等一些专门。除了内置的一些探针,用户也可以自定义探针。

分析器如何搜集数据

分析器必须有些方法来采集所需展示的数据。采集的数据来自执行环境中的某个接口,或者由分析的应用类生成。

一个最基本常见的分析器—Unix shell命令 time—封装了被分析的执行文件,从核心采集进程的一些事后信息。用于Microsoft Windows上本地应用的分析器可以连接到正在运行的应用,并采集可用的调试信息,用于计算分析数据。这些是执行环境中的一些接口示例,这里,分析器并没有修改用户的二进制应用。

Unix分析器 gprof(自1983年4.2bsd UNIX之后)通过向编译器指定一个额外的参数(-pg)可连接到编译的进程里。通过这种方式,分析代码可嵌入到用户的应用中。当应用退出时,将向磁盘写一个数据文件,包含调用树和执行时间,可使用gprof应用查看这些数据。Gprof就是一个能够分析用户应用的分析器。

JProfiler采用一种混合方式,使用JVM的分析接口同时也在加载时处理某些类,这些处理的类可生成JVM分析接口不能输出的数据。

JVM的分析接口(profiling interface)

JVM的分析接口是用在由C或C++编写的分析代理。如果打开JDK的include目录,将看到很多后缀.h的文件。这些文件说明了由JVM提供的C/C++库文件的接口。本地库和JVM之间的所有通信基础就是JNI(Java Native Interface),在 jni.h文件中定义。

JNI允许Java代码调用本地库中的方法,反之亦然。在Java代码中,用户可以使用System.load()的调用在同一个内存空间中加载本地库。当用户调用在”native”中声明的方法时,例如 public native String getName();,将在已加载的本地库的列表中查询该函数。所对应C函数的名称模式包含了Java代码中声明的包,类和方法。JNI也定义了Java数据类型如何对应到C/C++库。当调用本地C-函数时,将把一个“JNI环境”接口作为额外的参数。通过该环境接口,可调用Java方法,在C和Java数据类型之间转换,和执行其他JVM操作,如创建Java线程和与Java监测器同步。

直到Java1.5,JVM为工具厂商提供了一个分析接口,Java Virtual Machine Profiling Interface (JVMPI)。JVMPI并不规范,其行为因不同的JVM有很大差异。此外,JVMPI不能在现代垃圾回收下运 行,并且在分析非常大的堆时有问题。Java1.5时,为解决这些问题增加了JVM Tool Interface(JVMTI)。从Java1.6,已删除了JVMPI。虽然JVMPI只应该用于分析Java1.4,但是JProfiler可同时支持JVMPI和JVMTI。JVMTI在头文件jvmti.h. 中定义,通过JNI与JVM通信,提供了一个额外接口用于配置分析选项。JVMTI是一个基于事件的系统。分析代理库可为不同的事件注册处理函数,然后也可以启用或禁用所选事件。

禁用事件非常重要,可减少分析器的负载。例如,在分析器中,记录对象分配在默认情况下是关闭的,当在GUI中打开记录对象分配时,分析代理将告诉JVMTI接口,启用有关记录对象分配的一些事件。如果创建的对象过多,将产生很客观的负载,JVM自己和分析代理都要执行对每个对象的记录操作。在应用服务器的启动阶段,将创建大量这样对象,用户其实也对这些数据不感兴趣。因此,最好是在此时将对象分配记录选项关闭,这将提高被分析应用的性能,减少产生无用的数据。这同样适用于对方法调用的测量,即JProfiler的“CPU分析”。

JVMTI提供如下事件类型:

JVM生命周期事件

类生命周期事件

线程生命周期事件

对象生命周期事件

监测竞争事件

垃圾回收事件

分析代理和分析GUI

与只是将快照写到磁盘上不同,JProfiler可实时显示分析数据。虽然可以从分析代理直接启动GUI,但是这是不合适的,这会使得被分析的进程被第二个应用所影响,并且也不能再使用远程分析。因此,JProfiler GUI应该使用与被分析的应用不同的JVM。之间通过TCP/IP网络套接字进行通信。

记录的分析数据以分析代理的内部数据结构存放。只有很少一部分记录的数据传到GUI。例如,当打开热点视图中的调用树或回溯时,只有下几层的数据从分析代理传递到GUI。如果所有调用树传递到GUI,将通过套接字传递大量的数据,这将使得被分析的进程变慢,远程分析就不可行。本质上,分析代理保存了所记录的分析数据的数据库,而GUI是一个将用户请求发送到数据库的客户端。