[hibernate-commits] Hibernate SVN: r18689 - core/trunk/annotations/src/main/java/org/hibernate/type.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Thu Feb 4 05:57:53 EST 2010


Author: stliu
Date: 2010-02-04 05:57:52 -0500 (Thu, 04 Feb 2010)
New Revision: 18689

Modified:
   core/trunk/annotations/src/main/java/org/hibernate/type/EnumType.java
Log:
HHH-4317 Memory leak in EnumType class

Modified: core/trunk/annotations/src/main/java/org/hibernate/type/EnumType.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/type/EnumType.java	2010-02-04 00:07:31 UTC (rev 18688)
+++ core/trunk/annotations/src/main/java/org/hibernate/type/EnumType.java	2010-02-04 10:57:52 UTC (rev 18689)
@@ -23,19 +23,14 @@
  */
 package org.hibernate.type;
 
-import java.io.IOException;
-import java.io.ObjectInputStream;
 import java.io.Serializable;
 import java.lang.reflect.Method;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Types;
-import java.util.HashMap;
-import java.util.Map;
 import java.util.Properties;
 
-import org.hibernate.AssertionFailure;
 import org.hibernate.HibernateException;
 import org.hibernate.util.StringHelper;
 import org.hibernate.usertype.EnhancedUserType;
@@ -51,6 +46,7 @@
  * TODO implements readobject/writeobject to recalculate the enumclasses
  * @author Emmanuel Bernard
  */
+ at SuppressWarnings("unchecked")
 public class EnumType implements EnhancedUserType, ParameterizedType, Serializable {
 	/**
 	 * This is the old scheme where logging of parameter bindings and value extractions
@@ -77,21 +73,17 @@
 	public static final String COLUMN = "column";
 	public static final String TYPE = "type";
 
-	private static Map<Class, Object[]> enumValues = new HashMap<Class, Object[]>();
-
 	private Class<? extends Enum> enumClass;
-	private String column;
-	private String table;
+	private transient Object[] enumValues;
 	private String catalog;
 	private String schema;
-	private boolean guessed = false;
 	private int sqlType = Types.INTEGER; //before any guessing
 
 	public int[] sqlTypes() {
 		return new int[]{sqlType};
 	}
 
-	public Class returnedClass() {
+	public Class<? extends Enum> returnedClass() {
 		return enumClass;
 	}
 
@@ -103,6 +95,7 @@
 		return x == null ? 0 : x.hashCode();
 	}
 
+	
 	public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException {
 		Object object = rs.getObject( names[0] );
 		if ( rs.wasNull() ) {
@@ -112,16 +105,15 @@
 			return null;
 		}
 		if ( object instanceof Number ) {
-			Object[] values = enumValues.get( enumClass );
-			if ( values == null ) throw new AssertionFailure( "enumValues not preprocessed: " + enumClass );
+			initEnumValues();
 			int ordinal = ( (Number) object ).intValue();
-			if ( ordinal < 0 || ordinal >= values.length ) {
+			if ( ordinal < 0 || ordinal >= enumValues.length ) {
 				throw new IllegalArgumentException( "Unknown ordinal value for enum " + enumClass + ": " + ordinal );
 			}
 			if ( IS_VALUE_TRACING_ENABLED ) {
 				log().debug( "Returning '{}' as column {}", ordinal, names[0] );
 			}
-			return values[ordinal];
+			return enumValues[ordinal];
 		}
 		else {
 			String name = (String) object;
@@ -146,14 +138,14 @@
 		else {
 			boolean isOrdinal = isOrdinal( sqlType );
 			if ( isOrdinal ) {
-				int ordinal = ( (Enum) value ).ordinal();
+				int ordinal = ( (Enum<?>) value ).ordinal();
 				if ( IS_VALUE_TRACING_ENABLED ) {
 					log().debug( "Binding '{}' to parameter: {}", ordinal, index );
 				}
 				st.setObject( index, Integer.valueOf( ordinal ), sqlType );
 			}
 			else {
-				String enumString = ( (Enum) value ).name();
+				String enumString = ( (Enum<?>) value ).name();
 				if ( IS_VALUE_TRACING_ENABLED ) {
 					log().debug( "Binding '{}' to parameter: {}", enumString, index );
 				}
@@ -210,30 +202,31 @@
 		catch (ClassNotFoundException exception) {
 			throw new HibernateException( "Enum class not found", exception );
 		}
-		//this is threadsafe to do it here, setParameterValues() is called sequencially
-		initEnumValue();
+		// is might be good to call it here, to see a possible error immediately
+		// initEnumValue();
+		
 		//nullify unnullified properties yuck!
 		schema = parameters.getProperty( SCHEMA );
 		if ( "".equals( schema ) ) schema = null;
 		catalog = parameters.getProperty( CATALOG );
 		if ( "".equals( catalog ) ) catalog = null;
-		table = parameters.getProperty( TABLE );
-		column = parameters.getProperty( COLUMN );
+//		table = parameters.getProperty( TABLE );
+//		column = parameters.getProperty( COLUMN );
 		String type = parameters.getProperty( TYPE );
 		if ( type != null ) {
 			sqlType = Integer.decode( type ).intValue();
-			guessed = true;
+//			guessed = true;
 		}
 	}
 
-	private void initEnumValue() {
-		Object[] values = enumValues.get( enumClass );
-		if ( values == null ) {
+	/**
+	 * Lazy init of {@link #enumValues}.
+	 */
+	private void initEnumValues() {
+		if ( enumValues == null ) {
 			try {
-				Method method = null;
-				method = enumClass.getDeclaredMethod( "values", new Class[0] );
-				values = (Object[]) method.invoke( null, new Object[0] );
-				enumValues.put( enumClass, values );
+				Method method = enumClass.getDeclaredMethod( "values" );
+				enumValues = (Object[]) method.invoke( null );
 			}
 			catch (Exception e) {
 				throw new HibernateException( "Error while accessing enum.values(): " + enumClass, e );
@@ -241,11 +234,11 @@
 		}
 	}
 
-	private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
-		//FIXME Hum, I think I break the thread safety here
-		ois.defaultReadObject();
-		initEnumValue();
-	}
+	// is might be good to call initEnumValues() here, to see a possible error immediatelly, otherwise leave it commented
+//	private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
+//		initEnumValues();
+//		ois.defaultReadObject();
+//	}
 
 	public String objectToSQLString(Object value) {
 		boolean isOrdinal = isOrdinal( sqlType );
@@ -272,12 +265,11 @@
 	public Object fromXMLString(String xmlValue) {
 		try {
 			int ordinal = Integer.parseInt( xmlValue );
-			Object[] values = enumValues.get( enumClass );
-			if ( values == null ) throw new AssertionFailure( "enumValues not preprocessed: " + enumClass );
-			if ( ordinal < 0 || ordinal >= values.length ) {
+			initEnumValues();
+			if ( ordinal < 0 || ordinal >= enumValues.length ) {
 				throw new IllegalArgumentException( "Unknown ordinal value for enum " + enumClass + ": " + ordinal );
 			}
-			return values[ordinal];
+			return enumValues[ordinal];
 		}
 		catch(NumberFormatException e) {
 			try {



More information about the hibernate-commits mailing list