I'd like to build an OQL query with which to recursively print out all the static data of a JVM heap dump from classes within a specific package. I'm aware that there are potentially lots of issues in going recursively through memory references, but (at least initially) I'll mitigate them by thresholding the depth.
As per the documentation, classes have a statics
field, which in turn should be composed of name
s and value
s:
statics - name, value pairs for static fields of the Class.
I've come to a halt in obtaining the name of each of these static fields by using the field.name
expression and don't know how to iterate an object's non-static fields. I currently have:
select map(
filter(
filter(heap.classes(), "/com.heap./.test(it.name)"),
function (clazz) {
if (clazz.statics) {
return true;
}
return false;
}
), function (clazz) {
var res = '';
res += toHtml(clazz.name) + " : " + toHtml(clazz.statics) + "<br>";
map(clazz.statics, function (field) {
res += "--" + toHtml(field) + "," + toHtml(field.name) + "," + toHtml(field.state) +"<br>";
});
return res + "<br>";
}
)
And get the following output:
com.heap.dump.DataHolder : { :sun.misc.Launcher$AppClassLoader#1, }
--sun.misc.Launcher$AppClassLoader#1,null,null
com.heap.dump.HeapDumperTest : { dataHolder:com.heap.dump.DataHolder#1, mutableStaticState:java.lang.String#225, :sun.misc.Launcher$AppClassLoader#1, }
--com.heap.dump.DataHolder#1,null,java.lang.String#224
--java.lang.String#225,null,null
--sun.misc.Launcher$AppClassLoader#1,null,null
com.heap.dump.Main : { :sun.misc.Launcher$AppClassLoader#1, }
--sun.misc.Launcher$AppClassLoader#1,null,null
I'm iterating the clazz.statics
using the map()
function, following this answer.
It looks like the field
argument is just the field's value, as field.name
is always null
and field.state
actually retrieves the field on one of the objects (com.heap.dump.DataHolder.state
).
Main questions:
- While iterating static fields, how can the field name, aside from the value, be obtained?
- Once I have an object/instance I want to traverse, how do I iterate the non-static fields (name and value) for that object? This way of obtaining a field's value, just like is the
field.state
statement, looks helpful only if I already know the field names, which is not the case here.
Additional questions:
- How do I filter out the empty-named AppClassLoader static fields?
- Am I using the wrong tool for the job? Is there an easier alternative to VisualVM's OQL?