convert Class object to bytes
Asked Answered
S

5

30

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!

Spumescent answered 10/1, 2010 at 4:42 Comment(1)
See also #7980633Doubleteam
P
30

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.

Promissory answered 10/1, 2010 at 4:53 Comment(5)
and how to compile the class back on the other side when I receive this message as ByteArrayInputStream?Uplift
Creating classes from bytes is the job of a ClassLoader.Promissory
Hi, if the class is a proxy class and dynamic be generated at runtime, and stored in the memory, how can we save it to a file?Feller
How to do the reverse? that is to convert byte[] to java.lang.Class?Oeildeboeuf
If you want to recreate the class from the buffer, then look into thisChaplain
R
2

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)).

Reimer answered 10/1, 2010 at 4:48 Comment(0)
B
2

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.

Basile answered 10/1, 2010 at 8:57 Comment(0)
T
1

Make use of the ClassFileTransformer.

Tuckie answered 10/1, 2010 at 13:5 Comment(0)
C
0

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.

Chaplain answered 19/2, 2023 at 21:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.