JVM对象查询语⾔(OQL)
本⽂主要翻译⾃JDK 1.8的JVM监控⼯具jhat中关于OQL的英⽂帮助说明。
可以在jhat 和 jvisualvm 中进⾏实践。
OQL(对象查询语⾔)
OQL是⽤于查询Java堆的类SQL查询语⾔。OQL允许过滤/选择从Java堆中获取的信息。虽然HAT已经⽀持预定义的查询,例如“显⽰类X的所有实例”,但OQL增加了更多的灵活性。OQL基于JavaScript表达式语⾔。
OQL查询的形式
select <JavaScript expression to select>
[ from [instanceof] <class name> <identifier>
[ where <JavaScript boolean expression to filter> ] ]
解释:
(1)class name是java类的完全限定名,如:java.lang.String, java.util.ArrayList, [C是char数组, [Ljava.io.File是java.io.File[],依此类推
(2)类的完全限定名不⾜以唯⼀的辨识⼀个类,因为不同的ClassLoader载⼊的相同的类,它们在JVM中是不同类型的
(3)instanceof表⽰也查询某⼀个类的⼦类,如果不明确instanceof,则只精确查询class name指定的类
(4)from和where⼦句都是可选的
(5)可以使⽤obj.field_name语法访问Java字段,并且可以使⽤array [index]语法访问数组元素
OQL⽰例
查询长度⼤于等于100的字符串
select s from java.lang.String s where s.value.length >= 100
查询长度⼤于等于256的int数组
select a from [I a where a.length >= 256
另⼀种⽅式:select a from int[] a where a.length >= 256
显⽰与正则表达式匹配的字符串的内容
select String() from java.lang.String s
where /java/.test(String())
/java/ 修改成你的正则表达式,如/^MyClass$/ 就会匹配MyClass这个字符串
显⽰所有File对象的⽂件路径
select file.String() from java.io.File file
显⽰所有ClassLoader类的名称
select classof(cl).name from instanceof java.lang.ClassLoader cl
显⽰由给定id字符串标识的Class的实例
select o from instanceof 0x741012748 o
请注意,0x741012748是类的ID(在会话中)。通过查看该类页⾯中显⽰的id可以到它。
OQL内置对象,函数
堆对象
该堆内置对象⽀持下列⽅法:
heap.forEachClass - 为每个Java类调⽤⼀个回调函数
heap.forEachClass(callback);
heap.forEachObject - 为每个Java对象调⽤回调函数
heap.forEachObject(callback, clazz, includeSubtypes);
clazz是选择其实例的类。如果未指定,则默认为java.lang.Object。includeSubtypes是⼀个布尔标志,
指定是否包含⼦类型实例。该标志的默认值为true。
heap.findClass - 查给定名称的Java类
heap.findClass(className);
where className是要查的类的名称。⽣成的Class对象具有以下属性:
name - 类的名称。
superclass - 超类的类对象(如果是java.lang.Object,则为null)。
statics - 类的静态字段的名称,值对。
fields - 字段对象的数组。field对象具有名称,签名属性。
loader - 加载此类的ClassLoader对象。
signers - 签署此类的签名者。
protectionDomain - 此类所属的保护域。
类对象具有以下⽅法:
isSubclassOf - 测试给定的类是否是此类的直接或间接⼦类。
isSuperclassOf - 测试给定的Class是否是此类的直接或间接超类。
subclasses - 返回直接和间接⼦类的数组。
superclasses - 返回直接和间接超类的数组。
heap.findObject - 从给定的对象id中查对象
heap.findObject(stringIdOfObject);
heap.classes - 返回所有Java类的枚举
heap.objects - 返回Java对象的枚举
heap.objects(clazz, [includeSubtypes], [filter])
clazz是选择其实例的类。如果未指定,则默认为java.lang.Object。includeSubtypes是⼀个布尔标志,
指定是否包含⼦类型实例。该标志的默认值为true。此⽅法接受可选的过滤器表达式以过滤对象的结果集。
heap.finalizables - 返回待完成的Java对象的枚举。
heap.livepaths - 返回给定对象存活的路径数组。此⽅法接受可选的第⼆个参数,它是⼀个布尔标志。此标志指⽰是否包含弱引⽤的路径。默认情况下,不包括具有弱引⽤的路径。
select heap.livepaths(s) from java.lang.String s
该数组本⾝的每个元素都是另⼀个数组。后⼀个数组包含⼀个位于路径“引⽤链”中的对象。
id - 此根引⽤的对象的字符串id
type - 描述类型的Root(JNI Global,JNI Local,Java Static等)
description - Root的字符串描述
referrer - 负责此根或null的Thread Object或Class对象
例⼦:
访问类java.lang.System的静态字段'props'
select heap.findClass("java.lang.System").statics.props
获取java.lang.String类的字段数
select heap.findClass("java.lang.String").fields.length
到其对象id被赋予的对象
select heap.findObject("0xf3800b58")
选择所有匹配java.*的类
select filter(heap.classes(), "/java./.test(it.name)")
单个对象上的函数
filter过滤对象数组allocTrace(jobject)
classof(jobject)
forEachReferrer(callback, jobject)
identical(o1, o2)
objectid(jobject)
reachables(jobject, excludedFields)
referrers(jobject)
referees(jobject)
refers(jobject)
root(jobject)
sizeof(jobject)
toHtml(obj)
allocTrace函数
这将返回给定Java对象的分配站点跟踪(如果可⽤)。allocTrace返回对象的数组。每个对象具有以下属性:className - 其⽅法在框架中运⾏的Java类的名称。
methodName - 运⾏的Java⽅法的名称。
methodSignature - 框架中运⾏的Java⽅法的签名。
sourceFileName - 框架中运⾏的Java类的源⽂件的名称。
lineNumber - ⽅法中的源⾏号。
classof函数
返回给定Java对象的Class对象。结果对象⽀持以下属性:
name - 类的名称。
superclass - 超类的类对象(如果是java.lang.Object,则为null)。
静态 - 类的静态字段的名称,值对。
fields - 字段对象的数组。字段对象具有名称,签名属性。
loader - 加载此类的ClassLoader对象。
签名者 - 签署此类的签名者。
protectionDomain - 此类所属的保护域。
类对象具有以下⽅法:
isSubclassOf - 测试给定的类是否是此类的直接或间接⼦类。
isSuperclassOf - 测试给定的Class是否是此类的直接或间接超类。
subclasses - 返回直接和间接⼦类的数组。
superclasses - 返回直接和间接超类的数组。
例⼦:
显⽰每个Reference类型对象的类名
select classof(o).name from instanceof f.Reference o
显⽰java.io.InputStream的所有⼦类
select heap.findClass("java.io.InputStream").subclasses()
显⽰java.io.BufferedInputStream的所有超类
select heap.findClass("java.io.BufferedInputStream").superclasses()
forEachReferrer函数
为给定Java对象的每个引⽤者调⽤⼀个回调函数。
identical函数
返回两个给定的Java对象是否相同。
select identical(heap.findClass("Foo").statics.bar, heap.findClass("AnotherClass").statics.bar)
objectid函数
返回给定Java对象的String id。此id可以传递给 heap.findObject,也可以⽤于⽐较对象以进⾏标识。
select objectid(o) from java.lang.Object o
reachables函数
返回从给定Java对象传递引⽤的Java对象数组。(可选)接受第⼆个参数,该参数是逗号分隔的字段名称,以从可达性计算中排除。字段以class_name.field_name模式编写。
例⼦:
从每个Properties实例打印所有可到达的对象。
select reachables(p) from java.util.Properties p
打印每个java.URL中的所有可访问内容,但省略可通过指定字段访问的对象。
select reachables(u, 'java.URL.handler') from java.URL u
referrers函数
返回引⽤了给定Java对象的所有对象
例⼦:
查询每个java.lang.Object实例被引⽤的次数
select count(referrers(o)) from java.lang.Object o
查询那些对象引⽤了java.io.File实例对象