如何理解java中MAT对OQL的支持

2023-05-14,,

这篇文章将为大家详细讲解有关如何理解java中MAT对OQL的支持,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

MAT 支持一种类似于SQL的查询语言OQL(Object Query Language)。OQL使用类SQL语法,可以在堆中进行对象的查找和筛选。

1. Select子句

MAT中,Select子句的格式与SQL基本一致,用于指定要显示的列。Select子句中可以使用“*”,查看结果对象的引用实例(相当于outgoing references)。

select * from java.util.Vector v

以上查询的输出如图所示,在输出结果中,结果集中的每条记录都可以展开,查看各自的引用对象。

OQL还可以指定对象的属性进行输出,下例输出所有Vector对象的内部数组,输出结果如图所示。使用“OBJECTS”关键字,可以将返回结果集中的项以对象的形式显示。

SELECT OBJECTS v.elementData FROM java.util.Vector v

Select子句中,使用“AS RETAINED SET”关键字可以得到所得对象的保留集。下例得到jvm.chapter07.Student对象的保留集。

SELECT AS RETAINED SET * FROM jvm.chapter07.Student

DISTINCT”关键字用于在结果集中去除重复对象。下例的输出结果中只有一条“class java.lang.String”记录。如果没有“DISTINCT”,那么查询将为每个String实例输出其对应的Class信息。

SELECT DISTINCT OBJECTS classof(s) FROM java.lang.String s

2. From子句

From 子句用于指定查询范围,它可以指定类名、正则表达式或者对象地址。

下例使用From子句,指定类名进行搜索,并输出所有的java.lang.String实例。

SELECT * FROM java.lang.String s

下例使用正则表达式,限定搜索范围,输出所有java.lang包下所有类的实例,如图所示。

SELECT * FROM "jvm\.chapter07\..*"

也可以直接使用类的地址进行搜索。使用类的地址的好处是可以区分被不同ClassLoader加载的同一种类型。下例中“0x37a014d8”为类的地址。

select * from 0x37a014d8

有多种方法可以获得类的地址,在 MAT 中,一种最为简单的方法如图所示。

From子句中,还可以使用“INSTANCEOF”关键字,返回指定类的所有子类实例。下例的查询返回了当前堆快照中所有的抽象集合实例,包括java.util.Vectorjava.util.ArrayListjava.util.HashSet等。

SELECT * FROM INSTANCEOF java.util.AbstractCollection

From子句中,还可以使用“OBJECTS”关键字。使用“OBJECTS”关键字后,那么原本应该返回类的实例的查询,将返回类的信息。

SELECT * FROM OBJECTS java.lang.String

以上查询的返回结果如图所示。它仅返回一条记录,表示java.lang.String的类的信息。

如果不使用“OBJECTS”关键字,这个查询将返回所有的java.lang.String实例:

OBJECTS”关键字也支持与正则表达式一起使用。下面的查询,返回了所有满足给定正则表达式的所有类,其结果如图所示。

SELECT * FROM OBJECTS "jvm\.chapter07\..*"

注意:在From子句中使用OBJECTS关键字,将返回符合条件的类信息,而非实例信息。这与Select子句中的OBJECTS关键字是完全不同的。

3. Where子句

Where子句用于指定OQL的查询条件。OQL查询将只返回满足Where子句指定条件的对象。Where子句的格式与传统SQL极为相似。

下例返回长度大于10的char数组。

SELECT * FROM char[] s WHERE s.@length>10

下例返回包含“java”子字符串的所有字符串,使用“LIKE”操作符,LIKE”操作符的操作参数为正则表达式

SELECT * FROM java.lang.String s WHERE toString(s) LIKE ".*java.*"

下例返回所有value域不为null的字符串,使用“=”操作符。

SELECT * FROM java.lang.String s where s.value!=null

Where子句支持多个条件的AND、OR运算。下例返回数组长度大于15,并且深堆大于1000字节的所有Vector对象。

SELECT * FROM java.util.Vector v WHERE v.elementData.@length>15 AND v.@retainedHeapSize>1000
4 内置对象与方法

OQL中可以访问堆内对象的属性,也可以访问堆内代理对象的属性。访问堆内对象的属性时,格式如下:

[ <alias>. ] <field> . <field>. <field>

其中alias为对象名称。

下例访问java.io.File对象的path属性,并进一步访问pathvalue属性。

SELECT toString(f.path.value) FROM java.io.File f

以上查询得到的结果如图所示。

这些堆内对象的属性与Java对象一致,拥有与Java对象相同的结果。

MAT为了能快捷地获取堆内对象的额外属性(比如对象占用的堆大小、对象地址等),为每种元类型的堆内对象建立了相对应的代理对象,以增强原有的对象功能。访问代理对象的属性时,使用如下格式:

[ <alias>. ] @<attribute>

其中,alias为对象名称,attribute为属性名。

下例显示了String对象的内容、objectidobjectAddress

SELECT s.toString(), s.@objectId, s.@objectAddress FROM java.lang.String s

下例显示了File对象的对象ID、对象地址、代理对象的类型、类的类型、对象的浅堆大小以及对象的显示名称。

SELECT f.@objectId, f.@objectAddress, f.@class, f.@clazz, f.@usedHeapSize, f.@displayName FROM java.io.File f

下例显示java.util.Vector内部数组的长度。

SELECT v.elementData.@length FROM java.util.Vector v

下表整理了MAT代理对象的基本属性。

对象类型 接口 接口 功能
基对象 IObejct objectId 对象ID
基对象 IObejct objectAddress 对象地址
基对象 IObejct class 代理对象类型
基对象 IObejct clazz 对象类类型
基对象 IObejct usedHeapSize 浅堆大小
基对象 IObejct retainedHeapSize 深堆大小
基对象 IObejct displayName 显示名称
Class对象 IClass classLoaderId ClassLoad的ID
数组 IArray length 数组长度
元类型数组 IPrimitiveArray valueArray 数组内容
对象数组 IObjectArray referenceArray 数组内容

除了使用代理对象的属性,OQL中还可以使用代理对象的方法,使用格式如下:

[ <alias> . ] @<method>( [ <expression>, <expression> ] )

下例显示int数组中索引下标为2的数据内容。

SELECT s.getValueAt(2) FROM int[] s WHERE (s.@length > 2)

下例显示对象数组中索引下标为2的对象。

SELECT OBJECTS s.@referenceArray.get(2) FROM java.lang.Object[] s WHERE (s.@length > 2)

下例显示了当前堆中所有的类型。

select * from ${snapshot}.getClasses()

下例显示了所有的java.util.Vector对象及其子类型,它的输出如图所示。

select * from INSTANCEOF java.util.Vector

下例显示当前对象是否是数组。

SELECT c, classof(c).isArrayType() FROM ${snapshot}.getClasses() c

代理对象的方法整理如表所示。

对象说明 对象名 对象方法 对象方法说明
全局快照 ISnapshot getClasses() 所有实例的集合
全局快照 ISnapshot getClassesByName(String name, boolean includeSubClasses) 根据名称选取符合条件的实例
类对象 IClass hasSuperClass() 是否有超类
类对象 IClass isArrayType() 是否是数组
基对象 IObject getObjectAddress() 取得对象地址
元类型数组 IPrimitiveArray getValueAt(int index) 取得数组中给定索引的数据
元类型数组,对象数组 [] or List get(int index) 取得数组中给定索引的数据

MAT的OQL中还内置一些有用的函数,如表所示。

表 OQL中的内置函数

函数 说明
toHex( number ) 转为16进制
toString( object ) 转为字符串
dominators( object ) 取得直接支配对象
outbounds( object ) 取得给定对象引用的对象
inbounds( object ) 取得引用给定对象的对象
classof( object ) 取得当前对象的类
dominatorof( object ) 取得给定对象的直接支配者

下例显示所有长度为15的字符串内容(JDK 1.7导出的堆)。

SELECT toString(s) FROM java.lang.String s WHERE ((s.value.@length = 15) and (s.value != null))

下例显示所有jvm.chapter07.Student对象的直接支配对象。即给定对象回收后,将释放的对象集合。

SELECT objects dominators(s) FROM jvm.chapter07.Student s

以上查询的输出如图所示,显示Student对象支配3个Vector对象。

函数dominatorof()与dominators()的功能相反,它获取直接支配当前对象的对象。

SELECT distinct objects dominatorof(s) FROM jvm.chapter07.Student s

以上查询的输出如图所示,显示所有的Student对象直接被主线程支配。

注意:函数dominatorof()与dominators()的功能正好相反。dominatorof()用于获得直接支配当前对象的对象,而dominators()用于获取直接支配对象。

下例取得引用WebPage的对象。

SELECT objects inbounds(w) FROM jvm.chapter07.WebPage w

下例取得堆快照中所有在jvm.chapter包中的存在对象实例的类型,其输出如图所示。

SELECT distinct objects classof(obj) FROM "jvm\.chapter07\..*" obj

关于如何理解java中MAT对OQL的支持就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

《如何理解java中MAT对OQL的支持.doc》

下载本文的Word格式文档,以方便收藏与打印。