3

I would like to execute an OQL query in VisualVM (v1.4.4) to retrieve the (non-static) field names for an object.

The OQL documentation describes heap.findClass(className). This returns an object which includes a fields property (an array of field names).

When I execute the following OQL...

heap.findClass('java.io.ByteArrayInputStream').fields;

... it returns an array of 4 field objects (ByteArrayInputStream has 4 fields - buf, count, mark, and pos - I am assuming these are what are being returned):

org.netbeans.lib.profiler.heap.HprofField@56de8c
org.netbeans.lib.profiler.heap.HprofField@56de95
org.netbeans.lib.profiler.heap.HprofField@56de9e
org.netbeans.lib.profiler.heap.HprofField@56dea7

If I then try to manipulate this array, for example to access each field's name and signature properties (as described in the OQL docs), I get no results. I can't even get the length of the array. For example:

heap.findClass('java.io.ByteArrayInputStream').fields.length;

and:

heap.findClass('java.io.ByteArrayInputStream').fields[0];

Both of the above statements return <no results>.

What am I doing wrong? Probably something basic. I not very familiar with JavaScript - or with how data is displayed in VisualVM, for that matter.

andrewJames
  • 19,570
  • 8
  • 19
  • 51
  • hi! I too am new to OQL, are you trying the query with prefix _select_ say _**select heap.findClass('java.io.ByteArrayInputStream').fields;**_ – BHAWANI SINGH Jan 03 '20 at 17:32
  • No - I am not using the `select` syntax. Just native JavaScript, exactly as shown above. (If I use the `select` syntax, I get the same results, by the way - I just tried it). – andrewJames Jan 03 '20 at 17:58

2 Answers2

4

You need to use map() function. The following OQL retrieves the field names of ByteArrayInputStream class:

select map(heap.findClass('java.io.ByteArrayInputStream').fields, 'it.name')
Tomas Hurka
  • 6,723
  • 29
  • 38
2

Just to add to the very helpful answer from @Tomas - which I have accepted.

Based on his insight, I can also now do things like this in OQL - using a callback instead of an expression string:

map(heap.findClass('java.io.ByteArrayInputStream').fields, function (it) { 
  var res = ''; 
  res += toHtml(it.name) + " : " + toHtml(it.signature); 
  return res + "<br>"; 
});

The above example is trivial, but it opens up more possibilities.

His answer also made me realize where I was going wrong: OQL uses JavaScript expression language - not the exactly the same as JavaScript.

andrewJames
  • 19,570
  • 8
  • 19
  • 51