Linux查看HotSopt虚拟机GC线程的CPU占用率

本文介绍如何在Linux环境下监控Java应用的垃圾回收(GC)线程占用的CPU资源,通过使用top-H命令结合JVM Thread Dump,分析GC线程的CPU使用情况。

下面的问题将会检验你有关Linux系统上的Java程序的垃圾回收和High CPU排错的知识。在过度调用GC或及CPU占用率过高的时候,这种排错技术是至关重要的。假设你没有使用像是Compuware dynaTrace或者JVisualVMware这样先进的监视工具。有关于这些工具的使用教程将会在以后发布,但是请先确保自己掌握了基础的排错原则。

问题:

在Linux系统运行的时候,怎样可以监视并计算每一个Oracle HotSpot或者JRockit JVM垃圾回收(GC)线程占用了多少CPU资源呢?

答案

在Linux系统上,Java线程是作为本地的线程来实现的,这就导致每一个线程都是一个单独的Linux进程。这就意味着,你要使用top-H命令(线程开关视图)来监视HotSpot JVM产生的所有Java进程的CPU占用率。

也就是说,根据你正在使用的GC策略和服务器规范的不同,HotSpot和JRockit JVM会为每一个GC线程分配一个确定的序号来区分收集空间的新旧。通过产生的JVM线程库,这些线程可以很轻松地被识别。你可以参考下面这个范例,Oracle JRockit JVM用“(GC Worker Thread X)”的标记方式产生了四个线程。

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
===== FULL THREAD DUMP ===============
 
Fri Nov 16 19:58:36 2012
 
BEA JRockit(R) R27.5.0-110-94909-1.5.0_14-20080204-1558-linux-ia32
 
"Main Thread" id =1 idx=0x4 tid=14911 prio=5 alive, in native, waiting
 
-- Waiting for notification on: weblogic /t3/srvr/T3Srvr @0xfd0a4b0[fat lock]
 
at jrockit /vm/Threads .waitForNotifySignal(JLjava /lang/Object ;)Z(Native Method)
 
at java /lang/Object .wait(J)V(Native Method)
 
at java /lang/Object .wait(Object.java:474)
 
at weblogic /t3/srvr/T3Srvr .waitForDeath(T3Srvr.java:730)
 
^-- Lock released while waiting: weblogic /t3/srvr/T3Srvr @0xfd0a4b0[fat lock]
at weblogic /t3/srvr/T3Srvr .run(T3Srvr.java:380)
at weblogic /Server .main(Server.java:67)
 
at jrockit /vm/RNI .c2java(IIIII)V(Native Method)
 
-- end of trace
 
"(Signal Handler)" id =2 idx=0x8 tid=14920 prio=5 alive, in native, daemon
 
"(GC Main Thread)" id =3 idx=0xc tid=14921 prio=5 alive, in native, native_waiting, daemon
 
"(GC Worker Thread 1)" id =? idx=0x10 tid=14922 prio=5 alive, in native, daemon
 
"(GC Worker Thread 2)" id =? idx=0x14 tid=14923 prio=5 alive, in native, daemon
 
"(GC Worker Thread 3)" id =? idx=0x18 tid=14924 prio=5 alive, in native, daemon
 
"(GC Worker Thread 4)" id =? idx=0x1c tid=14925 prio=5 alive, in native, daemon
 
………………………

现在让我们通过这个简单的例子来了解一下这些规则。

第一步——监视GC线程的CPU利用率

第一步是监视和测定:

  • 通过Linux系统的top-hcommand命令的显示结果,来找出每一个GC工作线程的本地线程ID。
  • 确定每一个GC工作线程的CPU占用率。

第二步——生成并分析JVM线程池

使用Linux的top -H命令的同时,通过kill -3 命令生成2或3个JVM Thread Dump

  • 打开JVM线程池,找到JVM GC工作线程。
  • 然后,通过本地线程的ID(tid属性)找出“top -H”输出的数据和JVM Thread Dump中的数据的关系。

就像你在这个例子中看到的那样,通过这样的线程分析,我们可以发现GC工作线程总共占用了大约20%的CPU资源。这主要是因为在那个时候发生了major GC。请注意使用verbose:gc参数是非常有用的,因为它可以让你分析CPU使用峰值与minor GC以及major GC的关系,以及让你确定JVM GC进程占用了多少CPU资源。

原文来自:http://www.javacodegeeks.com/2013/04/hotspot-gc-thread-cpu-footprint-on-linux.html

 翻译: ImportNew.com 赖 信涛

译文链接: http://www.importnew.com/10910.html

以下是对这段代码的详细解析: 1. `final SettingsActivity activity = (SettingsActivity) getActivity();` - 这行代码的作用是获取当前的活动实例,并将其强制转换为 `SettingsActivity` 类型。`getActivity()` 通常是在一个 `Fragment` 中使用,用于获取与之关联的活动。通过强制类型转换,确保得到的活动是 `SettingsActivity` 类型,以便后续调用该类特有的方法。 2. `mMainSwitchBar = activity.getSwitchBar();` - 调用 `SettingsActivity` 实例的 `getSwitchBar()` 方法,获取一个 `SwitchBar` 对象,并将其赋值给成员变量 `mMainSwitchBar`。`SwitchBar` 通常是一个带有开关按钮的条形控件,用于在设置界面中提供某种开关功能。 3. `mMainSwitchBar.setTitle(getString(R.string.use_wifi_hotsopt_main_switch_title));` - 调用 `SwitchBar` 对象的 `setTitle()` 方法,为 `SwitchBar` 设置标题。`getString(R.string.use_wifi_hotsopt_main_switch_title)` 是从资源文件中获取字符串资源,该字符串将作为 `SwitchBar` 的标题显示。 4. `mSwitchBarController = new WifiTetherSwitchBarController(activity, mMainSwitchBar);` - 创建一个 `WifiTetherSwitchBarController` 实例,并将 `SettingsActivity` 实例和 `SwitchBar` 对象作为参数传递给构造函数。`WifiTetherSwitchBarController` 可能是一个自定义的控制器类,用于处理 `SwitchBar` 的逻辑,例如监听开关状态的变化、执行相应的操作等。 5. `getSettingsLifecycle().addObserver(mSwitchBarController);` - 调用 `getSettingsLifecycle()` 方法获取设置界面的生命周期对象,并调用其 `addObserver()` 方法,将 `WifiTetherSwitchBarController` 实例添加为生命周期观察者。这样,`WifiTetherSwitchBarController` 可以在设置界面的生命周期发生变化时(如创建、启动、暂停、销毁等)接收到相应的回调,从而执行相应的逻辑。 6. `mMainSwitchBar.show();` - 调用 `SwitchBar` 对象的 `show()` 方法,将 `SwitchBar` 显示在界面上。 ### 代码示例 ```java // 假设这是在一个 Fragment 中 public class MyFragment extends Fragment { private SwitchBar mMainSwitchBar; private WifiTetherSwitchBarController mSwitchBarController; @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); final SettingsActivity activity = (SettingsActivity) getActivity(); mMainSwitchBar = activity.getSwitchBar(); mMainSwitchBar.setTitle(getString(R.string.use_wifi_hotsopt_main_switch_title)); mSwitchBarController = new WifiTetherSwitchBarController(activity, mMainSwitchBar); getSettingsLifecycle().addObserver(mSwitchBarController); mMainSwitchBar.show(); } } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值