this is my first posted question. I have a fairly complicated OQL query which lists static fields of classes loaded in our packages. One problem I'm seeing with running the query against 'jhat' of Java 1.6.0_24 is that the 'unique' function doesn't work as expected. I expect
select unique(['a', 'b', 'c', 'a'])
to return ['a', 'b', 'c'] but instead it returns ['a'], wtf?
If anyone's interested the actual full query is (replace 'com.mydomain' with what you like):
select cl.name + ' -- ' + unique(map(filter(referees(cl), "classof(it).name != 'java.lang.Class' && classof(it).name != 'java.lang.String' && classof(it).name != 'sun.misc.Launcher$AppClassLoader' && classof(it).name != 'java.security.ProtectionDomain' && classof(it).name != '[Ljava.security.cert.Certificate;' && classof(it).name != 'sun.plugin2.applet.JNLP2ClassLoader'"), "classof(it).name")).join(', ')
from instanceof java.lang.Class cl
where /com.mydomain./(cl.name) && ! /com.mydomain.xs.protobuf./(cl.name)
&& length(filter(referees(cl), "classof(it).name != 'java.lang.Class' && classof(it).name != 'java.lang.String' && classof(it).name != 'sun.misc.Launcher$AppClassLoader' && classof(it).name != 'java.security.ProtectionDomain'")) > 0;
By default, unique
uniquifies on the object's objectid
, which is suitable for actual traced objects, but for strings it returns null. Thus, only the last string is kept (since all the strings have non-unique objectid
values).
You have two options:
Uniquify on the traced objects, rather than their names:
map(unique(filter(map(referees(cl), classof), "it.name != ...")), "it.name")
Specify the "function" to uniquify with, so that it works for strings:
unique(['a', 'b', 'c', 'a'], 'it')
This will cause the strings themselves to be uniquified.