From 52b93e873c2081ebd578a0dec26f65fff843c610 Mon Sep 17 00:00:00 2001 From: ceze88 Date: Tue, 23 Jan 2024 19:17:29 +0100 Subject: [PATCH] Fix LinkageError in rare cases --- .../core/dependency/DependencyLoader.java | 47 +++++++++++++++---- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/Core/src/main/java/com/craftaro/core/dependency/DependencyLoader.java b/Core/src/main/java/com/craftaro/core/dependency/DependencyLoader.java index 8f694b87..90ff473c 100644 --- a/Core/src/main/java/com/craftaro/core/dependency/DependencyLoader.java +++ b/Core/src/main/java/com/craftaro/core/dependency/DependencyLoader.java @@ -37,22 +37,14 @@ import java.util.zip.ZipOutputStream; public class DependencyLoader { private static final Logger logger = LoggerFactory.getLogger(DependencyLoader.class); - private static final Set loadedDependencies = new HashSet<>(); - private static LibraryLoader libraryLoader; + private static final LibraryLoader libraryLoader = new LibraryLoader(new File("craftaro")); public static LibraryLoader getLibraryLoader() { return libraryLoader; } - public static void initParentClassLoader(ClassLoader parent) { - libraryLoader = new LibraryLoader(parent, new File("craftaro")); - } - public static void loadDependencies(Set dependencies) { for (Dependency dependency : dependencies) { - if (loadedDependencies.contains(dependency)) { - continue; - } loadDependency(dependency); } } @@ -69,6 +61,11 @@ public class DependencyLoader { File outputFile = new File(libraryLoader.getLibFolder(), dependency.getGroupId().replace(".", File.separator) + File.separator + dependency.getArtifactId().replace(".", File.separator) + File.separator + dependency.getVersion() + File.separator + "raw-" + name + ".jar"); File relocatedFile = new File(outputFile.getParentFile(), name.replace("raw-", "") + ".jar"); if (relocatedFile.exists()) { + //Check if the file is already loaded to the classpath + if (isLoaded(relocatedFile)) { + return; + } + //Load dependency into the classpath loadJarIntoClasspath(relocatedFile, dependency); return; @@ -148,7 +145,11 @@ public class DependencyLoader { } } - libraryLoader.load(new LibraryLoader.Dependency(dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion(), dependency.getRepositoryUrl()), true); + try { + libraryLoader.load(new LibraryLoader.Dependency(dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion(), dependency.getRepositoryUrl()), true); + } catch (InvalidDependencyException e) { + //already loaded + } } catch (Exception e) { logger.error("[CraftaroCore] Failed to load dependency " + file, e); @@ -170,4 +171,30 @@ public class DependencyLoader { } return false; } + + private static boolean isLoaded(File file) { + //Find the first class file in the jar and try Class.forName + try (ZipFile zipFile = new ZipFile(file)) { + Enumeration entries = zipFile.entries(); + while (entries.hasMoreElements()) { + ZipEntry entry = entries.nextElement(); + if (entry.getName().startsWith("META-INF")) { + continue; + } + + if (entry.getName().endsWith(".class")) { + String className = entry.getName().replace("/", ".").replace(".class", ""); + try { + Class.forName(className); + return true; + } catch (Exception | Error e) { + return false; + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return false; + } }