Brian Harris
Brian Harris

Reputation: 2795

convert Class object to bytes

If I have a Class instance at runtime, can I get its byte[] representation? The bytes I'm interested in would be in the Class file format, such that they'd be valid input to [ClassLoader.defineClass][3].

[3]: http://java.sun.com/j2se/1.5.0/docs/api/java/lang/ClassLoader.html#defineClass(java.lang.String, byte[], int, int)

EDIT: I've accepted a getResourceAsStream answer, because it's very simple and will work most of the time. ClassFileTransformer seems like a more robust solution because it doesn't require that classes be loaded from .class files; it would handle network-loaded classes for example. There's a few hoops to jump through with that approach, but I'll keep in in mind. Thanks all!

Upvotes: 31

Views: 19218

Answers (5)

user16028444
user16028444

Reputation:

Here's a bit of help,

use


final Class<T> clazz = ...
final byte[] buffer = clazz.getClassLoader().getResourceAsStream(clazz.getName().replace('.', '/').concat(".class"));

to get the compiled byte code of the class.


And use


class SimpleClassLoader extends ClassLoader {

    public Clazz<?> loadFromBuffer(final byte[] buffer) {
        return defineClass(buffer, 0, buffer.length);
    }

    public Object newObjectFromBuffer(final byte[] buffer) {
        return loadFromBuffer(buffer).newInstance();
    }

}

to instantiate an Object or to load the Class back from the buffer.

Upvotes: 0

stacker
stacker

Reputation: 68942

Make use of the ClassFileTransformer.

Upvotes: 1

Alex Miller
Alex Miller

Reputation: 70201

You can usually just load the class as a resource from the Classloader.

Class c = ...
String className = c.getName();
String classAsPath = className.replace('.', '/') + ".class";
InputStream stream = c.getClassLoader().getResourceAsStream(classAsPath);

I would probably recommend using something from Apache commons-io to read the InputStream into a byte[], but IOUtils.toByteArray() should do the trick. Writing that code is really easy to get wrong and/or make slow.

Upvotes: 30

Suraj Chandran
Suraj Chandran

Reputation: 24791

You can try java instrumentation! In particular ClassFileTransformer maybe of interest to you!!

You simply override the transform method (from ClassFileTransformer), and your transform method will be called before each class is loaded. So then you cna do whatever class bytes.

Upvotes: 2

Tom Hawtin - tackline
Tom Hawtin - tackline

Reputation: 147154

In general you can't go back like that. However, for some class loaders you may be able to get the resource file be taking the fully qualified class name, replacing . with / and appending .class (so mypackage.MyClass becomes mypackage/MyClass.class (remember, may be case sensitive)).

Upvotes: 2

Related Questions