From e9278288a7e17aa62c58820cfc8a899f4a406b17 Mon Sep 17 00:00:00 2001 From: Sanne Grinovero Date: Thu, 29 Oct 2020 10:09:17 +0000 Subject: [PATCH] HHH-14305 Reduce retained memory consumption of SingleTableEntityPersister --- .../entity/SingleTableEntityPersister.java | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java index 9086a449d2..494ce3f243 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java @@ -28,6 +28,7 @@ import org.hibernate.internal.DynamicFilterAliasGenerator; import org.hibernate.internal.FilterAliasGenerator; import org.hibernate.internal.util.MarkerObject; import org.hibernate.internal.util.collections.ArrayHelper; +import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.mapping.Column; import org.hibernate.mapping.Formula; import org.hibernate.mapping.Join; @@ -89,7 +90,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { private final int[] subclassFormulaTableNumberClosure; // discriminator column - private final Map subclassesByDiscriminatorValue = new HashMap(); + private final Map subclassesByDiscriminatorValue; private final boolean forceDiscriminator; private final String discriminatorColumnName; private final String discriminatorColumnReaders; @@ -106,9 +107,10 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { private final String[][] constraintOrderedKeyColumnNames; //private final Map propertyTableNumbersByName = new HashMap(); - private final Map propertyTableNumbersByNameAndSubclass = new HashMap(); + private final Map propertyTableNumbersByNameAndSubclass; - private final Map sequentialSelectStringsByEntityName = new HashMap(); + //Efficiency note: try to not allocate an HashMap if we're not going to need it. + private final Map sequentialSelectStringsByEntityName; private static final Object NULL_DISCRIMINATOR = new MarkerObject( "" ); private static final Object NOT_NULL_DISCRIMINATOR = new MarkerObject( "" ); @@ -370,6 +372,9 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { ArrayList formulaJoinedNumbers = new ArrayList(); ArrayList propertyJoinNumbers = new ArrayList(); + final HashMap propertyTableNumbersByNameAndSubclassLocal = new HashMap<>(); + final Map subclassesByDiscriminatorValueLocal = new HashMap<>(); + iter = persistentClass.getSubclassPropertyClosureIterator(); while ( iter.hasNext() ) { Property prop = (Property) iter.next(); @@ -377,7 +382,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { propertyJoinNumbers.add( join ); //propertyTableNumbersByName.put( prop.getName(), join ); - propertyTableNumbersByNameAndSubclass.put( + propertyTableNumbersByNameAndSubclassLocal.put( prop.getPersistentClass().getEntityName() + '.' + prop.getName(), join ); @@ -393,6 +398,9 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { } } } + + propertyTableNumbersByNameAndSubclass = CollectionHelper.toSmallMap( propertyTableNumbersByNameAndSubclassLocal ); + subclassColumnTableNumberClosure = ArrayHelper.toIntArray( columnJoinNumbers ); subclassFormulaTableNumberClosure = ArrayHelper.toIntArray( formulaJoinedNumbers ); subclassPropertyTableNumberClosure = ArrayHelper.toIntArray( propertyJoinNumbers ); @@ -401,7 +409,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { subclassClosure = new String[subclassSpan]; subclassClosure[0] = getEntityName(); if ( persistentClass.isPolymorphic() ) { - addSubclassByDiscriminatorValue( discriminatorValue, getEntityName() ); + addSubclassByDiscriminatorValue( subclassesByDiscriminatorValueLocal, discriminatorValue, getEntityName() ); } // SUBCLASSES @@ -412,15 +420,16 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { Subclass sc = (Subclass) iter.next(); subclassClosure[k++] = sc.getEntityName(); if ( sc.isDiscriminatorValueNull() ) { - addSubclassByDiscriminatorValue( NULL_DISCRIMINATOR, sc.getEntityName() ); + addSubclassByDiscriminatorValue( subclassesByDiscriminatorValueLocal, NULL_DISCRIMINATOR, sc.getEntityName() ); } else if ( sc.isDiscriminatorValueNotNull() ) { - addSubclassByDiscriminatorValue( NOT_NULL_DISCRIMINATOR, sc.getEntityName() ); + addSubclassByDiscriminatorValue( subclassesByDiscriminatorValueLocal, NOT_NULL_DISCRIMINATOR, sc.getEntityName() ); } else { try { DiscriminatorType dtype = (DiscriminatorType) discriminatorType; addSubclassByDiscriminatorValue( + subclassesByDiscriminatorValueLocal, dtype.stringToObject( sc.getDiscriminatorValue() ), sc.getEntityName() ); @@ -435,13 +444,16 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { } } + // Don't hold a reference to an empty HashMap: + this.subclassesByDiscriminatorValue = CollectionHelper.toSmallMap( subclassesByDiscriminatorValueLocal ); + initSubclassPropertyAliasesMap( persistentClass ); postConstruct( creationContext.getMetadata() ); } - private void addSubclassByDiscriminatorValue(Object discriminatorValue, String entityName) { + private static void addSubclassByDiscriminatorValue(Map subclassesByDiscriminatorValue, Object discriminatorValue, String entityName) { String mappedEntityName = subclassesByDiscriminatorValue.put( discriminatorValue, entityName ); if ( mappedEntityName != null ) { throw new MappingException(