How to prevent proguard from removing "module-info.class" from the output jar?
Asked Answered
K

1

7

I'm upgrading a Java desktop application to JDK10 and need to leverage modules to use the javapackager to build a native package.

Everything was working great until I added an obfuscation step using Proguard (6.0.2). Once I enabled obfuscation (using a working proguard configuration file from the < JDK9 project) it works as expected but Proguard removes the module-info.class from the output JAR which prevents javapackager from finding the module.

According to Proguard's documentation for the injars parameter

By default, any non-class files will be copied without changes.

The problem here is that module-info.class is a "class" file (albeit a weird one). The "keep" rules depend on class names so I don't think there is any rule I can use to prevent this removal.

How can I get Proguard to keep the module-info.class file?

Kinky answered 6/5, 2018 at 18:27 Comment(5)
This looks like a useful product. I plan to give it a try as well, assuming that this hitch that you discovered is resolved! I'm curious about what you have tried. Looking at the "Keep Overview" guardsquare.com/en/proguard/manual/usage#keepoverview it seems like a simple -keep should both keep the module-info.class from being either renamed or removed. Can you go into more detail, actually show how you use the -keep option with module-info.class? Good luck on this!Hassiehassin
That's the thing, although the module-info.class ends in .class it's not a class file. And according to the manual the -keep options need to be followed by the class specification guardsquare.com/en/proguard/manual/usage#classspecification. The problem is that the file doesn't hold a class/interface/enum, just the description of the module. From what I've read, the version I used (6.0.2) should already support JDK9, so it would be natural for it to ignore the file but it's not.Kinky
Is the software maker providing responsive support? Also, am wondering if there is some sort of annotation that can be added to module-info to protect it from deletion. I will watch for updates here, and will update myself once I reach this step if I figure anything helpful out.Hassiehassin
Yes, the author was very helpful, check my answer belowKinky
Thanks for follow-up. As for myself, I decided to go with Inno-Setup 5 and forego obfuscation, and am finding that route for packaging is working. (Am packaging resulting file system of JLINK operation on project.)Hassiehassin
K
3

After filing a bug report, Proguard's author confirmed that we need to treat module-info as just another class and add a rule to keep it, like this:

-keep class module-info

and possibly using

-keepattributes Module*

In my case, I actually had tried it before posting the question but it didn't work for me on the project I was using it with (I got a NullPointerException when I tried it, more details in the bug report)

After the author's response, I tried it on a simpler project and the "keep" rule above worked fine so it meant that something specific to my first project was causing the issue.

I worked around the issue in that project for now by using gradle to copy the module-info.class from the unobfuscated jar into the obfuscated one. It's not pretty but it works.

Hope this helps anyone in the same situation.

Kinky answered 26/5, 2018 at 10:6 Comment(5)
I still get an error saying there is a class file incorrectly named nowFourthly
For reason I dont understand this did not work for me when I added the keepattributes like this keepattributes 'Exceptions,InnerClasses,Signature,Deprecated,Module*' but it worked when I added another keepattributes Module* line. I should also note it was written directly in gradle and not in configuration file. Sorry for downvoting the answer, unfortunately I cannot change it anymore.Ingroup
It did not work for us with the given defintion. We're using "-dontwarn module-info" as option now.Railroader
Those 2 options work for me in keeping the module-info classes, however it's not working. It's as if ProGuard is copying the main jar's module-info to the others, since I'm getting this error from jlink: Two versions of module X found. I have multiple jars, each having their own module. Running jar --describe-module --file a.jar shows each non-main jar in ProGuard output matches the main one, but input jars are fine.Datnow
Seems like would be a common problem for anyone using modules. With ProGuard 7 released for Java 14 support, still an issue for us to deal with it some hacky way. I guess I'm going to have to choose "Print mapping" under Obfuscation, and write a script for my build process to parse that mapping and copy over the module-info classes with updated (obfuscated) references to exported packages etc.Datnow

© 2022 - 2024 — McMap. All rights reserved.