Question

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;
Was it helpful?

Solution

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:

  1. Uniquify on the traced objects, rather than their names:

    map(unique(filter(map(referees(cl), classof), "it.name != ...")), "it.name")
    
  2. 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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top