I use the Eclipse debugger on a regular basis and this has always bugged me about the IDE. Step filtering is such an invaluable tool, that way I'm not stepping into classes that does not have source code or I'm simply not interested in. However Eclipse isn't getting it right for most cases. In particular, there are options to "Filter simple getters" and "Filter simple setters".
I might use a getter that just simply returns the value of a member variable.
private String value;
public String getValue()
{
return value;
}
Or perhaps a getter that lazily instantiates an expensive object.
private IObjectFactory instance;
public IObjectFactory getInstance()
{
if (instance == null)
instance = ObjectFactory.createFactory();
return instance;
}
I might use a setter that just sets the value of a member variable.
private String value;
public void setValue(String value)
{
this.value = value;
}
I might want to support fluent syntax.
private String value;
public ObjectFactory setValue(String value)
{
this.value = value;
return this;
}
Or perhaps do some validation or event triggering.
private String user;
public void setUser(String user)
{
if (StringUtils.isBlank(user))
throw ExceptionHelper.argumentNull("user");
this.user = user;
}
private String title;
public void setTitle(String title)
{
if (!StringUtils.equals(this.title, title))
{
this.title= title;
onPropertyChanged("title", title);
}
}
And for every single one of these uses, stepping into code using eclipse steps into these methods...
What does Eclipse consider as a "simple getter" or a "simple setter"?
The filters are definitely enabled:

In case it matters, I'm using Eclipse Kepler build 20130614-0229. I'm using JRE6 to run Eclipse and a Tomcat 7 server hosting a Java 1.4 web app. Although we ultimately target 1.4, it is compiled locally using JDK6 so I don't see that as being a problem. I do have JRebel installed and in use, perhaps the classloader is interfering with the algorithms which determine what is considered "simple"? Combined with the "Step through filters" option enabled, it's stepping through my code perhaps. I'll experiment further after thinking about this.
Ok I think I tracked it down.
Under normal circumstances, a plain getter and plain setter (examples 1 and 3 in the question) will be stepped over if these filters are enabled. If a special class loader such as JRebel which modifies methods to hook into them is installed and in use, it seems to interfere with Eclipse's algorithms which determine if a method is a "simple getter" or "simple setter".
So a getter that might look like this in code:
public String getValue()
{
return this.value;
}
Might be altered to look something like this from the JVM's perspective:
public String getValue()
{
Proxy proxy = getProxy(this);
return (String)proxy.invoke("getValue", new Object[] { });
// this is all just an example,
// it's defintely way more complicated than this
}
This altered code confuses Eclipse into thinking "that's not a simple getter so step into it". It does but the actual source code is my actual simple getter which then confuses me thinking "Why did Eclipse step into this simple getter?"
I ran a very contrived test to try to get the step filtering to work.
import org.apache.commons.lang.StringUtils;
public class Program
{
public static void main(String[] args)
{
User bob = new User("0001", "Bob");
String id = bob.getId(); //stepped over
String name = bob.getName(); //stepped over
IHome home = bob.getHome(); //stepped into
bob.setId("foo"); //stepped into
bob.setName("Bobby"); //stepped over
String asString = bob.setNameFluent("Bobbo").toString(); //stepped into
IHome newHome = Neighborhood.getHome("moo");
bob.setHome(newHome); //stepped into
return;
}
static class User
{
private String id;
private String name;
private IHome home;
public User() { this("0001", null); }
public User(String id, String name) { this.id = id; this.name = name; }
public String getId() // simple
{
return id;
}
public String getName() // simple
{
return name;
}
public IHome getHome() // not simple
{
if (home == null)
home = Neighborhood.getHome(id);
return home;
}
public void setId(String id) // not simple
{
if (StringUtils.isBlank(id))
throw ExceptionHelper.argumentBlank("id");
this.id = id;
}
public void setName(String name) // simple
{
this.name = name;
}
public User setNameFluent(String name) // not simple
{
this.name = name;
return this;
}
public void setHome(IHome home) // not simple
{
if (home != null)
{
this.home = home;
onHomeChanged();
}
}
protected void onHomeChanged()
{
this.id = home.getId();
}
public String toString()
{
return "User { name=" + getName() + ", home=" + getHome() + " }";
}
}
static interface IHome
{
String getId();
String getLocation();
}
static class Neighborhood
{
public static IHome getHome(String id)
{
return new Home(id);
}
static class Home implements IHome
{
private String id;
public Home(String id) { this.id = id; }
public String getId() { return id; }
public String getLocation() { return "Home" + id; }
public String toString() { return "Home: " + getLocation(); }
}
}
static class ExceptionHelper
{
public static IllegalArgumentException argumentBlank(String name)
{
return new IllegalArgumentException("Argument " + name + " must not be blank");
}
}
}
With the default configuration (JDK6 without JRebel), the step filtering appeared to work. Trying to step into the simple methods actually stepped over them. After enabling JRebel and stepping through the code again, it stepped into all the methods. And it doesn't matter if "Step through filters" is enabled or not.
tldr;
By using JRebel, the magic that it does confused Eclipse making simple getters and simple setters look more complicated than they originally are. Disabling JRebel will cause the filters to work as intended.
Here is a page on Eclipse's website, which describes the two options in a little more detail
Filter simple getters:
This option controls if simple Java bean-style getters should always be filtered or not while stepping
Filter simple setters:
This option controls if simple Java bean-style setters should always be filtered or not while stepping
From the sounds of it, examples 1 and 3 that you give do appear to be what they mean here. Not sure why you're seeing the behavior that you are though.
EDIT: Looks like the original poster found the issue; something about JRebel overcomplicating the methods.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With