tags:

views:

177

answers:

4

Given a Java class file (ClassName.class) with bytecode version X is there a general way to convert this class file from being represented in bytecode version X to being represented in bytecode version Y?

Assumptions:

  • The source code is not available. The class file is the only available representation of the class.
  • The class file is heavily obfuscated, so decompiling the class with say jad or similar program and then recompiling it with "-target ..." does not work.

Updates after initial post:

  • Update #1: Futhermore, assume that bytecode version X and bytecode version Y are sufficiently close so that all instructions used by the class (currently in bytecode version X) also exists in version Y.
+2  A: 

You could use Apache BCEL

The Byte Code Engineering Library is intended to give users a convenient possibility to analyze, create, and manipulate (binary) Java class files

BCEL gives you the possibility of reading in a class file of a given version, manipulating it, generating a new class file stream, and then loading that into the VM using the low-level ClassLoader API. Very fiddly, no doubt, and I doubt this will let you downgrade the version as easily as you could prograde.

skaffman
ASM would be a better option if support is required for more recent features like annotations ( http://asm.ow2.org/ ). Otherwise, this approach should work.
McDowell
Ah, OK. I haven't really been keeping up with this stuff, it scares me.
skaffman
+1  A: 

No. While later versions of Java will be able to execute that bytecode, you can't upgrade it: Later versions of the class files have a different format.

You can't downgrade it either because there is no way to replace the missing bytecodes by other constructs in older versions of Java.

[EDIT] IIRC, Sun added at least a single new bytecode instruction for every major version of Java. This is usually the reason for major Java releases: Changes to the bytecode.

That said, just try your luck and change the major version of the class file and see if your newer VM will load it. I doubt it will work for any complex example but you might be lucky.

Aaron Digulla
Even though a program may or may not exist, in theory it should be possible though. Just like a compiler transforms sourcecode into a bytecode, in theory a compiler could also exists which translates different bytecode versions to eachother.
Toad
reinier: I'm not convinced it's practical. See this document about the Java 6 verifier: https://jdk.dev.java.net/verifier.html Can you build a StackMapTable from bytecode alone?
Aaron Digulla
Aaron: Please see "Update 1". Does that clarification alter your answer?
knorv
@knorv: Not really. What are you up to anyway? Why do you need this?
Aaron Digulla
Aaron: Long story short; I'm stuck with an old version of Java in a production environment.
knorv
Aaron: With regards to "Sun added at least a single new bytecode instruction for every major version of Java" - true, but usually only a subset of all available bytecode instructions are used in a given Java class.
knorv
@knorv: Well ... try to reset the major version and see which exceptions the verifyer throws and chew through them.
Aaron Digulla
Aaron: Yepps, will do :-) Thanks for your answers+comments
knorv
+3  A: 

For downgrading you can have a look at various methods to get Java 5/6 code running in Java 1.3/1.4. See my anwser to related question http://stackoverflow.com/questions/1011706/backport-java-5-6-features-to-java-1-4/1098923#1098923

Peter Kofler
Thanks for a great answer! retrotranslator did the trick!
knorv
A: 

Use retroweaver

Mike B