diff --git a/src/runtime/java/dev/architectury/transformer/TransformerRuntime.java b/src/runtime/java/dev/architectury/transformer/TransformerRuntime.java index e95ea9d..71ab27b 100644 --- a/src/runtime/java/dev/architectury/transformer/TransformerRuntime.java +++ b/src/runtime/java/dev/architectury/transformer/TransformerRuntime.java @@ -137,7 +137,7 @@ public static void main(String[] args) throws Throwable { } } } - List tmpJars = new ArrayList<>(); + List> tmpJars = new ArrayList<>(); classpathProvider = ReadClasspathProvider.of(ClasspathProvider.fromProperties().filter(path -> { File file = path.toFile().getAbsoluteFile(); for (PathWithTransformersEntry path1 : toTransform) { @@ -152,7 +152,7 @@ public static void main(String[] args) throws Throwable { Map classRedefineCache = new HashMap<>(); DirectoryFileAccess debugOut = debugOuts.get(entry.getPath()); Path tmpJar = Files.createTempFile(null, ".jar"); - tmpJars.add(tmpJar); + tmpJars.add(new AbstractMap.SimpleEntry<>(tmpJar, entry)); Files.deleteIfExists(tmpJar); try (OpenedFileAccess outputInterface = OpenedFileAccess.ofJar(tmpJar)) { try (OpenedFileAccess og = OpenedFileAccess.ofJar(entry.getPath())) { @@ -208,9 +208,10 @@ public static void main(String[] args) throws Throwable { } List cp = new ArrayList<>(Arrays.asList(System.getProperty("java.class.path", "").split(File.pathSeparator))); - for (Path tmpJar : tmpJars) { - cp.add(tmpJar.toAbsolutePath().toString()); + for (Map.Entry tmpJar : tmpJars) { + cp.add(tmpJar.getKey().toAbsolutePath().toString()); } + removeDuplicates(cp, tmpJars); System.setProperty("java.class.path", String.join(File.pathSeparator, cp)); Path mainClassPath = Paths.get(System.getProperty(MAIN_CLASS)); @@ -219,6 +220,57 @@ public static void main(String[] args) throws Throwable { handle.invokeExact((String[]) argsList.toArray(new String[0])); } + private static void removeDuplicates(List cpList, List> tmpJars) throws IOException { + List> tmpModules = new ArrayList<>(); + for (Map.Entry tmpJar : tmpJars) { + try (OpenedFileAccess og = OpenedFileAccess.ofJar(tmpJar.getValue().path)) { + Set modules = new HashSet<>(); + og.handle(path -> { + if (path.endsWith(".class")) { + // Get package name, i.e. "dev/architectury/transformer/TransformerRuntime.class" -> "dev.architectury.transformer" + String packageName = Transform.trimLeadingSlash(path).substring(0, Transform.trimLeadingSlash(path).lastIndexOf('/')).replace('/', '.'); + modules.add(packageName); + } + }); + tmpModules.add(modules); + Logger.debug("Temporary jar [%s] contains packages: %s", tmpJar.getKey(), String.join(", ", modules)); + } + } + + cpList.removeIf(cp -> { + try { + Path cpPath = Paths.get(cp); + if (Files.isDirectory(cpPath)) { + try (OpenedFileAccess ac = OpenedFileAccess.ofDirectory(cpPath)) { + Set modules = new HashSet<>(); + ac.handle(path -> { + String relative = Transform.trimLeadingSlash(cpPath.relativize(Paths.get(path)).toString()); + if (relative.endsWith(".class")) { + // Get package name, i.e. "dev/architectury/transformer/TransformerRuntime.class" -> "dev.architectury.transformer" + String packageName = relative.substring(0, relative.lastIndexOf('/')).replace('/', '.'); + modules.add(packageName); + } + }); + Logger.debug("Classpath entry [%s] contains packages: %s", cp, String.join(", ", modules)); + if (modules.isEmpty()) { + return false; + } + for (Set module : tmpModules) { + if (module.equals(modules)) { + Logger.info("Removing duplicate classpath entry: " + cp); + return true; + } + } + } + } + } catch (Throwable e) { + e.printStackTrace(); + } + + return false; + }); + } + private static List parsePathWithTransformersEntries(String configText) throws IOException { Map> map; try (TransformersReader reader = new TransformersReader(new StringReader(configText))) {