Author: stliu
Date: 2010-08-18 06:33:35 -0400 (Wed, 18 Aug 2010)
New Revision: 20159
Modified:
annotations/branches/v3_4_0_GA_CP/src/main/java/org/hibernate/type/EnumType.java
Log:
JBPAPP-4905 HHH-4317 Memory leak in EnumType class
Modified:
annotations/branches/v3_4_0_GA_CP/src/main/java/org/hibernate/type/EnumType.java
===================================================================
---
annotations/branches/v3_4_0_GA_CP/src/main/java/org/hibernate/type/EnumType.java 2010-08-18
10:21:12 UTC (rev 20158)
+++
annotations/branches/v3_4_0_GA_CP/src/main/java/org/hibernate/type/EnumType.java 2010-08-18
10:33:35 UTC (rev 20159)
@@ -1,24 +1,19 @@
//$Id$
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.annotations.common.util.StringHelper;
import org.hibernate.usertype.EnhancedUserType;
import org.hibernate.usertype.ParameterizedType;
import org.hibernate.util.ReflectHelper;
+import org.hibernate.util.StringHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -55,21 +50,20 @@
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 column;
+// private String table;
private String catalog;
private String schema;
- private boolean guessed = false;
+// 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;
}
@@ -90,16 +84,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;
@@ -124,14 +117,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
);
}
@@ -188,30 +181,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 immediatelly
+ // 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 );
@@ -219,11 +213,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 );
@@ -250,12 +244,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 {
Show replies by date