Explorar el Código

Fix memory leak in SingletonExtensionFactory (#487) (#490)

tags/release-3.7.0
RationalityFrontline hace 2 años
padre
commit
1d58b179ab
No account linked to committer's email address

+ 9
- 4
pf4j/src/main/java/org/pf4j/SingletonExtensionFactory.java Ver fichero

import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.WeakHashMap;


/** /**
* An {@link ExtensionFactory} that always returns a specific instance. * An {@link ExtensionFactory} that always returns a specific instance.


private final List<String> extensionClassNames; private final List<String> extensionClassNames;


private Map<ClassLoader, Map<String, Object>> cache;
private final Map<ClassLoader, Map<String, Object>> cache;


public SingletonExtensionFactory(String... extensionClassNames) {
public SingletonExtensionFactory(PluginManager pluginManager, String... extensionClassNames) {
this.extensionClassNames = Arrays.asList(extensionClassNames); this.extensionClassNames = Arrays.asList(extensionClassNames);


cache = new WeakHashMap<>(); // simple cache implementation
cache = new HashMap<>();

pluginManager.addPluginStateListener(event -> {
if (event.getPluginState() != PluginState.STARTED) {
cache.remove(event.getPlugin().getPluginClassLoader());
}
});
} }


@Override @Override

+ 17
- 3
pf4j/src/test/java/org/pf4j/SingletonExtensionFactoryTest.java Ver fichero

*/ */
package org.pf4j; package org.pf4j;


import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.pf4j.test.FailTestExtension; import org.pf4j.test.FailTestExtension;
import org.pf4j.test.TestExtension; import org.pf4j.test.TestExtension;
*/ */
public class SingletonExtensionFactoryTest { public class SingletonExtensionFactoryTest {


private PluginManager pluginManager;

@BeforeEach
public void setUp() {
pluginManager = new DefaultPluginManager();
}

@AfterEach
public void tearDown() {
pluginManager = null;
}

@Test @Test
public void create() { public void create() {
ExtensionFactory extensionFactory = new SingletonExtensionFactory();
ExtensionFactory extensionFactory = new SingletonExtensionFactory(pluginManager);
Object extensionOne = extensionFactory.create(TestExtension.class); Object extensionOne = extensionFactory.create(TestExtension.class);
Object extensionTwo = extensionFactory.create(TestExtension.class); Object extensionTwo = extensionFactory.create(TestExtension.class);
assertSame(extensionOne, extensionTwo); assertSame(extensionOne, extensionTwo);


@Test @Test
public void createNewEachTime() { public void createNewEachTime() {
ExtensionFactory extensionFactory = new SingletonExtensionFactory(FailTestExtension.class.getName());
ExtensionFactory extensionFactory = new SingletonExtensionFactory(pluginManager, FailTestExtension.class.getName());
Object extensionOne = extensionFactory.create(TestExtension.class); Object extensionOne = extensionFactory.create(TestExtension.class);
Object extensionTwo = extensionFactory.create(TestExtension.class); Object extensionTwo = extensionFactory.create(TestExtension.class);
assertNotSame(extensionOne, extensionTwo); assertNotSame(extensionOne, extensionTwo);
@Test @Test
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void createNewEachTimeFromDifferentClassLoaders() throws Exception { public void createNewEachTimeFromDifferentClassLoaders() throws Exception {
ExtensionFactory extensionFactory = new SingletonExtensionFactory();
ExtensionFactory extensionFactory = new SingletonExtensionFactory(pluginManager);


// Get classpath locations // Get classpath locations
URL[] classpathReferences = getClasspathReferences(); URL[] classpathReferences = getClasspathReferences();

Cargando…
Cancelar
Guardar