6402254: Revisit ModelMBean DescriptorSupport implementation of equals and hashCode.
Reviewed-by: emcmanus
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/Util.java Mon Jul 28 12:37:52 2008 -0700
+++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/Util.java Tue Jul 29 19:21:59 2008 +0200
@@ -26,6 +26,7 @@
package com.sun.jmx.mbeanserver;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
@@ -113,4 +114,32 @@
public static <T> T cast(Object x) {
return (T) x;
}
+
+ /**
+ * Computes a descriptor hashcode from its names and values.
+ * @param names the sorted array of descriptor names.
+ * @param values the array of descriptor values.
+ * @return a hash code value, as described in {@link #hashCode(Descriptor)}
+ */
+ public static int hashCode(String[] names, Object[] values) {
+ int hash = 0;
+ for (int i = 0; i < names.length; i++) {
+ Object v = values[i];
+ int h;
+ if (v == null) {
+ h = 0;
+ } else if (v instanceof Object[]) {
+ h = Arrays.deepHashCode((Object[]) v);
+ } else if (v.getClass().isArray()) {
+ h = Arrays.deepHashCode(new Object[]{v}) - 31;
+ // hashcode of a list containing just v is
+ // v.hashCode() + 31, see List.hashCode()
+ } else {
+ h = v.hashCode();
+ }
+ hash += names[i].toLowerCase().hashCode() ^ h;
+ }
+ return hash;
+ }
+
}
--- a/jdk/src/share/classes/javax/management/ImmutableDescriptor.java Mon Jul 28 12:37:52 2008 -0700
+++ b/jdk/src/share/classes/javax/management/ImmutableDescriptor.java Tue Jul 29 19:21:59 2008 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright 2004-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2004-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
package javax.management;
+import com.sun.jmx.mbeanserver.Util;
import java.io.InvalidObjectException;
import java.lang.reflect.Array;
import java.util.Arrays;
@@ -362,6 +363,7 @@
*/
// Note: this Javadoc is copied from javax.management.Descriptor
// due to 6369229.
+ @Override
public boolean equals(Object o) {
if (o == this)
return true;
@@ -410,29 +412,15 @@
*/
// Note: this Javadoc is copied from javax.management.Descriptor
// due to 6369229.
+ @Override
public int hashCode() {
if (hashCode == -1) {
- int hash = 0;
- for (int i = 0; i < names.length; i++) {
- Object v = values[i];
- int h;
- if (v == null)
- h = 0;
- else if (v instanceof Object[])
- h = Arrays.deepHashCode((Object[]) v);
- else if (v.getClass().isArray()) {
- h = Arrays.deepHashCode(new Object[] {v}) - 31;
- // hashcode of a list containing just v is
- // v.hashCode() + 31, see List.hashCode()
- } else
- h = v.hashCode();
- hash += names[i].toLowerCase().hashCode() ^ h;
- }
- hashCode = hash;
+ hashCode = Util.hashCode(names, values);
}
return hashCode;
}
+ @Override
public String toString() {
StringBuilder sb = new StringBuilder("{");
for (int i = 0; i < names.length; i++) {
@@ -479,6 +467,7 @@
* If the descriptor construction fails for any reason, this exception will
* be thrown.
*/
+ @Override
public Descriptor clone() {
return this;
}
--- a/jdk/src/share/classes/javax/management/modelmbean/DescriptorSupport.java Mon Jul 28 12:37:52 2008 -0700
+++ b/jdk/src/share/classes/javax/management/modelmbean/DescriptorSupport.java Tue Jul 29 19:21:59 2008 +0200
@@ -33,6 +33,7 @@
import static com.sun.jmx.defaults.JmxProperties.MODELMBEAN_LOGGER;
import static com.sun.jmx.mbeanserver.Util.cast;
import com.sun.jmx.mbeanserver.GetPropertyAction;
+import com.sun.jmx.mbeanserver.Util;
import java.io.IOException;
import java.io.ObjectInputStream;
@@ -774,6 +775,7 @@
* fails for any reason, this exception will be thrown.
*/
+ @Override
public synchronized Object clone() throws RuntimeOperationsException {
if (MODELMBEAN_LOGGER.isLoggable(Level.FINEST)) {
MODELMBEAN_LOGGER.logp(Level.FINEST,
@@ -814,13 +816,16 @@
* otherwise.
*
*/
- // XXXX TODO: This is not very efficient!
// Note: this Javadoc is copied from javax.management.Descriptor
// due to 6369229.
+ @Override
public synchronized boolean equals(Object o) {
if (o == this)
return true;
-
+ if (! (o instanceof Descriptor))
+ return false;
+ if (o instanceof ImmutableDescriptor)
+ return o.equals(this);
return new ImmutableDescriptor(descriptorMap).equals(o);
}
@@ -844,11 +849,16 @@
* @return A hash code value for this object.
*
*/
- // XXXX TODO: This is not very efficient!
// Note: this Javadoc is copied from javax.management.Descriptor
// due to 6369229.
+ @Override
public synchronized int hashCode() {
- return new ImmutableDescriptor(descriptorMap).hashCode();
+ final int size = descriptorMap.size();
+ // descriptorMap is sorted with a comparator that ignores cases.
+ //
+ return Util.hashCode(
+ descriptorMap.keySet().toArray(new String[size]),
+ descriptorMap.values().toArray(new Object[size]));
}
/**
@@ -1278,6 +1288,7 @@
* field Names or field Values. If the descriptor string fails
* for any reason, this exception will be thrown.
*/
+ @Override
public synchronized String toString() {
if (MODELMBEAN_LOGGER.isLoggable(Level.FINEST)) {
MODELMBEAN_LOGGER.logp(Level.FINEST,