-
Notifications
You must be signed in to change notification settings - Fork 424
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proguard omits directory entries in output JAR, causing ClassLoader#getResources
to fail
#462
Comments
And this looks very similar to #381. |
It is hard to understand how proguard write data entries to jar file, so I did a very hack fix, maybe helpful: diff --git a/base/src/main/java/proguard/OutputWriter.java b/base/src/main/java/proguard/OutputWriter.java
--- a/base/src/main/java/proguard/OutputWriter.java (revision fbcf41fd670cc6ffdf2db6cfddc07f5a527142e2)
+++ b/base/src/main/java/proguard/OutputWriter.java (date 1738083442253)
@@ -41,6 +41,9 @@
import java.security.*;
import java.security.cert.X509Certificate;
import java.util.*;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+import java.util.jar.JarOutputStream;
/**
@@ -397,6 +400,48 @@
// Close all output entries.
writer.close();
+
+ // read all the entries from the output jar and write them back to the jar
+ Map<String, byte[]> entries = new TreeMap<>();
+ File file = classPath.get(toOutputIndex - 1).getFile();
+ try (JarInputStream jis = new JarInputStream(new FileInputStream(file))) {
+ JarEntry entry;
+ while ((entry = jis.getNextJarEntry()) != null) {
+ if (!entry.isDirectory()) {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1024];
+ int bytesRead;
+ while ((bytesRead = jis.read(buffer)) != -1) {
+ baos.write(buffer, 0, bytesRead);
+ }
+ entries.put(entry.getName(), baos.toByteArray());
+ }
+ }
+ }
+ // add missing directories
+ Set<String> dirs = new HashSet<>();
+ for (String entry : entries.keySet()) {
+ while (entry.contains("/")) {
+ entry = entry.substring(0, entry.lastIndexOf('/'));
+ dirs.add(entry + "/");
+ }
+ }
+ for (String dir : dirs) {
+ if (!entries.containsKey(dir)) {
+ entries.put(dir, null);
+ }
+ }
+
+ // write the entries back to the jar
+ try (JarOutputStream jos = new JarOutputStream(new FileOutputStream(file))) {
+ for (Map.Entry<String, byte[]> entry : entries.entrySet()) {
+ jos.putNextEntry(new JarEntry(entry.getKey()));
+ if (entry.getValue() != null) {
+ jos.write(entry.getValue());
+ }
+ jos.closeEntry();
+ }
+ }
}
catch (IOException ex)
{ It works for me. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
When processing JAR files through Proguard, directory entries in the output JAR are not properly preserved. This results in
ClassLoader#getResources(String)
being unable to locate resources when queried using directory paths.Environment
Proguard 7.6.1, jdk-21, Windows 11.
Steps to Reproduce
Attempt to load resources using:
Expected Behavior
The directory resource URL should be returned when querying existing directory paths.
Actual Behavior
Empty enumeration is returned because the JAR lacks directory entries, even though files exist in those directories.
This breaks resource loading patterns commonly used in Resource discovery mechanisms and Framework classpath scanning implementations.
The text was updated successfully, but these errors were encountered: