I am attempting to trim my JAR down, but every time I run it after I use ProGuard (5.2.1) it throws the following exception:
Exception in thread "main" java.lang.VerifyError: Inconsistent stackmap frames at branch target 147
Exception Details:
Location:
coursier/Cache$.validateChecksum(Lcoursier/core/Artifact;Ljava/lang/String;Ljava/io/File;Ljava/util/concurrent/ExecutorService;)Lscalaz/EitherT; @147: new
Reason:
Type uninitialized 33 (current frame, stack[0]) is not assignable to 'scalaz/EitherT' (stack map, stack[0])
Current Frame:
bci: @108
flags: { }
locals: { top, top, 'java/lang/String', top, top, top, 'coursier/core/Artifact', 'scala/Option' }
stack: { uninitialized 33, uninitialized 33, integer }
Stackmap Frame:
bci: @147
flags: { }
locals: { top, top, top, top, top, top, top, 'scala/Option' }
stack: { 'scalaz/EitherT', 'scalaz/EitherT' }
Bytecode:
0x0000000: 1904 3a05 2a2b 2db6 00de b601 3112 24bb
0x0000010: 0033 592b b701 00b9 01b8 0300 c000 653a
0x0000020: 06bb 00a9 5919 06b6 012b 2cb9 01b7 0200
0x0000030: 3a07 1907 c100 8d99 002d 1907 c000 8d3a
0x0000040: 0819 08b6 017c c000 723a 09b2 00d8 bb00
0x0000050: 5759 2c19 0619 09b7 0124 1905 b601 a13a
0x0000060: 0aa7 002c b200 cb19 07b6 0150 9900 27b2
0x0000070: 00d8 b200 d6bb 005f 592c 1906 b601 32b7
0x0000080: 0125 b601 9db6 01a4 b601 a23a 0a19 0ab7
0x0000090: 0198 b0bb 0085 5919 07b7 0168 bf
Stackmap Table:
full_frame(@100,{Top,Top,Object[#114],Top,Top,Top,Object[#101],Object[#135]},{Uninitialized[#33],Uninitialized[#33]})
full_frame(@141,{Top,Top,Top,Top,Top,Top,Top,Top,Top,Top,Object[#175]},{Uninitialized[#33],Uninitialized[#33]})
full_frame(@147,{Top,Top,Top,Top,Top,Top,Top,Object[#135]},{Object[#169],Object[#169]})
at com.outr.jefe.repo.Ivy2$Local$.<init>(Ivy2.scala:11)
at com.outr.jefe.repo.Ivy2$Local$.<clinit>(Ivy2.scala)
at com.outr.jefe.runner.Repositories.list$lzycompute(Configuration.scala:45)
at com.outr.jefe.runner.Repositories.list(Configuration.scala:43)
at com.outr.jefe.runner.Runner$.start(Runner.scala:27)
at com.outr.jefe.runner.Runner$.delayedEndpoint$com$outr$jefe$runner$Runner$1(Runner.scala:11)
at com.outr.jefe.runner.Runner$delayedInit$body.apply(Runner.scala:9)
at scala.Function0$class.apply$mcV$sp(Function0.scala:34)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
at scala.App$$anonfun$main$1.apply(App.scala:76)
at scala.App$$anonfun$main$1.apply(App.scala:76)
at scala.collection.immutable.List.foreach(List.scala:381)
at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:35)
at scala.App$class.main(App.scala:76)
at com.outr.jefe.runner.Runner$.main(Runner.scala:9)
at com.outr.jefe.runner.Runner.main(Runner.scala)
This is a Scala project and I'm using the following configuration:
-injars /home/mhicks/projects/open-source/jefe/runner/target/scala-2.11/jefe-runner-assembly-1.0.0.jar
-outjars /home/mhicks/projects/open-source/jefe/output/runner.jar
-libraryjars <java.home>/lib/rt.jar
-libraryjars <java.home>/lib/jce.jar
-dontwarn scala.**
-keepclasseswithmembers public class * {
public static void main(java.lang.String[]);
}
-keep class * implements org.xml.sax.EntityResolver
-keepclassmembers class * {
** MODULE$;
}
-keepclassmembernames class scala.concurrent.forkjoin.ForkJoinPool {
long eventCount;
int workerCounts;
int runControl;
scala.concurrent.forkjoin.ForkJoinPool$WaitQueueNode syncStack;
scala.concurrent.forkjoin.ForkJoinPool$WaitQueueNode spareStack;
}
-keepclassmembernames class scala.concurrent.forkjoin.ForkJoinWorkerThread {
int base;
int sp;
int runState;
}
-keepclassmembernames class scala.concurrent.forkjoin.ForkJoinTask {
int status;
}
-keepclassmembernames class scala.concurrent.forkjoin.LinkedTransferQueue {
scala.concurrent.forkjoin.LinkedTransferQueue$PaddedAtomicReference head;
scala.concurrent.forkjoin.LinkedTransferQueue$PaddedAtomicReference tail;
scala.concurrent.forkjoin.LinkedTransferQueue$PaddedAtomicReference cleanMe;
}
-dontoptimize
-dontobfuscate
-verbose
If I add "-dontshrink" and "-dontpreverify" then everything works, but I don't think ProGuard is doing anything except copying the file at that point.
Bugs: #101
Bugs: #114
Bugs: #135
Bugs: #169
Bugs: #175
Bugs: #33
Thanks for your report. The error suggests that ProGuard has computed and added incorrect preverification information for a method. Would it be possible to attach or mail me the compiled class file coursier/Cache$.class (before and after ProGuard has processed it)?
Eric, I sent you an email at the sourceforge users address. I went ahead and attached them to this ticket as well just in case.
Any updates on this?
ProGuard's preverification step fails to identify a newly created instance of scalaz.EitherT on the stack as uninitialized, after a conditional branch across the initializer (unusual bytecode). A more advanced analyzer on an internal ProGuard branch doesn't have the problem, but backporting it is non-trivial.
For the time being, you may be able to work around it by restructuring your code slightly, or maybe by using a different Scala compiler.