-addconfigurationdebugging throws NPE
Proguard 7.6.1
Adding -addconfigurationdebugging, throws this NPE:
java.lang.NullPointerException: Cannot invoke "String.replace(char, char)" because "internalClassName" is null at proguard.classfile.util.ClassUtil.externalClassName(ClassUtil.java:282) ~[proguard.jar:7.6.1] at proguard.io.ClassMapDataEntryReplacer.writeClassMap(ClassMapDataEntryReplacer.java:109) ~[proguard.jar:7.6.1] at proguard.io.ClassMapDataEntryReplacer.read(ClassMapDataEntryReplacer.java:75) ~[proguard.jar:7.6.1] at proguard.io.FilteredDataEntryReader.read(FilteredDataEntryReader.java:71) ~[proguard.jar:7.6.1] at proguard.io.FilteredDataEntryReader.read(FilteredDataEntryReader.java:71) ~[proguard.jar:7.6.1] at proguard.io.ExtraDataEntryReader.readExtraEntries(ExtraDataEntryReader.java:150) ~[proguard.jar:7.6.1] at proguard.io.ExtraDataEntryReader.read(ExtraDataEntryReader.java:123) ~[proguard.jar:7.6.1] at proguard.io.RenamedDataEntryReader.read(RenamedDataEntryReader.java:81) ~[proguard.jar:7.6.1] at proguard.io.FilteredDataEntryReader.read(FilteredDataEntryReader.java:71) ~[proguard.jar:7.6.1] at proguard.io.FilteredDataEntryReader.read(FilteredDataEntryReader.java:71) ~[proguard.jar:7.6.1] at proguard.io.JarReader.read(JarReader.java:74) ~[proguard.jar:7.6.1] at proguard.io.DirectorySource.readFiles(DirectorySource.java:55) ~[proguard.jar:7.6.1] at proguard.io.DirectorySource.pumpDataEntries(DirectorySource.java:44) ~[proguard.jar:7.6.1] at proguard.InputReader.readInput(InputReader.java:278) ~[proguard.jar:7.6.1] at proguard.InputReader.readInput(InputReader.java:229) ~[proguard.jar:7.6.1] at proguard.OutputWriter.writeOutput(OutputWriter.java:392) ~[proguard.jar:7.6.1] at proguard.OutputWriter.execute(OutputWriter.java:148) ~[proguard.jar:7.6.1] at proguard.pass.PassRunner.run(PassRunner.java:24) ~[proguard.jar:7.6.1] at proguard.ProGuard.writeOutput(ProGuard.java:586) ~[proguard.jar:7.6.1] at proguard.ProGuard.execute(ProGuard.java:252) ~[proguard.jar:7.6.1] at proguard.ProGuard.main(ProGuard.java:642) [proguard.jar:7.6.1]
Same error with the 7.5.0 version.
This looks like the same issue as #224: the exception comes from the line here where the super class name of a class is null.
It's quite likely due to Java modules. In projects using Java modules, there are classes files called module-info.class. These classes do not have a superclass name like normal class files e.g.
$ javap -c -v -p -cp mod1.jar module-info
Classfile jrt:/jdk.zipfs/module-info.class
Last modified 6 Aug 2021; size 325 bytes
SHA-256 checksum c7b7308ed3e2e734899d18aa45d4e491e4700f51cb601d36749d70efafac37f5
Compiled from "module-info.java"
module jdk.zipfs@17
minor version: 0
major version: 61
flags: (0x8000) ACC_MODULE
this_class: #2 // "module-info"
super_class: #0
interfaces: 0, fields: 0, methods: 0, attributes: 4
Constant pool:
#1 = Utf8 module-info
...
This can be easily reproduced on a sample like this one.
$ bin/proguard.sh -injars mod1.jar -addconfigurationdebugging -outjars out.jar -ignorewarnings -keep class \*
ProGuard, version 7.6.0
....
Warning: -addconfigurationdebugging is enabled; the resulting build will contain obfuscation information.
It should only be used for debugging purposes.
Unexpected error
java.lang.NullPointerException: Cannot invoke "String.replace(char, char)" because "internalClassName" is null
at proguard.classfile.util.ClassUtil.externalClassName(ClassUtil.java:271) ~[proguard.jar:7.6.0]
at proguard.io.ClassMapDataEntryReplacer.writeClassMap(ClassMapDataEntryReplacer.java:109) ~[proguard.jar:7.6.0]
at proguard.io.ClassMapDataEntryReplacer.read(ClassMapDataEntryReplacer.java:75) ~[proguard.jar:7.6.0]
...
You could try using a filter to filter out the module-info files from the input during the addconfiguration build, like:
-injars my.jar(!module-info.class)
Related to modules, they are not fully supported by ProGuard - see #455, #122.
Thanks. Yeah, I actually made my JAR non-modular (removing modular-info.class altogether) because Proguard couldn't support it as per your other bug links, and I noticed this NPE went away.
Any idea why Proguard won't handle module-info.class after all these years? Seems to me like it should be fairly simple (maybe it isn't). It's not a standard class but it is just byte-code.