Verifying Functional Correctness Properties at the Level of Java Bytecode