这篇文章将为大家详细讲解有关如何理解java中MAT对OQL的支持,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。
MAT
支持一种类似于SQL的查询语言OQL(Object Query Language
)。OQL使用类SQL语法,可以在堆中进行对象的查找和筛选。
在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
From
子句用于指定查询范围,它可以指定类名、正则表达式或者对象地址。
下例使用From
子句,指定类名进行搜索,并输出所有的java.lang.String
实例。
SELECT * FROM java.lang.String s
下例使用正则表达式,限定搜索范围,输出所有java.lang包下所有类的实例,如图所示。
SELECT * FROM "jvm\.chapter07\..*"
也可以直接使用类的地址进行搜索。使用类的地址的好处是可以区分被不同ClassLoade
r加载的同一种类型。下例中“0x37a014d8
”为类的地址。
select * from 0x37a014d8
有多种方法可以获得类的地址,在 MAT
中,一种最为简单的方法如图所示。
在From
子句中,还可以使用“INSTANCEOF
”关键字,返回指定类的所有子类实例。下例的查询返回了当前堆快照中所有的抽象集合实例,包括java.util.Vector
、java.util.ArrayList
和java.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关键字是完全不同的。
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
OQL中可以访问堆内对象的属性,也可以访问堆内代理对象的属性。访问堆内对象的属性时,格式如下:
[ <alias>. ] <field> . <field>. <field>
其中alias
为对象名称。
下例访问java.io.File
对象的path
属性,并进一步访问path
的value
属性。
SELECT toString(f.path.value) FROM java.io.File f
以上查询得到的结果如图所示。
这些堆内对象的属性与Java对象一致,拥有与Java对象相同的结果。
MAT为了能快捷地获取堆内对象的额外属性(比如对象占用的堆大小、对象地址等),为每种元类型的堆内对象建立了相对应的代理对象,以增强原有的对象功能。访问代理对象的属性时,使用如下格式:
[ <alias>. ] @<attribute>
其中,alias
为对象名称,attribute
为属性名。
下例显示了String
对象的内容、objectid
和objectAddress
。
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的支持就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。