ProGuard: 6.0.2 (however, fails also with previous versions)
Java: jdk1.8.0_162 (x64)
Platform: Windows 10
The following class cannot be loaded after obfuscation:
package test;
import java.io.IOException;
public class Problematic
{
public static interface Runner
{
public void run() throws IOException;
}
public static void retry(int a, long b, Runner r) throws IOException
{
while (true)
{
try
{
r.run();
return;
} catch (IOException ex)
{
if (a <= 0)
throw ex;
}
if (b > 0)
{
try
{
Thread.sleep(b);
} catch (InterruptedException e)
{
}
}
a--;
}
}
}
=========================== Invoked by:
package test;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
try
{
Problematic.retry(1, 2000, new Problematic.Runner()
{
@Override
public void run() throws IOException
{
throw new IOException();
}
});
} catch (IOException ex)
{
System.out.println(ex);
}
}
public static void main2(String[] args) {
try
{
Problematic.retry(1, 2000, new Problematic.Runner()
{
@Override
public void run() throws IOException
{
throw new IOException();
}
});
} catch (IOException ex)
{
System.out.println(ex);
}
}
}
============================ ProGuard/ANT:
<proguard>
-injars '${dir.deploy}/jar/demo.jar'
-libraryjars '${rt.jar}'
-outjars '${dir.deploy}/jar/demo-pro.jar'
-keep public class test.Main {
public static void main(java.lang.String[]);
public static void main2(java.lang.String[]);
}
</proguard>
===== Error when executing code:
java.lang.VerifyError: Inconsistent stackmap frames at branch target 14
[java] Exception Details:
[java] Location:
[java] test/c.a(IJLtest/d;)V @14: ldc2_w
[java] Reason:
[java] Type 'java/io/IOException' (current frame, locals[1]) is not assignable to long (stack map, locals[1])
[java] Current Frame:
[java] bci: @9
[java] flags: { }
[java] locals: { integer, 'java/io/IOException', top, 'test/d' }
[java] stack: { integer }
[java] Stackmap Frame:
[java] bci: @14
[java] flags: { }
[java] locals: { integer, long, long_2nd, 'test/d' }
[java] stack: { }
[java] Bytecode:
[java] 0x0000000: 2db9 000a 0100 b14c 1a9d 0005 2bbf 1400
[java] 0x0000010: 0709 949e 000d 1400 07b8 0009 a700 0457
[java] 0x0000020: 8400 ffa7 ffdd
[java] Exception Handler Table:
[java] bci [0, 6] => handler: 7
[java] bci [22, 28] => handler: 31
[java] Stackmap Table:
[java] same_frame(@0)
[java] same_locals_1_stack_item_frame(@7,Object[#1])
[java] same_frame(@14)
[java] same_locals_1_stack_item_frame(@31,Object[#2])
[java] same_frame(@32)
===== Complete minimal test case (incl. jar files) in attachment
Thank you!
Thanks for your detailed report. I can reproduce the issue and I'll see how we can solve it. For the time being, you can work around it with
Hi Eric, I can confirm that this workaround works. Thank you for this very useful software.
Note to other people who may be worried about VerifyErrors at runtime: we currenly rely on a custom Ant Task that loads+resolves each obfuscated class. This way, it is possible to determine at build time whether the StackMap frames will be accepted by the JDK verifier. I cannot share that code, but it should be pretty easy to implement.
The bug has now been solved for the upcoming ProGuard update 6.0.3.