您是否曾经无缘无故地挂起了应用服务器,或者Java应用程序没有响应? 您的应用程序是否耗尽了内存或性能不佳? 使用Health Center,您可以更轻松地解决此类问题。
使用Health Center监视和诊断问题
用于Java的IBM®监视和诊断工具-健康中心(健康中心)是一种免费的,开销低的诊断工具和API,用于监视在IBM Java虚拟机(JVM)上运行的应用程序。 使用Health Center,您可以通过提供信息来识别和帮助解决问题来快速评估正在运行的Java应用程序的状态。 您可以:
- 识别本机或堆内存是否泄漏
- 发现哪些方法花费最多的时间
- 消除I / O瓶颈
- 可视化和调整垃圾收集
- 查看任何锁争用
- 分析异常的WebSphere®Real Time事件
- 监视您的应用程序的线程活动
- 检测死锁条件
- 收集类直方图数据
Health Center的最新版本是功能强大的新API,可用于编写自己的监视工具。 麻烦的,难以发现的问题的日子现在已经开始。
在本文中,学习编写监视工具,以检查应用程序是否出现死锁情况。 然后,应用这些原理来编写更深入的工具,查询从垃圾回收活动到方法分析的所有内容,并确定应用程序在其CPU周期上所花费的时间。
系统要求
Health Center API捆绑软件至少需要Eclipse 3.4或Eclipse4.x。
将API软件包安装到Eclipse中
IBM Monitoring and Diagnostics工具通常安装在IBM Support Assistant(ISA)中。 要将Health Center嵌入到应用程序中并使用API对其进行编码,请首先将其安装到Eclipse环境中。 为此,请按照下列步骤操作:
- 启动Eclipse开发环境。
- 转到帮助->安装新软件 。
- 将ISA更新站点添加为新站点。
- 点击添加 。
- 在名称框中输入ISA Update网站。
- 在位置框中输入以下URL:http://public.dhe.ibm.com/software/isa/isa410/production/。 此操作将开始搜索所有可用工具,并且需要花费几分钟。
- 在搜索框中输入健康中心
- 选择软件包Health Center Core Feature ,然后单击Next (参见图1):
图1.要安装的可用软件列表
- 验证安装详细信息,然后单击“ 下一步” 。
- 阅读并接受许可条款,然后单击“ 完成” 。 这些步骤将Health Center Core功能安装到Eclipse IDE中。 您已准备好根据API进行编码。
- 验证安装详细信息,然后单击“ 下一步” 。
使用API,编写一个简单的rcp来检测死锁。 首先,在Eclipse中创建一个新的插件项目,并将Health Center API添加为依赖项。 为此,请按照下列步骤操作:
- 转到文件->新建->项目->插件项目 。
- 为项目命名,例如HC_Deadlock。 单击下一步 。
- 清除“ 生成激活器”复选框。 当询问您是否要创建富客户端应用程序时,单击“ 是” 。 单击Next (参见图2):
图2.插件项目选项
- 单击下一步 。 在模板屏幕上,选择Headless Hello RCP 。 点击完成 。
接下来,将Health Center API程序包添加为对新项目的依赖项。 跟着这些步骤:
- 要将API导入添加到清单中,请在新项目中打开META-INF下的MANIFEST.MF文件(参见图3):
图3. Package Explorer插件
- 选择Dependencies选项卡,然后单击Add 。 在“ 选择插件”字段中,在搜索中键入healthcenter.api 。 选择com.ibm.java.diagnostics.healthcenter.api插件-请注意版本号可能不同(请参见图4):
图4. Health Center API插件选择
- 单击确定 。 从“ 选择依赖项”选项卡步骤重复该练习。 这次,再次添加org.eclipse.ui ,版本号可能会有所不同(请参见图5):
图5. org.eclipse.ui的插件选择
- 单击确定 ,然后保存文件。
API插件现已包含在您的应用程序中,您可以开始对其进行编码。
针对死锁应用程序进行测试
在编写死锁监视工具之前,您需要监视一些东西。 清单1显示了一个简单应用程序的源代码,该应用程序出现了死锁:
清单1.一个带有死锁的简单应用程序
public class GenerateDeadlock {
AThread t1 = null;
AThread t2 = null;
AThread t3 = null;
static class AThread extends Thread {
Object hold;
Object grab;
AThread(String name, Object hold, Object grab) {
super(name);
this.hold = hold;
this.grab = grab;
}
private void delay(long time) {
try {
Thread.sleep(time);
} catch (InterruptedException e) {
}
}
private void grabLocks() {
System.out.println("Thread " + this + " about to hold " + hold);
synchronized (hold) {
System.out.println(" Thread " + this + " about to grab "
+ grab);
delay(5000);
synchronized (grab) {
System.out.println(" Thread " + this
+ " got both monitors");
delay(1000000);
}
}
}
public void run() {
System.out.println("Thread " + this + " starting");
for (int i = 0; i < 200000; i++) {
grabLocks();
}
System.out.println("Thread " + this + " completed");
}
}
private void createDeadlock() {
System.out.println("Force 3 thread deadlock");
String s1 = "obj 1";
String s2 = "obj 2";
String s3 = "obj 3";
t1 = new AThread("Thread 1", s1, s2);
t2 = new AThread("Thread 2", s2, s3);
t3 = new AThread("Thread 3", s3, s1);
t1.start();
t2.start();
t3.start();
}
public static void main(String[] args) {
GenerateDeadlock d = new GenerateDeadlock();
d.createDeadlock();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Press a key to exit");
try {
System.in.read();
System.exit(0);
} catch (java.io.IOException e) {
}
}
}
卫生中心分为两个部分。 第一部分是Health Center 代理 ,该代理将加载您要监视的应用程序。 代理提供对JVM中数据的访问,然后再使用Health Center的第二部分( 客户端) 。 API使您可以访问此客户端,该客户端通常从ISA启动。 将客户端嵌入到您的应用程序中,以连接到使用Health Center代理启动的应用程序,并可以访问Health Center客户端监视和显示的所有数据。 该API不提供GUI,而是使所有数据可用于您自己的应用程序。 图6显示了将Health Center客户端和代理安装在ISA和JVM中时的位置概览:
图6. Health Center客户端和代理在ISA和JVM中安装时的位置
启动清单1中附带有Health Center代理的程序。 它还需要最低的IBM Java级别的Java 5 SR8,Java 6 SR1或Java7。您可以下载IBM开发人员工具包 。
要使用Java 5 SR10和更高版本,Java 6 SR5和更高版本以及Java 7与代理一起启动应用程序,请使用以下命令(请参见图7):
java - Xhealthcenter GenerateDeadlock
对于Java 5 SR9和更低版本,或Java 6 SR4和更低版本,请使用以下命令:
java - agentlib:healthcenter - Xtrace:output=healthcenter.out GenerateDeadlock
图7.运行GenerateDeadlock程序
Java 5 SR9和Java 6 SR3自动包含该代理。 有关代理的最新版本以及如何更新代理的说明,请访问Health Center-安装Health Center代理 。
编写死锁监视应用程序
您已经准备好修改基本的Hello RCP World应用程序,并使用Health Center API将其变成死锁检测工具。 打开名为Application.java的文件(请参见图8):
图8. Application.java代码的位置
设置连接详细信息
首先,获得一个ConnectionProperties
对象,该对象包含您要连接的应用程序的详细信息。 默认对象设置为使用localhost和端口1972,但是您可以在构造函数和类方法中更改这些值(并增加安全性):
ConnectionProperties hcConn = new ConnectionProperties();
当您拥有ConnectionProperties
对象时,请连接到要监视的应用程序,该应用程序已经由Health Center代理启动。 调用静态HealthCenterFactory.connect(hcConn, true)
方法。 此调用返回HealthCenter
对象,该对象是直接连接到Health Center的对象,并允许访问Health Center正在监视的所有数据。 connect调用可在您的应用程序中有效地启动Health Center实例并开始收集数据:
HealthCenter hcMon = HealthCenterFactory.connect(hcConn,true);
获取数据
现在您有了HealthCenter
对象,您可以查询数据了。 该API的布局与GUI相似:获取HealthCenter
对象后的第一步是按照您感兴趣的数据类型进行调用。 对于此示例,您要检查死锁,这是ThreadsData
类的一部分。 您可以使用HealthCenter
对象上的getThreadsData()
方法进行访问,如下所示:
ThreadsData hcThreadsData = HealthCenter.getThreadsData();
ThreadsData
类具有deadlockDetected()
方法,如果检测到死锁,该方法将返回true。 通过轮询此方法,可以通知您是否发生死锁:
if(hcThreadsData.deadlockDetected()) {
do something
}
访问推荐和分析引擎
Health Center具有内置的推荐引擎,该引擎提供所有分析并返回结果。 当您运行完整版的Health Center时,通常会在Analysis and Recommendations面板中看到这些结果(请参见图9):
图9. Health Center中的“分析和建议”面板
要查询任何建议,可以使用几种方法。 getAllRecommendations()
返回所有建议的数组,但是您只能使用getCriticalRecommendations()
调用查询关键问题,这是在ThreadsData object
上使用的ThreadsData object
:
String[] hcThreadsRec = hcThreadsData.getCriticalRecommendations()
查看完整的源代码
前五个调用对于将Health Center嵌入应用程序并检查要监视的应用程序中是否存在死锁是必需的。 清单2显示了使用这些调用的完整源代码:
清单2.完整的源代码显示了五个正在使用的调用
package deadlockdemo;
import org.eclipse.equinox.app.IApplication;
import org.eclipse.equinox.app.IApplicationContext;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import com.ibm.java.diagnostics.healthcenter.api.ConnectionProperties;
import com.ibm.java.diagnostics.healthcenter.api.HealthCenter;
import com.ibm.java.diagnostics.healthcenter.api.factory.HealthCenterFactory;
import com.ibm.java.diagnostics.healthcenter.api.threads.ThreadsData;
/**
* This class controls all aspects of the application's execution
*/
public class Application implements IApplication {
HealthCenter hcMon;
public Object start(IApplicationContext context) throws Exception {
ConnectionProperties hcConn = new ConnectionProperties();
hcMon = HealthCenterFactory.connect(hcConn, true);
try {
System.out
.println("Waiting for 10 seconds to allow initial data to be
parsed from the connection");
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
checkForDeadlock();
return IApplication.EXIT_OK;
}
public void stop() {
// nothing to do
}
public void checkForDeadlock() {
while (!detectDeadlock()) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private boolean detectDeadlock() {
ThreadsData hcthreadsData = hcMon.getThreadsData();
if (hcthreadsData == null) {
System.out.println("No threads yet");
} else {
if (hcthreadsData.deadlockDetected()) {
Display display = new Display();
Shell shell = new Shell(display);
MessageBox mb = new MessageBox(shell);
String deadlockMessage = new String();
String[] hcThreadsRec = hcthreadsData
.getCriticalRecommendations();
for (String rec : hcThreadsRec) {
deadlockMessage = deadlockMessage + rec + "\n";
}
mb.setMessage(deadlockMessage);
mb.setText("Deadlock detected");
mb.open();
display.dispose();
return true;
}
}
return false;
}
}
监视死锁
现在,您将在后台运行死锁监视应用程序和受死锁感染的程序。 消息指示死锁(请参见图10):
图10.死锁检测结果面板
结论
本文介绍了如何从Health Center API开始然后编写一种监视工具来检查应用程序是否存在死锁情况的基础知识。 您可以应用这些技术来提取和使用Health Center中的任何数据。 在第2部分中 ,您将基于这些概念并在死锁检测应用程序中添加一个方法分析视图,以显示该应用程序花费大部分CPU周期的位置。
翻译自: https://www.ibm.com/developerworks/java/library/j-healthcareapi1/index.html