In my bytecode instrumentation project, I stumble frequently on VerifyErrors. However, the default java Verifier gives little information on which instruction resulted in the error (it only gives the method and a small message). Is there any stand-alone bytecode verifier which provides with a little more advanced help in locating the error, at least the precise instruction location? Thank you.
As with any project involving JVM bytecode, I would first check to see whether the BCEL has anything that might be useful for you. Also, perhaps FindBugs may help - though I'm not sure whether it assumes verifiable bytecode to start with or not.
ASM CheckClassAdaptor.verify() gives great feedback: http://asm.ow2.org/
I was also looking for something that would report potential verify errors, but especially IncompatibleClassChangeError
s. I wrote a little test project with one API class and another client class calling API methods, plus a main class to run a verifier; then changed the API, recompiling it but not the client, and checked to see what could be caught. Used -target 7
though no special JDK 7 features for now.
First and most obviously, Class.forName
can find certain errors in the client class's signature, but it does not seem to check method bodies for calls to nonexistent API methods and the like, even if you call getDeclaredMethods
; the errors are reported by the VM only when the problematic line of code is actually run.
JustIce in BCEL 5.2 seems to be easiest;
org.apache.bcel.verifier.Verifier.main(new String[] {clazz});
does the job:
Pass 3a, method number 1 ['public void m()']:
VERIFIED_REJECTED
Instruction invokestatic[184](3) 4 constraint violated:
Referenced method 'x' with expected signature '()V' not found in class 'API'.
....
I tried ASM 4.0, but
org.objectweb.asm.util.CheckClassAdapter.main(new String[] {clazz});
does not work; perhaps it checks the format of methods, but not linkage. Inlining main
and passing checkDataFlow=true
does not help.
Searching, I also found https://kenai.com/hg/maxine~maxine/file/8429d3ebc036/com.oracle.max.vm/test/test/com/sun/max/vm/verifier/CommandLineVerifier.java but I could not find any way to make this work; the accompanying unit test throws a ClassNotFoundException
when run.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With