JDK-6493913 : OpenMBeanInfoSupport.equals violates parent's contract
  • Type: Bug
  • Component: core-svc
  • Sub-Component: javax.management
  • Affected Version: 6
  • Priority: P5
  • Status: Closed
  • Resolution: Won't Fix
  • OS: generic
  • CPU: generic
  • Submitted: 2006-11-15
  • Updated: 2024-07-05
  • Resolved: 2024-07-05
Related Reports
Relates :  
Relates :  
Description
The class OpenMBeanInfoSupport  is a subclass of MBeanInfo  and overrides its equals method. In addition to the requirements of MBeanInfo.equals, it requires that its argument be an instance of OpenMBeanInfo. This means that this method violates the symmetry property guaranteed by the contract for Object.equals. If I have an object mbeanInfo of class MBeanInfo and an object openMBeanInfo  of class OpenMBeanInfoSupport, then mbeanInfo.equals(openMBeanInfo) might be true while openMBeanInfo.equals(mbeanInfo) is false. Similar remarks apply to OpenMBeanAttributeInfoSupport etc.

Comments
No known impact, problem is somewhat theoretical. Closing as will not fix at this point.
05-07-2024

should be fixed together with 7148504.
10-09-2013

Need to figure out a right solution.
02-09-2013

Yes to modify MBeanInfo.equals may be a simple solution to fix the bug, but if tomorrow a user adds a new sub-class named TotoMbean, and he wants to implement TotoMBean.equals to return false if an argument is not a TotoMBean instance, then he has to ask modifying the MBeanInfo.equals. And more, same issue for OpenMBeanAttributeInfoSupport.equals OpenMBeanConstructorInfoSupport.equals OpenMBeanOperationInfoSupport.equals OpenMBeanParameterInfoSupport.equals So we have to do same modifications for the super class of these classes. Need more thinking?
22-08-2013

I believe that however this bug is fixed, it will require an update of the spec. One simple fix could be to modify OpenMBeanInfoSupport.equals() - and replace: // if obj is null, return false // if (obj == null) { return false; } // if obj is not a OpenMBeanInfo, return false // OpenMBeanInfo other; try { other = (OpenMBeanInfo) obj; } catch (ClassCastException e) { return false; } with: // if obj is not a OpenMBeanInfo, return MBeanInfo.equals(obj) // OpenMBeanInfo other; if (obj instanceof OpenMBeanInfo) { other = (OpenMBeanInfo) obj; } else if (obj instanceof MBeanInfo) { return super.equals(obj); } else { return null; } This would mean that: if we compare 2 instances of OpenMBeanInfoSupport, the behavior is unchanged - we have the 'old' implementation of OMBIS.equals() if we compare 1 instance of OpenMBeanInfoSupport with one instance of MBeanInfo - then we use MBeanInfo.equals() so the order in which we compare (i1.equals(i2) or i2.equals(i1)) is irrelevant: both will return the same result. There are only two concrete subclasses of MBeanInfo in the JDK, OpenMBeanInfoSupport and ModelMBeanInfoSupport, and ModelMBeanInfoSupport does not redefine equal, so the above would work also when the other instance is an instance of ModelMBeanInfoSupport. However this would require a (small) spec update. An alternative fix, as Shanliang noted - could be to remove the equals() implementation and hashCode implementation from OpenMBeanInfoSupport, and rely on the super class implementation of these methods. This however (I think) would only work if MBeanInfo were also using 'sameArrayContents()' rather than plain 'Arrays.equals()' when comparing arrays of attributes etc... So that would imply modifying MBeanInfo.equals so that two arrays with same elements in different orders are considered equals. (which would also impact ModelMBeanInfoSupport, and might also require a precision in the spec). The impact on the spec/behavior of comparing to OpenMBeanInfoSupport might be greater. In any case, modifying the behavior of OpenMBeanInfoSupport.equals is a spec change, and removing OpenMBeanInfoSupport.equals is also a spec change. There are good chances that any of these two alternative fix would require a modification of the JCK, so this is probably only doable in a major version of the JDK, and with an update of JSR 3. As a second thought - modifying OpenMBeanInfoSupport.equals() as suggested in the former solution above would also force us to remove OpenMBeanInfoSupport's implementation of hashCode(), because two objects for which equals() return true must have the same hashCode. So it seems that the solution that would make the least changes in behavior would be to modify MBeanInfo.equals instead, and make it return false if the object passed as parameter is an instance of OpenMBeanInfoSupport. In summary - in this third branch of the alternative - we would: * Leave OpenMBeanInfoSupport unchanged * Add the following statement in MBeanInfo.equals: // preserve symetry with OpenMBeanInfoSupport's implementation of equals if (obj instanceof OpenMBeanInfoSupport && !(this instanceof OpenMBeanInfo)) return false; This is ugly - but it maybe our best alternative to preserve existing behavior as much as possible without violating equals and hashCode specifications.
22-08-2013

MBeanInfo.equals compares the variables "description" and the "descriptor", but OpenMBeanInfo.equals ignore these 2 variables. After fixing the original issue in this bug: to require the argument as a MBeanInfo instance instead of OpenMBeanInfo, we will have a new problem: openMBeanInfo.equals(mbeanInfo) might be true while mbeanInfo.equals(openMBeanInfo) is false. A simple fix is not to override the method equals in OpenMBeanInfo, this needs to modify the spec, and risk to have a compatibility problem.
22-08-2013

This is not JSR-255 related.
31-07-2013

EVALUATION There is no longer any real difference between an OpenMBeanAttributeInfoSupport (e.g.) and an MBeanAttributeInfo, since the information that used to be exclusive to the former (OpenType, defaultValue, minValue, maxValue, legalValues) is now present in its Descriptor. An OpenMBeanAttributeInfoSupport should compare equal to an MBeanAttributeInfo that has the same Descriptor contents. This requires a minor specification change.
15-11-2006