Skip to content

Commit

Permalink
[Blazebit#1805] Add logic to EntityViewManager and ProxyFactory to ma…
Browse files Browse the repository at this point in the history
…intain evm references in proxies
  • Loading branch information
Mobe91 committed Sep 29, 2023
1 parent a9b1b6e commit c90f2bb
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,11 @@ public class EntityViewManagerProducer {
evm = config.createEntityViewManager(criteriaBuilderFactory);
}
@PreDestroy
public void closeEvm() {
evm.close();
}
@Produces
@ApplicationScoped
public EntityViewManager createEntityViewManager() {
Expand Down Expand Up @@ -377,6 +382,11 @@ public class EntityViewManagerProducer {
evm = config.createEntityViewManager(criteriaBuilderFactory);
}
@PreDestroy
public void closeEvm() {
evm.close();
}
@Produces
@ApplicationScoped
public EntityViewManager createEntityViewManager() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -502,4 +502,10 @@ public interface EntityViewManager extends ServiceProvider {
* @since 1.2.0
*/
public <T, Q extends FullQueryBuilder<T, Q>> Q applySetting(EntityViewSetting<T, Q> setting, CriteriaBuilder<?> criteriaBuilder, String entityViewRoot);

/**
* Closes this {@link EntityViewManager} and frees resources. The entity view manager will not be usable
* anymore after this method has been invoked.
*/
public void close();
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public class SerializableEntityViewManager implements EntityViewManager, Seriali

public static final String EVM_FIELD_NAME = "ENTITY_VIEW_MANAGER";
public static final String SERIALIZABLE_EVM_FIELD_NAME = "SERIALIZABLE_ENTITY_VIEW_MANAGER";
public static final String SERIALIZABLE_EVM_DELEGATE_FIELD_NAME = "evm";

private final Class<?> entityViewClass;
private transient volatile EntityViewManager evm;
Expand Down Expand Up @@ -275,4 +276,9 @@ public <T, Q extends FullQueryBuilder<T, Q>> Q applySetting(EntityViewSetting<T,
public <T> T getService(Class<T> serviceClass) {
return getEvm().getService(serviceClass);
}

@Override
public void close() {
getEvm().close();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1450,6 +1450,11 @@ public EntityViewManager getSerializableDelegate(Class<?> entityViewClass) {
return serializableDelegates.get(proxyFactory.getProxy(this, metamodel.managedViewOrError(entityViewClass)));
}

@Override
public void close() {
proxyFactory.clear();
}

/**
* @author Christian Beikov
* @since 1.2.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1011,6 +1011,8 @@ private <T> Class<? extends T> defineOrGetClass(Class<?> clazz, Class<?> neighbo
}

private <T> Class<? extends T> defineOrGetClass(EntityViewManager entityViewManager, boolean unsafe, Class<?> clazz, Class<?> neighbourClazz, CtClass cc) throws IOException, IllegalAccessException, NoSuchFieldException, CannotCompileException {
Class<? extends T> c;
boolean newlyDefined = false;
try {
// Ask the package opener to allow deep access, otherwise defining the class will fail
if (clazz.getPackage() != null) {
Expand All @@ -1021,13 +1023,8 @@ private <T> Class<? extends T> defineOrGetClass(EntityViewManager entityViewMana
cc.writeFile(DEBUG_DUMP_DIRECTORY.toString());
}

Class<? extends T> c = (Class<? extends T>) UnsafeHelper.define(cc.getName(), cc.toBytecode(), neighbourClazz);

if (entityViewManager != null) {
c.getField(SerializableEntityViewManager.EVM_FIELD_NAME).set(null, entityViewManager);
}

return c;
c = (Class<? extends T>) UnsafeHelper.define(cc.getName(), cc.toBytecode(), neighbourClazz);
newlyDefined = true;
} catch (CannotCompileException | LinkageError ex) {
// If there are multiple proxy factories for the same class loader
// we could end up in defining a class multiple times, so we check if the classloader
Expand All @@ -1037,7 +1034,7 @@ private <T> Class<? extends T> defineOrGetClass(EntityViewManager entityViewMana
|| ex.getCause() instanceof InvocationTargetException && ex.getCause().getCause() instanceof LinkageError && (error = (LinkageError) ex.getCause().getCause()) != null
|| ex.getCause() instanceof LinkageError && (error = (LinkageError) ex.getCause()) != null) {
try {
return (Class<? extends T>) pool.getClassLoader().loadClass(cc.getName());
c = (Class<? extends T>) pool.getClassLoader().loadClass(cc.getName());
} catch (ClassNotFoundException cnfe) {
// Something we can't handle happened
throw error;
Expand All @@ -1049,12 +1046,33 @@ private <T> Class<? extends T> defineOrGetClass(EntityViewManager entityViewMana
// With Java 9 it's actually the case that Javassist doesn't throw the LinkageError but instead tries to define the class differently
// Too bad that this different path lead to a NullPointerException
try {
return (Class<? extends T>) pool.getClassLoader().loadClass(cc.getName());
c = (Class<? extends T>) pool.getClassLoader().loadClass(cc.getName());
} catch (ClassNotFoundException cnfe) {
// Something we can't handle happened
throw ex;
}
}
if (entityViewManager != null) {
updateEvmReferences(c, entityViewManager, !newlyDefined);
}
return c;
}

private void updateEvmReferences(Class<?> entityViewClass, EntityViewManager evm, boolean updateSerializableEvmDelegate) {
try {
entityViewClass.getField(SerializableEntityViewManager.EVM_FIELD_NAME).set(null, evm);
if (updateSerializableEvmDelegate) {
SerializableEntityViewManager serializableEvm =
(SerializableEntityViewManager) entityViewClass.getField(
SerializableEntityViewManager.SERIALIZABLE_EVM_FIELD_NAME).get(null);
Field serializableEvmDelegateField = SerializableEntityViewManager.class.getDeclaredField(
SerializableEntityViewManager.SERIALIZABLE_EVM_DELEGATE_FIELD_NAME);
serializableEvmDelegateField.setAccessible(true);
serializableEvmDelegateField.set(serializableEvm, evm);
}
} catch (IllegalAccessException | NoSuchFieldException e) {
throw new RuntimeException(e);
}
}

private boolean shouldAddDefaultConstructor(boolean hasEmptyConstructor, boolean addedReferenceConstructor, CtField[] attributeFields) {
Expand Down Expand Up @@ -3489,4 +3507,14 @@ private String getGenericSignature(MethodAttribute<?, ?> attribute, CtField attr

return sb.toString();
}

public void clear() {
baseClasses.clear();
for (Class<?> proxyClass : proxyClasses.values()) {
updateEvmReferences(proxyClass, null, true);
}
proxyClasses.clear();
unsafeProxyClasses.clear();
proxyClassesToViewClasses.clear();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -542,5 +542,10 @@ public <T, Q extends FullQueryBuilder<T, Q>> Q applySetting(EntityViewSetting<T,
public <T> T getService(Class<T> serviceClass) {
return entityViewManager.get().getService(serviceClass);
}

@Override
public void close() {
entityViewManager.get().close();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -539,5 +539,10 @@ public <T, Q extends FullQueryBuilder<T, Q>> Q applySetting(EntityViewSetting<T,
public <T> T getService(Class<T> serviceClass) {
return entityViewManager.get().getService(serviceClass);
}

@Override
public void close() {
entityViewManager.get().close();
}
}
}

0 comments on commit c90f2bb

Please sign in to comment.