DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG 
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://nagoya.apache.org/bugzilla/show_bug.cgi?id=15986>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND 
INSERTED IN THE BUG DATABASE.

http://nagoya.apache.org/bugzilla/show_bug.cgi?id=15986

Infinite loop in ToStringBuilder.reflectionToString for inner classes

           Summary: Infinite loop in ToStringBuilder.reflectionToString for
                    inner classes
           Product: Commons
           Version: 1.0.1 Final
          Platform: PC
        OS/Version: Windows NT/2K
            Status: NEW
          Severity: Blocker
          Priority: Other
         Component: Lang
        AssignedTo: [EMAIL PROTECTED]
        ReportedBy: [EMAIL PROTECTED]


ToStringBuilder.reflectionToString() enters an infinite loop when used with the 
following example:

/////////////////////////////
public class Outer {
  Inner inner = new Inner();
  class Inner {
    public String toString() {
      return ToStringBuilder.reflectionToString(this);
    }
  }
  public String toString() {
    return ToStringBuilder.reflectionToString(this);
  }
  public static void main(String[] args) {
    Outer outer = new Outer();
    System.out.println(outer);
  }
}
/////////////////////////////

The reason is that the two classes refer to each other via the explicit field 
inner and the implicit field Outer.this. 

The bug can be resolved by skipping the implicit fields. Is there any good 
reason for printing those anyway?

I am not sure what is the best way to detect if a field is an implicit field. 
But I patched the code myself in a way that seemed to work:

/////////////////////////////
public static String reflectionToString(Object object, ToStringStyle style, 
        boolean outputTransients) {
    if (object == null) {
        throw new IllegalArgumentException("The object must not be null");
    }
    if (style == null) {
        style = getDefaultStyle();
    }
    Field[] fields = object.getClass().getDeclaredFields();
    Field.setAccessible(fields, true);
    ToStringBuilder builder = new ToStringBuilder(object, style);
    for (int i = 0; i < fields.length; ++i) {
        Field f = fields[i];
        if (!f.getName().startsWith("this$")) {
          if (outputTransients || !Modifier.isTransient(f.getModifiers())) {
              if (!Modifier.isStatic(f.getModifiers())) {
                  try {
                      builder.append(f.getName(), f.get(object));
                      
                  } catch (IllegalAccessException ex) {
                      //this can't happen. Would get a Security exception 
instead
                      //throw a runtime exception in case the impossible 
happens.
                      throw new InternalError("Unexpected 
IllegalAccessException");
                  }
              }
          }
        }
    }
    return builder.toString();
}
/////////////////////////////

Notice the extra if statement that tests for field names starting with "this$". 
I don't know if this is guaranteed to work always, though.

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to