diff options
author | Decebal Suiu <decebal.suiu@gmail.com> | 2024-12-23 22:39:37 +0200 |
---|---|---|
committer | Decebal Suiu <decebal.suiu@gmail.com> | 2024-12-23 22:39:37 +0200 |
commit | 1599e856c3a53790503a7c72b7c74001f9eb42d7 (patch) | |
tree | 4bea295501024525e596cc1e5b5d1601a97f3f7a /pf4j/src | |
parent | 1e3010c111e99676b6c78588d922ff2f83b5223b (diff) | |
download | pf4j-1599e856c3a53790503a7c72b7c74001f9eb42d7.tar.gz pf4j-1599e856c3a53790503a7c72b7c74001f9eb42d7.zip |
Add collect class loader test
Diffstat (limited to 'pf4j/src')
-rw-r--r-- | pf4j/src/test/java/org/pf4j/PluginClassLoaderTest.java | 93 |
1 files changed, 71 insertions, 22 deletions
diff --git a/pf4j/src/test/java/org/pf4j/PluginClassLoaderTest.java b/pf4j/src/test/java/org/pf4j/PluginClassLoaderTest.java index b19bd3b..1a24770 100644 --- a/pf4j/src/test/java/org/pf4j/PluginClassLoaderTest.java +++ b/pf4j/src/test/java/org/pf4j/PluginClassLoaderTest.java @@ -21,20 +21,27 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import org.pf4j.processor.LegacyExtensionStorage; +import org.pf4j.test.JavaFileObjectUtils; +import org.pf4j.test.JavaSources; import org.pf4j.test.PluginZip; import org.pf4j.util.FileUtils; +import javax.tools.JavaFileObject; import java.io.File; import java.io.IOException; import java.io.PrintWriter; +import java.lang.ref.WeakReference; import java.net.URISyntaxException; import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.AbstractMap; import java.util.Collections; import java.util.Enumeration; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -58,6 +65,8 @@ class PluginClassLoaderTest { private PluginClassLoader parentLastPluginDependencyClassLoader; private PluginClassLoader parentFirstPluginDependencyClassLoader; + private PluginZip pluginDependencyZip; + @TempDir Path pluginsPath; @@ -65,16 +74,17 @@ class PluginClassLoaderTest { static void setUpGlobal() throws IOException, URISyntaxException { Path parentClassPathBase = Paths.get(PluginClassLoaderTest.class.getClassLoader().getResource(".").toURI()); - File metaInfFile = parentClassPathBase.resolve("META-INF").toFile(); + Path metaInfPath = parentClassPathBase.resolve("META-INF"); + File metaInfFile = metaInfPath.toFile(); if (metaInfFile.mkdir()) { // Only delete the directory if this test created it, guarding for any future usages of the directory. metaInfFile.deleteOnExit(); } - createFile(parentClassPathBase.resolve("META-INF").resolve("file-only-in-parent")); - createFile(parentClassPathBase.resolve("META-INF").resolve("file-in-both-parent-and-dependency-and-plugin")); - createFile(parentClassPathBase.resolve("META-INF").resolve("file-in-both-parent-and-dependency")); - createFile(parentClassPathBase.resolve("META-INF").resolve("file-in-both-parent-and-plugin")); + createFile(metaInfPath.resolve("file-only-in-parent")); + createFile(metaInfPath.resolve("file-in-both-parent-and-dependency-and-plugin")); + createFile(metaInfPath.resolve("file-in-both-parent-and-dependency")); + createFile(metaInfPath.resolve("file-in-both-parent-and-plugin")); createFile(parentClassPathBase.resolve(LegacyExtensionStorage.EXTENSIONS_RESOURCE)); } @@ -93,22 +103,34 @@ class PluginClassLoaderTest { pluginManager = new TestPluginManager(pluginsPath); pluginManagerParentFirst = new TestPluginManager(pluginsPath); - pluginDependencyDescriptor = new DefaultPluginDescriptor(); - pluginDependencyDescriptor.setPluginId("myDependency"); - pluginDependencyDescriptor.setPluginVersion("1.2.3"); - pluginDependencyDescriptor.setPluginDescription("My plugin"); - pluginDependencyDescriptor.setDependencies(""); - pluginDependencyDescriptor.setProvider("Me"); - pluginDependencyDescriptor.setRequires("5.0.0"); + pluginDependencyDescriptor = new DefaultPluginDescriptor() + .setPluginId("myDependency") + .setPluginVersion("1.2.3") + .setPluginDescription("My plugin") + .setDependencies("") + .setProvider("Me") + .setRequires("5.0.0"); + + Map<String, JavaFileObject> generatedClasses = JavaSources.compileAll(JavaSources.GREETING, JavaSources.WHAZZUP_GREETING) + .stream() + .map(javaFileObject -> new AbstractMap.SimpleEntry<>(JavaFileObjectUtils.getClassName(javaFileObject), javaFileObject)) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + Path classesPath = Paths.get("classes"); + Path metaInfPath = classesPath.resolve("META-INF"); + + Path greetingClassPath = classesPath.resolve(JavaSources.GREETING_CLASS_NAME.replace('.', '/') + ".class"); + Path whaszzupGreetingClassPath = classesPath.resolve(JavaSources.WHAZZUP_GREETING_CLASS_NAME.replace('.', '/') + ".class"); Path pluginDependencyPath = pluginsPath.resolve(pluginDependencyDescriptor.getPluginId() + "-" + pluginDependencyDescriptor.getVersion() + ".zip"); - PluginZip pluginDependencyZip = new PluginZip.Builder(pluginDependencyPath, pluginDependencyDescriptor.getPluginId()) + pluginDependencyZip = new PluginZip.Builder(pluginDependencyPath, pluginDependencyDescriptor.getPluginId()) .pluginVersion(pluginDependencyDescriptor.getVersion()) - .addFile(Paths.get("classes/META-INF/dependency-file"), "dependency") - .addFile(Paths.get("classes/META-INF/file-in-both-parent-and-dependency-and-plugin"), "dependency") - .addFile(Paths.get("classes/META-INF/file-in-both-parent-and-dependency"), "dependency") - .addFile(Paths.get("classes/" + LegacyExtensionStorage.EXTENSIONS_RESOURCE), "dependency") + .addFile(metaInfPath.resolve("dependency-file"), "dependency") + .addFile(metaInfPath.resolve("file-in-both-parent-and-dependency-and-plugin"), "dependency") + .addFile(metaInfPath.resolve("file-in-both-parent-and-dependency"), "dependency") + .addFile(classesPath.resolve(LegacyExtensionStorage.EXTENSIONS_RESOURCE), "dependency") + .addFile(greetingClassPath, JavaFileObjectUtils.getAllBytes(generatedClasses.get(JavaSources.GREETING_CLASS_NAME))) + .addFile(whaszzupGreetingClassPath, JavaFileObjectUtils.getAllBytes(generatedClasses.get(JavaSources.WHAZZUP_GREETING_CLASS_NAME))) .build(); FileUtils.expandIfZip(pluginDependencyZip.path()); @@ -121,7 +143,6 @@ class PluginClassLoaderTest { pluginManager.addClassLoader(pluginDependencyDescriptor.getPluginId(), parentLastPluginDependencyClassLoader); pluginManagerParentFirst.addClassLoader(pluginDependencyDescriptor.getPluginId(), parentFirstPluginDependencyClassLoader); - for (String classesDirectory : pluginDependencyClasspath.getClassesDirectories()) { File classesDirectoryFile = pluginDependencyZip.unzippedPath().resolve(classesDirectory).toFile(); parentLastPluginDependencyClassLoader.addFile(classesDirectoryFile); @@ -148,10 +169,10 @@ class PluginClassLoaderTest { Path pluginPath = pluginsPath.resolve(pluginDescriptor.getPluginId() + "-" + pluginDescriptor.getVersion() + ".zip"); PluginZip pluginZip = new PluginZip.Builder(pluginPath, pluginDescriptor.getPluginId()) .pluginVersion(pluginDescriptor.getVersion()) - .addFile(Paths.get("classes/META-INF/plugin-file"), "plugin") - .addFile(Paths.get("classes/META-INF/file-in-both-parent-and-dependency-and-plugin"), "plugin") - .addFile(Paths.get("classes/META-INF/file-in-both-parent-and-plugin"), "plugin") - .addFile(Paths.get("classes/" + LegacyExtensionStorage.EXTENSIONS_RESOURCE), "plugin") + .addFile(metaInfPath.resolve("plugin-file"), "plugin") + .addFile(metaInfPath.resolve("file-in-both-parent-and-dependency-and-plugin"), "plugin") + .addFile(metaInfPath.resolve("file-in-both-parent-and-plugin"), "plugin") + .addFile(classesPath.resolve(LegacyExtensionStorage.EXTENSIONS_RESOURCE), "plugin") .build(); FileUtils.expandIfZip(pluginZip.path()); @@ -347,6 +368,34 @@ class PluginClassLoaderTest { assertTrue(parentLastPluginClassLoader.isClosed()); } + @Test + void collectClassLoader() throws IOException, ClassNotFoundException, InterruptedException { + // Create a new classloader + PluginClassLoader classLoader = new PluginClassLoader(pluginManager, pluginDependencyDescriptor, PluginClassLoaderTest.class.getClassLoader()); + PluginClasspath pluginDependencyClasspath = new DefaultPluginClasspath(); + for (String classesDirectory : pluginDependencyClasspath.getClassesDirectories()) { + File classesDirectoryFile = pluginDependencyZip.unzippedPath().resolve(classesDirectory).toFile(); + classLoader.addFile(classesDirectoryFile); + } + + WeakReference<PluginClassLoader> weakRef = new WeakReference<>(classLoader); + + // Use the classloader + classLoader.loadClass(JavaSources.GREETING_CLASS_NAME); + + // Clear strong reference + classLoader.close(); + classLoader = null; + + // Try to force GC + System.gc(); + System.runFinalization(); + Thread.sleep(100); // Give GC a chance to run + + // Check if ClassLoader was collected + assertNull(weakRef.get(), "ClassLoader was not garbage collected"); + } + private static void assertFirstLine(String expected, URL resource) throws URISyntaxException, IOException { assertNotNull(resource); assertEquals(expected, Files.readAllLines(Paths.get(resource.toURI())).get(0)); |