首先,它最重要的 Descriptor 主要是 name、displayName 和 descriptorType,其中 name 是属性名称。"name" 要与对应 ModelMBeanAttributeInfo 的 name 相同。descriptorType 必须是 "attribute"。
另外,value、default、legalValues "value" 是用来设定初始值的,"default" 指当不能从 resource 中获得该属性时的默认返回值,"legalValues" 是一组合法的属性数据。它并不用来保证 setAttribute 的数据一致性,而是在 UI 系统,如 JConsole 中提示用户可能的数据输入。
在属性访问的 getMethod, setMethod 方法上,事实上所有对属性的访问都会被 delegate 给同一 MBeanInfo 中特定的 Operation。 getMethod/setMethod 给出了对应的 ModelMBeanOperationInfo 名称。
还有一些额外的属性,比如:persistPolicy, persistPeriod 是代表了持久化策略;currencyTimeLimit, lastUpdatedTimeStamp 缓存策略;iterable 属性是否必须使用 iterate 来访问。默认为否;protocolMap 定义了与第三方系统有关的数据转换的 data model;visibility 定义了与第三方 UI 系统有关的 MBean 如何显示的策略;presentationString 也是定义了与第三方 UI 系统有关的 MBean 如何显示策略,比如 "presentation=server.gif"。
事实上,策略特性有两个层次的作用域:整个 Model Bean 和特定的 MBeanFeature。
Model Bean 的策略描述会被施加到该 Model Bean 的所有 MBeanFeature 上去,除非该 MBeanFeature 重写了这个策略特性。
在上面的例子里,这一个语句:
serverMMBeanInfo.setMBeanDescriptor(serverDescription);
|
给整个 serverMBeanInfo 设了一个策略描述 serverDescription,其中用 "currencyTimeLimit=10" 指出属性的缓存时间是 10 秒。所以,在 Main 方法中,两次 serverMBean.getAttribute("upTime");之间的间隔小于 10 秒就会得到同样的缓存值。
如果我们不想让 "upTime" 这个属性被缓存,我们可以在它的策略描述中加入 "currencyTimeLimit=-1":
Descriptor upTime = new DescriptorSupport(
new String[] {
"name=upTime",
"descriptorType=attribute",
"displayName=Server upTime",
"getMethod=getUpTime",
"currencyTimeLimit=-1" //不需要缓存
});
Descriptor getUpTimeDesc =
new DescriptorSupport(
new String[] {
"name=getUpTime",
"descriptorType=operation",
"class=modelmbean.Server",
"role=operation"
,"currencyTimeLimit=-1" //不需要缓存
});
|
getUpTimeDesc 也要改动的原因是 RequiredModelBean 会把获取 upTime 属性的工作 delegate 给 getUpTime invocation。只要其中一处使用 MBean 级的缓存策略,就没法获得实时 upTime 数据了。
虚拟机检测 JMX 与虚拟机检测 JMX 的提出,为 Java 虚拟机提供了 Java 层上的检测机制。J2SE 中,新提出的 >java.lang.management 包即是 JMX 在 JDK 的一个应用,它提供了大量的有用的接口,通过 MBean 方式,提供了对 Java 虚拟机和运行时远端的监控和检测方式,来帮助用户来检测本地或者远端的虚拟机的运行情况。有了 JMX 之后,我们可以设计一个客户端,来检测远端一个正在运行的虚拟机中的线程数、线程当前的 Stack、内存管理、GC 所占用的时间、虚拟机中的对象和当前虚拟机参数等重要的参数和运行时信息。JMX 另外的一个重要功能是对配置信息的检测和再配置。比如,我们可以在远端查看和修改当前 JVM 的 verbose 参数,以达到动态管理的目的。甚至,我们可以在远端指挥 JVM 做一次 GC,这在下文中有详细介绍。
JMX 提供的虚拟机检测 API 检测虚拟机当前的状态总是 Java 开放人员所关心的,也正是因为如此,出现了大量的 profiler 工具来检测当前的虚拟机状态。从 Java SE 5 之后,在 JDK 中,我们有了一些 Java 的虚拟机检测 API,即 >java.lang.management 包。Management 包里面包括了许多 MXBean 的接口类和 LockInfo、MemoryUsage、MonitorInfo 和 ThreadInfo 等类。从名字可以看出,该包提供了虚拟机内存分配、垃圾收集(GC)情况、操作系统层、线程调度和共享锁,甚至编译情况的检测机制。这样一来,Java 的开发人员就可以很简单地为自己做一些轻量级的系统检测,来确定当前程序的各种状态,以便随时调整。
要获得这些信息,我们首先通过 >java.lang.management.ManagementFactory 这个工厂类来获得一系列的 MXBean。包括:
- ClassLoadingMXBean
ClassLoadMXBean 包括一些类的装载信息,比如有多少类已经装载/卸载(unloaded),虚拟机类装载的 verbose 选项(即命令行中的 Java –verbose:class 选项)是否打开,还可以帮助用户打开/关闭该选项。
- CompilationMXBean
CompilationMXBean 帮助用户了解当前的编译器和编译情况,该 mxbean 提供的信息不多。
- GarbageCollectorMXBean
相对于开放人员对 GC 的关注程度来说,该 mxbean 提供的信息十分有限,仅仅提供了 GC 的次数和 GC 花费总时间的近似值。但是这个包中还提供了三个的内存管理检测类:MemoryManagerMXBean,MemoryMXBean 和 MemoryPoolMXBean。
- MemoryManagerMXBean
这个类相对简单,提供了内存管理类和内存池(memory pool)的名字信息。
- MemoryMXBean
这个类提供了整个虚拟机中内存的使用情况,包括 Java 堆(heap)和非 Java 堆所占用的内存,提供当前等待 finalize 的对象数量,它甚至可以做 gc(实际上是调用 System.gc)。
- MemoryPoolMXBean
该信息提供了大量的信息。在 JVM 中,可能有几个内存池,因此有对应的内存池信息,因此,在工厂类中,getMemoryPoolMXBean() 得到是一个 MemoryPoolMXBean 的 list。每一个 MemoryPoolMXBean 都包含了该内存池的详细信息,如是否可用、当前已使用内存/最大使用内存值、以及设置最大内存值等等。
- OperatingSystemMXBean
该类提供的是操作系统的简单信息,如构架名称、当前 CPU 数、最近系统负载等。
- RuntimeMXBean
运行时信息包括当前虚拟机的名称、提供商、版本号,以及 classpath、bootclasspath 和系统参数等等。
- ThreadMXBean
在 Java 这个多线程的系统中,对线程的监控是相当重要的。ThreadMXBean 就是起到这个作用。ThreadMXBean 可以提供的信息包括各个线程的各种状态,CPU 占用情况,以及整个系统中的线程状况。从 ThreadMXBean 可以得到某一个线程的 ThreadInfo 对象。这个对象中则包含了这个线程的所有信息。
java.lang.management 和虚拟机的关系 我们知道,management 和底层虚拟机的关系是非常紧密的。其实,有一些的是直接依靠虚拟机提供的公开 API 实现的,比如 JVMTI;而另外一些则不然,很大一块都是由虚拟机底层提供某些不公开的 API / Native Code 提供的。这样的设计方式,保证了 management 包可以提供足够的信息,并且使这些信息的提供又有足够的效率;也使 management 包和底层的联系非常紧密。
查看本文来源