Question

I want to open the Byte code (Java Binaries) generated by Java Compiler using some kind of editor, which allows me to view the byte code (Raw, but human understandable, in the format defined here) & modify things directly in the .class file.

I have tried the javap utility. But through javap, I cannot change my .class File, also it doesn't seems to show the raw byte code

Also, I have seen de-compiler like JD Decompiler which gives me the code from the .class File. But I am not interested in the source code, I want to view the byte code.

Also, I have tried GUI editors called dirtyJOE & JBE. This editor is quite a good one and fulfills half of my purpose. I can see various fields in the .class file and edit my .class file as well. But this also seems to be like a translator which decodes the byte code and show it on the UI for easy understanding. It doesn't shows me the raw byte code.

Is it even possible to go to the raw bytecode?

I might sound stupid, but I wanted to confirm this, to understand the Java Compiler and JVM properly.

Était-ce utile?

La solution

It is possible to dump the raw byte code with javap -v but to get all the information in the class file in a format you can edit I use ASM. The reason you wouldn't use this for editing is;

  • it doesn't allow you to do much that you can't do in Java.
  • it much, much harder to use.
  • you don't get much feed back as to what is wrong if you break it.

Its worth nothing that the byte code is just a compiled for of the Java code which is why they do much the same thing. The JVM is free to optimise it in any number of ways which makes understand the byte code not very useful if you want to understand how the JVM works or the code runs.


Thank you to @Antimony for suggested uses for manually written byte code. While some of them are valid they are either fairly advanced or obscure or have an alternative way of achieving the same thing.

Some ideas for

throw checked exceptions without declaring them,

Thread.currentThread().stop(checkedException);

catch checked exceptions without declaring them,

   if (false) throw new CheckedException();
} catch(CheckedException ce) {

use identifiers invalid in Java

There are so many valid, but not so useful characters to use I would use one of those

if( ⁀ ‿ ⁀ == ⁀ ⁔ ⁀ || ¢ + ¢== ₡)

and

for (char c‮h = 0; c‮h < Character.MAX_VALUE; c‮h++)
    if (Character.isJavaIdentifierPart(c‮h) && !Character.isJavaIdentifierStart(c‮h))
        System.out.printf("%04x <%s>%n", (int) c‮h, "" + c‮h);

is valid code due to an invisible character in the identifier which causes the text to print backwards.

http://vanillajava.blogspot.co.uk/2012/09/hidden-code.html

http://vanillajava.blogspot.co.uk/2012/08/uses-for-special-characters-in-java-code.html

access fields before constructor call

I am pretty sure this causes a VerifyError (or it did when I tried it). Instead you can use

Object o = Unsafe.allocateInstance(clazz); // create without calling a constructor.

call different constructors conditionally

Again I have been able to place code between the object creation and the instance call, but there might be a way to get it to work. In Java you would write

MyClass mc = condition ? new MyClass(a) : new MyClass(a, b);

do exception handling on constructors.

Not sure what you mean here as you can catch or throw exceptions in constructors.

assign final fields more than once or not at all

You could use reflections instead and give final fields their default value. i.e. it not possible for a field to have no value.

have a strictfp constructor with nonstrictfp methods

That is an interesting one, but not one I have ever needed.

use laxer type checking

The byte code does allow different rules for type checking but they are easy to fall foul of with not so helpful VerifyErrors. You could do this but its very hard to get right IMHO.

throw exceptions from static initializer

You can throw unchecked exceptions already, and to throw checked ones you can use the trick above, however I usually wrap with in an AssertionError or the like.

use invokedynamic

You can use MethodHandles but they are rather clunky in Java 7. I hope that in Java 8 they will be more natural to use.

use subroutines

Interesting, I haven't tried this, but I am not sure what advantage they would give over method calls.

use unusual control flow

True, but this is more likely to confuse the JIT optimiser so the code can be slower as a result so may not give you the advantage you might hope for.

use old super call semantics

You could but I am not sure how useful that is.

use thread monitors

You can use

Unsafe.enterMonitor();
Unsafe.exitMonitor();
Unsafe.tryMonitorEnter();

initial values for fields.

I agree the compiler doesn't use these as much as I would expect but then again I am not sure they what difference it would make if it did.

Autres conseils

There are several libraries designed for bytecode manipulation, such as ASM, but I haven't used them so I can't say much about their power or usability.

There are also assemblers, which are designed to convert a human readable form into binary class files (I've even written one myself). As far as I know, there aren't any tools to convert class files into assembly format, but I could write one if you're interested.

For simple modifications, you can also just use a hex editor if you know what you're doing. I've edited classes several times in a hex editor before.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top