2

I am using ASM library to instrument some classes. I create my own instance of MethodVisitor and override some of its methods e.g. visitCode() which is called when the MethodVisitor is at the start of the method. Here, I insert my own code if the method is not a getter/setter. But how can I know if the method is not a getter/setter if the visitor is only at the start of the method and the rest of the method hasn't been visited yet?

I could look at the name of the method, but that's not conclusive. To test if a method is a getter or setter I'd like check if the only thing which the method does, is that it uses a GETFIELD or SETFIELD opcode on the current instance and nothing else.

UPDATE: One way I found to work is to override the visitField() method as well on my ClassVisitor, not just the visitMethod(), so I store all the field names of the class and check if a method has the name getX() or setX() where X is a field name. This approach would work but it is still limited because what if the user has such a method named like that, but it is not a setter/getter.

Nfff3
  • 321
  • 8
  • 24
  • 3
    A sense a semantic problem. Is `Component.getBounds()` a getter or not? In some implementations, there is a `Rectangle bounds` field, in others, there is `int x, y, width, height;`. But even in the former case, the method will be `return new Rectangle(bounds);` rather than `return bounds;`. So are you looking for methods merely consisting of a `getfield` instruction or are you looking for methods being a Java Beans style getter? – Holger Aug 03 '20 at 11:22
  • @Holger, I am looking for Java Beans style getter, so this is what I have in mind: check name of method if it contains set/get + name of field, check the return type of the method(void if setter, field type if getter), and also check the argument list of the method(nothing for getter, field type for setter), I think this would be enough, but I don't really know how to implement it. – Nfff3 Aug 03 '20 at 15:26
  • 3
    But there is no requirement for Bean getters and setters to match a field name. As with my previous example, having `public Rectangle getBounds()` and `public void setBounds(Rectangle)` is enough to have a `bounds` property. Whether the class uses a single `Rectangle` field or four `int` fields to implement this internally, doesn’t matter. And when it has a single field, why should it matter whether this `private` field has been named `bounds`, `boundsProperty`, `componentBounds`, `theBounds` or `b`? So just check the name and the parameter & return type and forget about fields. – Holger Aug 03 '20 at 15:40
  • @Holger, OK, I will do just that but I still would like to check the body of the method to see if it is a short method or not. I don't want to ignore methods about which I thought were getters/setters and in reality are long, useful methods. But I'm adding my code at the beginning of each method(using the visitor based API of ASM) so I cannot know how long the method is if I am just at the beginning of it... – Nfff3 Aug 03 '20 at 17:59
  • 2
    ASM’s visitor API has no such functionality to query the code size beforehand. You can store the method’s artifacts in a `MethodNode` [like in this answer](https://stackoverflow.com/a/59878665/2711488), to query information that would otherwise only be available after the traversal, before visiting them using the actual method visitor. – Holger Aug 04 '20 at 08:16
  • @Holger, thanks that will do it. From an overhead perspective, the 2 approaches(`MethodNode` vs iterating over the class twice) are the same, right? – Nfff3 Aug 04 '20 at 14:35
  • 1
    There’s no definite answer. A `MethodNode` will need more memory to hold the method’s artifacts, but it’s only for a single method at a time. In contrast, visiting a class twice might repeat some processing of other things than methods. Further, you’d have to remember information from the first pass for the second, for all methods. – Holger Aug 04 '20 at 15:04

0 Answers0